Overview
ETH Balance
0 ETH
ETH Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 20,899 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Fulfill Order | 17362404 | 623 days ago | IN | 0.0002 ETH | 0.0000025 | ||||
Fulfill Order | 17357431 | 623 days ago | IN | 0.0001 ETH | 0.00000272 | ||||
Fulfill Order | 17357052 | 623 days ago | IN | 0.0001 ETH | 0.00000264 | ||||
Fulfill Order | 17356412 | 623 days ago | IN | 0.0001 ETH | 0.00000278 | ||||
Fulfill Order | 17354893 | 623 days ago | IN | 0.0001 ETH | 0.00000269 | ||||
Fulfill Order | 17354103 | 623 days ago | IN | 0.0001 ETH | 0.0000027 | ||||
Fulfill Order | 17329808 | 623 days ago | IN | 0.0001 ETH | 0.00000235 | ||||
Fulfill Order | 17329787 | 623 days ago | IN | 0.0001 ETH | 0.00000279 | ||||
Fulfill Order | 17328602 | 623 days ago | IN | 0.0001 ETH | 0.00000262 | ||||
Fulfill Order | 17327905 | 623 days ago | IN | 0.0001 ETH | 0.00000262 | ||||
Fulfill Order | 17327796 | 623 days ago | IN | 0.0001 ETH | 0.00000262 | ||||
Fulfill Order | 17326658 | 623 days ago | IN | 0.0001 ETH | 0.00000258 | ||||
Fulfill Order | 17325593 | 623 days ago | IN | 0.0001 ETH | 0.00000254 | ||||
Fulfill Order | 17323411 | 623 days ago | IN | 0.0001 ETH | 0.00000259 | ||||
Fulfill Order | 17319445 | 623 days ago | IN | 0.0001 ETH | 0.00000195 | ||||
Fulfill Order | 17318074 | 623 days ago | IN | 0.0001 ETH | 0.00000195 | ||||
Fulfill Order | 17315517 | 623 days ago | IN | 0.00023 ETH | 0.00000237 | ||||
Fulfill Order | 17313018 | 623 days ago | IN | 0.001 ETH | 0.00000228 | ||||
Fulfill Order | 17312830 | 623 days ago | IN | 0.0001 ETH | 0.00000228 | ||||
Fulfill Order | 17311209 | 623 days ago | IN | 0.0001 ETH | 0.00000229 | ||||
Fulfill Order | 17308968 | 623 days ago | IN | 0.0001 ETH | 0.00000225 | ||||
Fulfill Order | 17307641 | 623 days ago | IN | 0.00011 ETH | 0.0000017 | ||||
Fulfill Order | 17307524 | 623 days ago | IN | 0.0001 ETH | 0.00000191 | ||||
Fulfill Order | 17304695 | 623 days ago | IN | 0.0001 ETH | 0.00000227 | ||||
Fulfill Order | 17304160 | 623 days ago | IN | 0.0001 ETH | 0.00000227 |
Latest 25 internal transactions (View All)
Advanced mode:
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
17362404 | 623 days ago | 0.0000002 ETH | ||||
17362404 | 623 days ago | 0.0001948 ETH | ||||
17362404 | 623 days ago | 0.000005 ETH | ||||
17357431 | 623 days ago | 0.0000009 ETH | ||||
17357431 | 623 days ago | 0.0000966 ETH | ||||
17357431 | 623 days ago | 0.0000025 ETH | ||||
17357052 | 623 days ago | 0.000015 ETH | ||||
17357052 | 623 days ago | 0.0000825 ETH | ||||
17357052 | 623 days ago | 0.0000025 ETH | ||||
17356412 | 623 days ago | 0.000015 ETH | ||||
17356412 | 623 days ago | 0.0000825 ETH | ||||
17356412 | 623 days ago | 0.0000025 ETH | ||||
17354893 | 623 days ago | 0.0000009 ETH | ||||
17354893 | 623 days ago | 0.0000966 ETH | ||||
17354893 | 623 days ago | 0.0000025 ETH | ||||
17354103 | 623 days ago | 0.0000001 ETH | ||||
17354103 | 623 days ago | 0.0000974 ETH | ||||
17354103 | 623 days ago | 0.0000025 ETH | ||||
17329808 | 623 days ago | 0.0000025 ETH | ||||
17329808 | 623 days ago | 0.000095 ETH | ||||
17329808 | 623 days ago | 0.0000025 ETH | ||||
17329787 | 623 days ago | 0.000001 ETH | ||||
17329787 | 623 days ago | 0.0000965 ETH | ||||
17329787 | 623 days ago | 0.0000025 ETH | ||||
17328602 | 623 days ago | 0.000001 ETH |
Loading...
Loading
Contract Name:
Seaport
Compiler Version
v0.8.14+commit.80d49f37
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity >=0.8.13; import { Consideration } from "./Consideration.sol"; /** * @title Seaport * @custom:version 1.1 * @author 0age (0age.eth) * @custom:coauthor d1ll0n (d1ll0n.eth) * @custom:coauthor transmissions11 (t11s.eth) * @custom:contributor Kartik (slokh.eth) * @custom:contributor LeFevre (lefevre.eth) * @custom:contributor Joseph Schiarizzi (CupOJoseph.eth) * @custom:contributor Aspyn Palatnick (stuckinaboot.eth) * @custom:contributor James Wenzel (emo.eth) * @custom:contributor Stephan Min (stephanm.eth) * @custom:contributor Ryan Ghods (ralxz.eth) * @custom:contributor hack3r-0m (hack3r-0m.eth) * @custom:contributor Diego Estevez (antidiego.eth) * @custom:contributor Chomtana (chomtana.eth) * @custom:contributor Saw-mon and Natalie (sawmonandnatalie.eth) * @custom:contributor 0xBeans (0xBeans.eth) * @custom:contributor 0x4non (punkdev.eth) * @custom:contributor Laurence E. Day (norsefire.eth) * @custom:contributor vectorized.eth (vectorized.eth) * @custom:contributor karmacoma (karmacoma.eth) * @custom:contributor horsefacts (horsefacts.eth) * @custom:contributor UncarvedBlock (uncarvedblock.eth) * @custom:contributor Zoraiz Mahmood (zorz.eth) * @custom:contributor William Poulin (wpoulin.eth) * @custom:contributor Rajiv Patel-O'Connor (rajivpoc.eth) * @custom:contributor tserg (tserg.eth) * @custom:contributor cygaar (cygaar.eth) * @custom:contributor Meta0xNull (meta0xnull.eth) * @custom:contributor gpersoon (gpersoon.eth) * @custom:contributor Matt Solomon (msolomon.eth) * @custom:contributor Weikang Song (weikangs.eth) * @custom:contributor zer0dot (zer0dot.eth) * @custom:contributor Mudit Gupta (mudit.eth) * @custom:contributor leonardoalt (leoalt.eth) * @custom:contributor cmichel (cmichel.eth) * @custom:contributor PraneshASP (pranesh.eth) * @custom:contributor JasperAlexander (jasperalexander.eth) * @custom:contributor Ellahi (ellahi.eth) * @custom:contributor zaz (1zaz1.eth) * @custom:contributor berndartmueller (berndartmueller.eth) * @custom:contributor dmfxyz (dmfxyz.eth) * @custom:contributor daltoncoder (dontkillrobots.eth) * @custom:contributor 0xf4ce (0xf4ce.eth) * @custom:contributor phaze (phaze.eth) * @custom:contributor hrkrshnn (hrkrshnn.eth) * @custom:contributor axic (axic.eth) * @custom:contributor leastwood (leastwood.eth) * @custom:contributor 0xsanson (sanson.eth) * @custom:contributor blockdev (blockd3v.eth) * @custom:contributor fiveoutofnine (fiveoutofnine.eth) * @custom:contributor shuklaayush (shuklaayush.eth) * @custom:contributor 0xPatissier * @custom:contributor pcaversaccio * @custom:contributor David Eiber * @custom:contributor csanuragjain * @custom:contributor sach1r0 * @custom:contributor twojoy0 * @custom:contributor ori_dabush * @custom:contributor Daniel Gelfand * @custom:contributor okkothejawa * @custom:contributor FlameHorizon * @custom:contributor vdrg * @custom:contributor dmitriia * @custom:contributor bokeh-eth * @custom:contributor asutorufos * @custom:contributor rfart(rfa) * @custom:contributor Riley Holterhus * @custom:contributor big-tech-sux * @notice Seaport is a generalized ETH/ERC20/ERC721/ERC1155 marketplace. It * minimizes external calls to the greatest extent possible and provides * lightweight methods for common routes as well as more flexible * methods for composing advanced orders or groups of orders. Each order * contains an arbitrary number of items that may be spent (the "offer") * along with an arbitrary number of items that must be received back by * the indicated recipients (the "consideration"). */ contract Seaport is Consideration { /** * @notice Derive and set hashes, reference chainId, and associated domain * separator during deployment. * * @param conduitController A contract that deploys conduits, or proxies * that may optionally be used to transfer approved * ERC20/721/1155 tokens. */ constructor(address conduitController) Consideration(conduitController) {} /** * @dev Internal pure function to retrieve and return the name of this * contract. * * @return The name of this contract. */ function _name() internal pure override returns (string memory) { // Return the name of the contract. assembly { mstore(0x20, 0x20) mstore(0x47, 0x07536561706f7274) return(0x20, 0x60) } } /** * @dev Internal pure function to retrieve the name of this contract as a * string that will be used to derive the name hash in the constructor. * * @return The name of this contract as a string. */ function _nameString() internal pure override returns (string memory) { // Return the name of the contract. return "Seaport"; } }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.13; // prettier-ignore import { ConsiderationInterface } from "./ConsiderationInterface.sol"; // prettier-ignore import { OrderComponents, BasicOrderParameters, OrderParameters, Order, AdvancedOrder, OrderStatus, CriteriaResolver, Fulfillment, FulfillmentComponent, Execution } from "./ConsiderationStructs.sol"; import { OrderCombiner } from "./OrderCombiner.sol"; /** * @title Consideration * @author 0age * @custom:coauthor d1ll0n * @custom:coauthor transmissions11 * @custom:version 1.1 * @notice Consideration is a generalized ETH/ERC20/ERC721/ERC1155 marketplace. * It minimizes external calls to the greatest extent possible and * provides lightweight methods for common routes as well as more * flexible methods for composing advanced orders or groups of orders. * Each order contains an arbitrary number of items that may be spent * (the "offer") along with an arbitrary number of items that must be * received back by the indicated recipients (the "consideration"). */ contract Consideration is ConsiderationInterface, OrderCombiner { /** * @notice Derive and set hashes, reference chainId, and associated domain * separator during deployment. * * @param conduitController A contract that deploys conduits, or proxies * that may optionally be used to transfer approved * ERC20/721/1155 tokens. */ constructor(address conduitController) OrderCombiner(conduitController) {} /** * @notice Fulfill an order offering an ERC20, ERC721, or ERC1155 item by * supplying Ether (or other native tokens), ERC20 tokens, an ERC721 * item, or an ERC1155 item as consideration. Six permutations are * supported: Native token to ERC721, Native token to ERC1155, ERC20 * to ERC721, ERC20 to ERC1155, ERC721 to ERC20, and ERC1155 to * ERC20 (with native tokens supplied as msg.value). For an order to * be eligible for fulfillment via this method, it must contain a * single offer item (though that item may have a greater amount if * the item is not an ERC721). An arbitrary number of "additional * recipients" may also be supplied which will each receive native * tokens or ERC20 items from the fulfiller as consideration. Refer * to the documentation for a more comprehensive summary of how to * utilize this method and what orders are compatible with it. * * @param parameters Additional information on the fulfilled order. Note * that the offerer and the fulfiller must first approve * this contract (or their chosen conduit if indicated) * before any tokens can be transferred. Also note that * contract recipients of ERC1155 consideration items must * implement `onERC1155Received` in order to receive those * items. * * @return fulfilled A boolean indicating whether the order has been * successfully fulfilled. */ function fulfillBasicOrder(BasicOrderParameters calldata parameters) external payable override returns (bool fulfilled) { // Validate and fulfill the basic order. fulfilled = _validateAndFulfillBasicOrder(parameters); } /** * @notice Fulfill an order with an arbitrary number of items for offer and * consideration. Note that this function does not support * criteria-based orders or partial filling of orders (though * filling the remainder of a partially-filled order is supported). * * @param order The order to fulfill. Note that both the * offerer and the fulfiller must first approve * this contract (or the corresponding conduit if * indicated) to transfer any relevant tokens on * their behalf and that contracts must implement * `onERC1155Received` to receive ERC1155 tokens * as consideration. * @param fulfillerConduitKey A bytes32 value indicating what conduit, if * any, to source the fulfiller's token approvals * from. The zero hash signifies that no conduit * should be used (and direct approvals set on * Consideration). * * @return fulfilled A boolean indicating whether the order has been * successfully fulfilled. */ function fulfillOrder(Order calldata order, bytes32 fulfillerConduitKey) external payable override returns (bool fulfilled) { // Convert order to "advanced" order, then validate and fulfill it. fulfilled = _validateAndFulfillAdvancedOrder( _convertOrderToAdvanced(order), new CriteriaResolver[](0), // No criteria resolvers supplied. fulfillerConduitKey, msg.sender ); } /** * @notice Fill an order, fully or partially, with an arbitrary number of * items for offer and consideration alongside criteria resolvers * containing specific token identifiers and associated proofs. * * @param advancedOrder The order to fulfill along with the fraction * of the order to attempt to fill. Note that * both the offerer and the fulfiller must first * approve this contract (or their conduit if * indicated by the order) to transfer any * relevant tokens on their behalf and that * contracts must implement `onERC1155Received` * to receive ERC1155 tokens as consideration. * Also note that all offer and consideration * components must have no remainder after * multiplication of the respective amount with * the supplied fraction for the partial fill to * be considered valid. * @param criteriaResolvers An array where each element contains a * reference to a specific offer or * consideration, a token identifier, and a proof * that the supplied token identifier is * contained in the merkle root held by the item * in question's criteria element. Note that an * empty criteria indicates that any * (transferable) token identifier on the token * in question is valid and that no associated * proof needs to be supplied. * @param fulfillerConduitKey A bytes32 value indicating what conduit, if * any, to source the fulfiller's token approvals * from. The zero hash signifies that no conduit * should be used (and direct approvals set on * Consideration). * @param recipient The intended recipient for all received items, * with `address(0)` indicating that the caller * should receive the items. * * @return fulfilled A boolean indicating whether the order has been * successfully fulfilled. */ function fulfillAdvancedOrder( AdvancedOrder calldata advancedOrder, CriteriaResolver[] calldata criteriaResolvers, bytes32 fulfillerConduitKey, address recipient ) external payable override returns (bool fulfilled) { // Validate and fulfill the order. fulfilled = _validateAndFulfillAdvancedOrder( advancedOrder, criteriaResolvers, fulfillerConduitKey, recipient == address(0) ? msg.sender : recipient ); } /** * @notice Attempt to fill a group of orders, each with an arbitrary number * of items for offer and consideration. Any order that is not * currently active, has already been fully filled, or has been * cancelled will be omitted. Remaining offer and consideration * items will then be aggregated where possible as indicated by the * supplied offer and consideration component arrays and aggregated * items will be transferred to the fulfiller or to each intended * recipient, respectively. Note that a failing item transfer or an * issue with order formatting will cause the entire batch to fail. * Note that this function does not support criteria-based orders or * partial filling of orders (though filling the remainder of a * partially-filled order is supported). * * @param orders The orders to fulfill. Note that both * the offerer and the fulfiller must first * approve this contract (or the * corresponding conduit if indicated) to * transfer any relevant tokens on their * behalf and that contracts must implement * `onERC1155Received` to receive ERC1155 * tokens as consideration. * @param offerFulfillments An array of FulfillmentComponent arrays * indicating which offer items to attempt * to aggregate when preparing executions. * @param considerationFulfillments An array of FulfillmentComponent arrays * indicating which consideration items to * attempt to aggregate when preparing * executions. * @param fulfillerConduitKey A bytes32 value indicating what conduit, * if any, to source the fulfiller's token * approvals from. The zero hash signifies * that no conduit should be used (and * direct approvals set on Consideration). * @param maximumFulfilled The maximum number of orders to fulfill. * * @return availableOrders An array of booleans indicating if each order * with an index corresponding to the index of the * returned boolean was fulfillable or not. * @return executions An array of elements indicating the sequence of * transfers performed as part of matching the given * orders. */ function fulfillAvailableOrders( Order[] calldata orders, FulfillmentComponent[][] calldata offerFulfillments, FulfillmentComponent[][] calldata considerationFulfillments, bytes32 fulfillerConduitKey, uint256 maximumFulfilled ) external payable override returns (bool[] memory availableOrders, Execution[] memory executions) { // Convert orders to "advanced" orders and fulfill all available orders. return _fulfillAvailableAdvancedOrders( _convertOrdersToAdvanced(orders), // Convert to advanced orders. new CriteriaResolver[](0), // No criteria resolvers supplied. offerFulfillments, considerationFulfillments, fulfillerConduitKey, msg.sender, maximumFulfilled ); } /** * @notice Attempt to fill a group of orders, fully or partially, with an * arbitrary number of items for offer and consideration per order * alongside criteria resolvers containing specific token * identifiers and associated proofs. Any order that is not * currently active, has already been fully filled, or has been * cancelled will be omitted. Remaining offer and consideration * items will then be aggregated where possible as indicated by the * supplied offer and consideration component arrays and aggregated * items will be transferred to the fulfiller or to each intended * recipient, respectively. Note that a failing item transfer or an * issue with order formatting will cause the entire batch to fail. * * @param advancedOrders The orders to fulfill along with the * fraction of those orders to attempt to * fill. Note that both the offerer and the * fulfiller must first approve this * contract (or their conduit if indicated * by the order) to transfer any relevant * tokens on their behalf and that * contracts must implement * `onERC1155Received` in order to receive * ERC1155 tokens as consideration. Also * note that all offer and consideration * components must have no remainder after * multiplication of the respective amount * with the supplied fraction for an * order's partial fill amount to be * considered valid. * @param criteriaResolvers An array where each element contains a * reference to a specific offer or * consideration, a token identifier, and a * proof that the supplied token identifier * is contained in the merkle root held by * the item in question's criteria element. * Note that an empty criteria indicates * that any (transferable) token * identifier on the token in question is * valid and that no associated proof needs * to be supplied. * @param offerFulfillments An array of FulfillmentComponent arrays * indicating which offer items to attempt * to aggregate when preparing executions. * @param considerationFulfillments An array of FulfillmentComponent arrays * indicating which consideration items to * attempt to aggregate when preparing * executions. * @param fulfillerConduitKey A bytes32 value indicating what conduit, * if any, to source the fulfiller's token * approvals from. The zero hash signifies * that no conduit should be used (and * direct approvals set on Consideration). * @param recipient The intended recipient for all received * items, with `address(0)` indicating that * the caller should receive the items. * @param maximumFulfilled The maximum number of orders to fulfill. * * @return availableOrders An array of booleans indicating if each order * with an index corresponding to the index of the * returned boolean was fulfillable or not. * @return executions An array of elements indicating the sequence of * transfers performed as part of matching the given * orders. */ function fulfillAvailableAdvancedOrders( AdvancedOrder[] memory advancedOrders, CriteriaResolver[] calldata criteriaResolvers, FulfillmentComponent[][] calldata offerFulfillments, FulfillmentComponent[][] calldata considerationFulfillments, bytes32 fulfillerConduitKey, address recipient, uint256 maximumFulfilled ) external payable override returns (bool[] memory availableOrders, Execution[] memory executions) { // Fulfill all available orders. return _fulfillAvailableAdvancedOrders( advancedOrders, criteriaResolvers, offerFulfillments, considerationFulfillments, fulfillerConduitKey, recipient == address(0) ? msg.sender : recipient, maximumFulfilled ); } /** * @notice Match an arbitrary number of orders, each with an arbitrary * number of items for offer and consideration along with a set of * fulfillments allocating offer components to consideration * components. Note that this function does not support * criteria-based or partial filling of orders (though filling the * remainder of a partially-filled order is supported). * * @param orders The orders to match. Note that both the offerer * and fulfiller on each order must first approve * this contract (or their conduit if indicated by * the order) to transfer any relevant tokens on * their behalf and each consideration recipient * must implement `onERC1155Received` in order to * receive ERC1155 tokens. * @param fulfillments An array of elements allocating offer components * to consideration components. Note that each * consideration component must be fully met in * order for the match operation to be valid. * * @return executions An array of elements indicating the sequence of * transfers performed as part of matching the given * orders. */ function matchOrders( Order[] calldata orders, Fulfillment[] calldata fulfillments ) external payable override returns (Execution[] memory executions) { // Convert to advanced, validate, and match orders using fulfillments. return _matchAdvancedOrders( _convertOrdersToAdvanced(orders), new CriteriaResolver[](0), // No criteria resolvers supplied. fulfillments ); } /** * @notice Match an arbitrary number of full or partial orders, each with an * arbitrary number of items for offer and consideration, supplying * criteria resolvers containing specific token identifiers and * associated proofs as well as fulfillments allocating offer * components to consideration components. * * @param advancedOrders The advanced orders to match. Note that both the * offerer and fulfiller on each order must first * approve this contract (or their conduit if * indicated by the order) to transfer any relevant * tokens on their behalf and each consideration * recipient must implement `onERC1155Received` in * order to receive ERC1155 tokens. Also note that * the offer and consideration components for each * order must have no remainder after multiplying * the respective amount with the supplied fraction * in order for the group of partial fills to be * considered valid. * @param criteriaResolvers An array where each element contains a reference * to a specific order as well as that order's * offer or consideration, a token identifier, and * a proof that the supplied token identifier is * contained in the order's merkle root. Note that * an empty root indicates that any (transferable) * token identifier is valid and that no associated * proof needs to be supplied. * @param fulfillments An array of elements allocating offer components * to consideration components. Note that each * consideration component must be fully met in * order for the match operation to be valid. * * @return executions An array of elements indicating the sequence of * transfers performed as part of matching the given * orders. */ function matchAdvancedOrders( AdvancedOrder[] memory advancedOrders, CriteriaResolver[] calldata criteriaResolvers, Fulfillment[] calldata fulfillments ) external payable override returns (Execution[] memory executions) { // Validate and match the advanced orders using supplied fulfillments. return _matchAdvancedOrders( advancedOrders, criteriaResolvers, fulfillments ); } /** * @notice Cancel an arbitrary number of orders. Note that only the offerer * or the zone of a given order may cancel it. Callers should ensure * that the intended order was cancelled by calling `getOrderStatus` * and confirming that `isCancelled` returns `true`. * * @param orders The orders to cancel. * * @return cancelled A boolean indicating whether the supplied orders have * been successfully cancelled. */ function cancel(OrderComponents[] calldata orders) external override returns (bool cancelled) { // Cancel the orders. cancelled = _cancel(orders); } /** * @notice Validate an arbitrary number of orders, thereby registering their * signatures as valid and allowing the fulfiller to skip signature * verification on fulfillment. Note that validated orders may still * be unfulfillable due to invalid item amounts or other factors; * callers should determine whether validated orders are fulfillable * by simulating the fulfillment call prior to execution. Also note * that anyone can validate a signed order, but only the offerer can * validate an order without supplying a signature. * * @param orders The orders to validate. * * @return validated A boolean indicating whether the supplied orders have * been successfully validated. */ function validate(Order[] calldata orders) external override returns (bool validated) { // Validate the orders. validated = _validate(orders); } /** * @notice Cancel all orders from a given offerer with a given zone in bulk * by incrementing a counter. Note that only the offerer may * increment the counter. * * @return newCounter The new counter. */ function incrementCounter() external override returns (uint256 newCounter) { // Increment current counter for the supplied offerer. newCounter = _incrementCounter(); } /** * @notice Retrieve the order hash for a given order. * * @param order The components of the order. * * @return orderHash The order hash. */ function getOrderHash(OrderComponents calldata order) external view override returns (bytes32 orderHash) { // Derive order hash by supplying order parameters along with counter. orderHash = _deriveOrderHash( OrderParameters( order.offerer, order.zone, order.offer, order.consideration, order.orderType, order.startTime, order.endTime, order.zoneHash, order.salt, order.conduitKey, order.consideration.length ), order.counter ); } /** * @notice Retrieve the status of a given order by hash, including whether * the order has been cancelled or validated and the fraction of the * order that has been filled. * * @param orderHash The order hash in question. * * @return isValidated A boolean indicating whether the order in question * has been validated (i.e. previously approved or * partially filled). * @return isCancelled A boolean indicating whether the order in question * has been cancelled. * @return totalFilled The total portion of the order that has been filled * (i.e. the "numerator"). * @return totalSize The total size of the order that is either filled or * unfilled (i.e. the "denominator"). */ function getOrderStatus(bytes32 orderHash) external view override returns ( bool isValidated, bool isCancelled, uint256 totalFilled, uint256 totalSize ) { // Retrieve the order status using the order hash. return _getOrderStatus(orderHash); } /** * @notice Retrieve the current counter for a given offerer. * * @param offerer The offerer in question. * * @return counter The current counter. */ function getCounter(address offerer) external view override returns (uint256 counter) { // Return the counter for the supplied offerer. counter = _getCounter(offerer); } /** * @notice Retrieve configuration information for this contract. * * @return version The contract version. * @return domainSeparator The domain separator for this contract. * @return conduitController The conduit Controller set for this contract. */ function information() external view override returns ( string memory version, bytes32 domainSeparator, address conduitController ) { // Return the information for this contract. return _information(); } /** * @notice Retrieve the name of this contract. * * @return contractName The name of this contract. */ function name() external pure override returns (string memory contractName) { // Return the name of the contract. contractName = _name(); } }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.13; import { Side, ItemType } from "./ConsiderationEnums.sol"; // prettier-ignore import { OfferItem, ConsiderationItem, ReceivedItem, OrderParameters, Fulfillment, FulfillmentComponent, Execution, Order, AdvancedOrder, CriteriaResolver } from "./ConsiderationStructs.sol"; import { OrderFulfiller } from "./OrderFulfiller.sol"; import { FulfillmentApplier } from "./FulfillmentApplier.sol"; import "./ConsiderationConstants.sol"; /** * @title OrderCombiner * @author 0age * @notice OrderCombiner contains logic for fulfilling combinations of orders, * either by matching offer items to consideration items or by * fulfilling orders where available. */ contract OrderCombiner is OrderFulfiller, FulfillmentApplier { /** * @dev Derive and set hashes, reference chainId, and associated domain * separator during deployment. * * @param conduitController A contract that deploys conduits, or proxies * that may optionally be used to transfer approved * ERC20/721/1155 tokens. */ constructor(address conduitController) OrderFulfiller(conduitController) {} /** * @notice Internal function to attempt to fill a group of orders, fully or * partially, with an arbitrary number of items for offer and * consideration per order alongside criteria resolvers containing * specific token identifiers and associated proofs. Any order that * is not currently active, has already been fully filled, or has * been cancelled will be omitted. Remaining offer and consideration * items will then be aggregated where possible as indicated by the * supplied offer and consideration component arrays and aggregated * items will be transferred to the fulfiller or to each intended * recipient, respectively. Note that a failing item transfer or an * issue with order formatting will cause the entire batch to fail. * * @param advancedOrders The orders to fulfill along with the * fraction of those orders to attempt to * fill. Note that both the offerer and the * fulfiller must first approve this * contract (or a conduit if indicated by * the order) to transfer any relevant * tokens on their behalf and that * contracts must implement * `onERC1155Received` in order to receive * ERC1155 tokens as consideration. Also * note that all offer and consideration * components must have no remainder after * multiplication of the respective amount * with the supplied fraction for an * order's partial fill amount to be * considered valid. * @param criteriaResolvers An array where each element contains a * reference to a specific offer or * consideration, a token identifier, and a * proof that the supplied token identifier * is contained in the merkle root held by * the item in question's criteria element. * Note that an empty criteria indicates * that any (transferable) token * identifier on the token in question is * valid and that no associated proof needs * to be supplied. * @param offerFulfillments An array of FulfillmentComponent arrays * indicating which offer items to attempt * to aggregate when preparing executions. * @param considerationFulfillments An array of FulfillmentComponent arrays * indicating which consideration items to * attempt to aggregate when preparing * executions. * @param fulfillerConduitKey A bytes32 value indicating what conduit, * if any, to source the fulfiller's token * approvals from. The zero hash signifies * that no conduit should be used (and * direct approvals set on Consideration). * @param recipient The intended recipient for all received * items. * @param maximumFulfilled The maximum number of orders to fulfill. * * @return availableOrders An array of booleans indicating if each order * with an index corresponding to the index of the * returned boolean was fulfillable or not. * @return executions An array of elements indicating the sequence of * transfers performed as part of matching the given * orders. */ function _fulfillAvailableAdvancedOrders( AdvancedOrder[] memory advancedOrders, CriteriaResolver[] memory criteriaResolvers, FulfillmentComponent[][] calldata offerFulfillments, FulfillmentComponent[][] calldata considerationFulfillments, bytes32 fulfillerConduitKey, address recipient, uint256 maximumFulfilled ) internal returns (bool[] memory availableOrders, Execution[] memory executions) { // Validate orders, apply amounts, & determine if they utilize conduits. _validateOrdersAndPrepareToFulfill( advancedOrders, criteriaResolvers, false, // Signifies that invalid orders should NOT revert. maximumFulfilled, recipient ); // Aggregate used offer and consideration items and execute transfers. (availableOrders, executions) = _executeAvailableFulfillments( advancedOrders, offerFulfillments, considerationFulfillments, fulfillerConduitKey, recipient ); // Return order fulfillment details and executions. return (availableOrders, executions); } /** * @dev Internal function to validate a group of orders, update their * statuses, reduce amounts by their previously filled fractions, apply * criteria resolvers, and emit OrderFulfilled events. * * @param advancedOrders The advanced orders to validate and reduce by * their previously filled amounts. * @param criteriaResolvers An array where each element contains a reference * to a specific order as well as that order's * offer or consideration, a token identifier, and * a proof that the supplied token identifier is * contained in the order's merkle root. Note that * a root of zero indicates that any transferable * token identifier is valid and that no proof * needs to be supplied. * @param revertOnInvalid A boolean indicating whether to revert on any * order being invalid; setting this to false will * instead cause the invalid order to be skipped. * @param maximumFulfilled The maximum number of orders to fulfill. * @param recipient The intended recipient for all received items. */ function _validateOrdersAndPrepareToFulfill( AdvancedOrder[] memory advancedOrders, CriteriaResolver[] memory criteriaResolvers, bool revertOnInvalid, uint256 maximumFulfilled, address recipient ) internal { // Ensure this function cannot be triggered during a reentrant call. _setReentrancyGuard(); // Read length of orders array and place on the stack. uint256 totalOrders = advancedOrders.length; // Track the order hash for each order being fulfilled. bytes32[] memory orderHashes = new bytes32[](totalOrders); // Override orderHashes length to zero after memory has been allocated. assembly { mstore(orderHashes, 0) } // Declare an error buffer indicating status of any native offer items. // {00} == 0 => In a match function, no native offer items: allow. // {01} == 1 => In a match function, some native offer items: allow. // {10} == 2 => Not in a match function, no native offer items: allow. // {11} == 3 => Not in a match function, some native offer items: THROW. uint256 invalidNativeOfferItemErrorBuffer; // Use assembly to set the value for the second bit of the error buffer. assembly { // Use the second bit of the error buffer to indicate whether the // current function is not matchAdvancedOrders or matchOrders. invalidNativeOfferItemErrorBuffer := shl( 1, gt( // Take the remainder of the selector modulo a magic value. mod( shr(NumBitsAfterSelector, calldataload(0)), NonMatchSelector_MagicModulus ), // Check if remainder is higher than the greatest remainder // of the two match selectors modulo the magic value. NonMatchSelector_MagicRemainder ) ) } // Skip overflow checks as all for loops are indexed starting at zero. unchecked { // Iterate over each order. for (uint256 i = 0; i < totalOrders; ++i) { // Retrieve the current order. AdvancedOrder memory advancedOrder = advancedOrders[i]; // Determine if max number orders have already been fulfilled. if (maximumFulfilled == 0) { // Mark fill fraction as zero as the order will not be used. advancedOrder.numerator = 0; // Update the length of the orderHashes array. assembly { mstore(orderHashes, add(i, 1)) } // Continue iterating through the remaining orders. continue; } // Validate it, update status, and determine fraction to fill. ( bytes32 orderHash, uint256 numerator, uint256 denominator ) = _validateOrderAndUpdateStatus( advancedOrder, criteriaResolvers, revertOnInvalid, orderHashes ); // Update the length of the orderHashes array. assembly { mstore(orderHashes, add(i, 1)) } // Do not track hash or adjust prices if order is not fulfilled. if (numerator == 0) { // Mark fill fraction as zero if the order is not fulfilled. advancedOrder.numerator = 0; // Continue iterating through the remaining orders. continue; } // Otherwise, track the order hash in question. orderHashes[i] = orderHash; // Decrement the number of fulfilled orders. // Skip underflow check as the condition before // implies that maximumFulfilled > 0. maximumFulfilled--; // Place the start time for the order on the stack. uint256 startTime = advancedOrder.parameters.startTime; // Place the end time for the order on the stack. uint256 endTime = advancedOrder.parameters.endTime; // Retrieve array of offer items for the order in question. OfferItem[] memory offer = advancedOrder.parameters.offer; // Read length of offer array and place on the stack. uint256 totalOfferItems = offer.length; // Iterate over each offer item on the order. for (uint256 j = 0; j < totalOfferItems; ++j) { // Retrieve the offer item. OfferItem memory offerItem = offer[j]; assembly { // If the offer item is for the native token, set the // first bit of the error buffer to true. invalidNativeOfferItemErrorBuffer := or( invalidNativeOfferItemErrorBuffer, iszero(mload(offerItem)) ) } // Apply order fill fraction to offer item end amount. uint256 endAmount = _getFraction( numerator, denominator, offerItem.endAmount ); // Reuse same fraction if start and end amounts are equal. if (offerItem.startAmount == offerItem.endAmount) { // Apply derived amount to both start and end amount. offerItem.startAmount = endAmount; } else { // Apply order fill fraction to offer item start amount. offerItem.startAmount = _getFraction( numerator, denominator, offerItem.startAmount ); } // Update end amount in memory to match the derived amount. offerItem.endAmount = endAmount; // Adjust offer amount using current time; round down. offerItem.startAmount = _locateCurrentAmount( offerItem.startAmount, offerItem.endAmount, startTime, endTime, false // round down ); } // Retrieve array of consideration items for order in question. ConsiderationItem[] memory consideration = ( advancedOrder.parameters.consideration ); // Read length of consideration array and place on the stack. uint256 totalConsiderationItems = consideration.length; // Iterate over each consideration item on the order. for (uint256 j = 0; j < totalConsiderationItems; ++j) { // Retrieve the consideration item. ConsiderationItem memory considerationItem = ( consideration[j] ); // Apply fraction to consideration item end amount. uint256 endAmount = _getFraction( numerator, denominator, considerationItem.endAmount ); // Reuse same fraction if start and end amounts are equal. if ( considerationItem.startAmount == considerationItem.endAmount ) { // Apply derived amount to both start and end amount. considerationItem.startAmount = endAmount; } else { // Apply fraction to consideration item start amount. considerationItem.startAmount = _getFraction( numerator, denominator, considerationItem.startAmount ); } // Update end amount in memory to match the derived amount. considerationItem.endAmount = endAmount; // Adjust consideration amount using current time; round up. considerationItem.startAmount = ( _locateCurrentAmount( considerationItem.startAmount, considerationItem.endAmount, startTime, endTime, true // round up ) ); // Utilize assembly to manually "shift" the recipient value. assembly { // Write recipient to endAmount, as endAmount is not // used from this point on and can be repurposed to fit // the layout of a ReceivedItem. mstore( add( considerationItem, ReceivedItem_recipient_offset // old endAmount ), mload( add( considerationItem, ConsiderationItem_recipient_offset ) ) ) } } } } // If the first bit is set, a native offer item was encountered. If the // second bit is set in the error buffer, the current function is not // matchOrders or matchAdvancedOrders. If the value is three, both the // first and second bits were set; in that case, revert with an error. if (invalidNativeOfferItemErrorBuffer == 3) { revert InvalidNativeOfferItem(); } // Apply criteria resolvers to each order as applicable. _applyCriteriaResolvers(advancedOrders, criteriaResolvers); // Emit an event for each order signifying that it has been fulfilled. // Skip overflow checks as all for loops are indexed starting at zero. unchecked { // Iterate over each order. for (uint256 i = 0; i < totalOrders; ++i) { // Do not emit an event if no order hash is present. if (orderHashes[i] == bytes32(0)) { continue; } // Retrieve parameters for the order in question. OrderParameters memory orderParameters = ( advancedOrders[i].parameters ); // Emit an OrderFulfilled event. _emitOrderFulfilledEvent( orderHashes[i], orderParameters.offerer, orderParameters.zone, recipient, orderParameters.offer, orderParameters.consideration ); } } } /** * @dev Internal function to fulfill a group of validated orders, fully or * partially, with an arbitrary number of items for offer and * consideration per order and to execute transfers. Any order that is * not currently active, has already been fully filled, or has been * cancelled will be omitted. Remaining offer and consideration items * will then be aggregated where possible as indicated by the supplied * offer and consideration component arrays and aggregated items will * be transferred to the fulfiller or to each intended recipient, * respectively. Note that a failing item transfer or an issue with * order formatting will cause the entire batch to fail. * * @param advancedOrders The orders to fulfill along with the * fraction of those orders to attempt to * fill. Note that both the offerer and the * fulfiller must first approve this * contract (or the conduit if indicated by * the order) to transfer any relevant * tokens on their behalf and that * contracts must implement * `onERC1155Received` in order to receive * ERC1155 tokens as consideration. Also * note that all offer and consideration * components must have no remainder after * multiplication of the respective amount * with the supplied fraction for an * order's partial fill amount to be * considered valid. * @param offerFulfillments An array of FulfillmentComponent arrays * indicating which offer items to attempt * to aggregate when preparing executions. * @param considerationFulfillments An array of FulfillmentComponent arrays * indicating which consideration items to * attempt to aggregate when preparing * executions. * @param fulfillerConduitKey A bytes32 value indicating what conduit, * if any, to source the fulfiller's token * approvals from. The zero hash signifies * that no conduit should be used, with * direct approvals set on Consideration. * @param recipient The intended recipient for all received * items. * * @return availableOrders An array of booleans indicating if each order * with an index corresponding to the index of the * returned boolean was fulfillable or not. * @return executions An array of elements indicating the sequence of * transfers performed as part of matching the given * orders. */ function _executeAvailableFulfillments( AdvancedOrder[] memory advancedOrders, FulfillmentComponent[][] memory offerFulfillments, FulfillmentComponent[][] memory considerationFulfillments, bytes32 fulfillerConduitKey, address recipient ) internal returns (bool[] memory availableOrders, Execution[] memory executions) { // Retrieve length of offer fulfillments array and place on the stack. uint256 totalOfferFulfillments = offerFulfillments.length; // Retrieve length of consideration fulfillments array & place on stack. uint256 totalConsiderationFulfillments = ( considerationFulfillments.length ); // Allocate an execution for each offer and consideration fulfillment. executions = new Execution[]( totalOfferFulfillments + totalConsiderationFulfillments ); // Skip overflow checks as all for loops are indexed starting at zero. unchecked { // Track number of filtered executions. uint256 totalFilteredExecutions = 0; // Iterate over each offer fulfillment. for (uint256 i = 0; i < totalOfferFulfillments; ++i) { /// Retrieve the offer fulfillment components in question. FulfillmentComponent[] memory components = ( offerFulfillments[i] ); // Derive aggregated execution corresponding with fulfillment. Execution memory execution = _aggregateAvailable( advancedOrders, Side.OFFER, components, fulfillerConduitKey, recipient ); // If offerer and recipient on the execution are the same... if (execution.item.recipient == execution.offerer) { // Increment total filtered executions. ++totalFilteredExecutions; } else { // Otherwise, assign the execution to the executions array. executions[i - totalFilteredExecutions] = execution; } } // Iterate over each consideration fulfillment. for (uint256 i = 0; i < totalConsiderationFulfillments; ++i) { /// Retrieve consideration fulfillment components in question. FulfillmentComponent[] memory components = ( considerationFulfillments[i] ); // Derive aggregated execution corresponding with fulfillment. Execution memory execution = _aggregateAvailable( advancedOrders, Side.CONSIDERATION, components, fulfillerConduitKey, address(0) // unused ); // If offerer and recipient on the execution are the same... if (execution.item.recipient == execution.offerer) { // Increment total filtered executions. ++totalFilteredExecutions; } else { // Otherwise, assign the execution to the executions array. executions[ i + totalOfferFulfillments - totalFilteredExecutions ] = execution; } } // If some number of executions have been filtered... if (totalFilteredExecutions != 0) { // reduce the total length of the executions array. assembly { mstore( executions, sub(mload(executions), totalFilteredExecutions) ) } } } // Revert if no orders are available. if (executions.length == 0) { revert NoSpecifiedOrdersAvailable(); } // Perform final checks and return. availableOrders = _performFinalChecksAndExecuteOrders( advancedOrders, executions ); return (availableOrders, executions); } /** * @dev Internal function to perform a final check that each consideration * item for an arbitrary number of fulfilled orders has been met and to * trigger associated executions, transferring the respective items. * * @param advancedOrders The orders to check and perform executions for. * @param executions An array of elements indicating the sequence of * transfers to perform when fulfilling the given * orders. * * @return availableOrders An array of booleans indicating if each order * with an index corresponding to the index of the * returned boolean was fulfillable or not. */ function _performFinalChecksAndExecuteOrders( AdvancedOrder[] memory advancedOrders, Execution[] memory executions ) internal returns (bool[] memory availableOrders) { // Retrieve the length of the advanced orders array and place on stack. uint256 totalOrders = advancedOrders.length; // Initialize array for tracking available orders. availableOrders = new bool[](totalOrders); // Skip overflow checks as all for loops are indexed starting at zero. unchecked { // Iterate over orders to ensure all considerations are met. for (uint256 i = 0; i < totalOrders; ++i) { // Retrieve the order in question. AdvancedOrder memory advancedOrder = advancedOrders[i]; // Skip consideration item checks for order if not fulfilled. if (advancedOrder.numerator == 0) { // Note: orders do not need to be marked as unavailable as a // new memory region has been allocated. Review carefully if // altering compiler version or managing memory manually. continue; } // Mark the order as available. availableOrders[i] = true; // Retrieve consideration items to ensure they are fulfilled. ConsiderationItem[] memory consideration = ( advancedOrder.parameters.consideration ); // Read length of consideration array and place on the stack. uint256 totalConsiderationItems = consideration.length; // Iterate over each consideration item to ensure it is met. for (uint256 j = 0; j < totalConsiderationItems; ++j) { // Retrieve remaining amount on the consideration item. uint256 unmetAmount = consideration[j].startAmount; // Revert if the remaining amount is not zero. if (unmetAmount != 0) { revert ConsiderationNotMet(i, j, unmetAmount); } } } } // Put ether value supplied by the caller on the stack. uint256 etherRemaining = msg.value; // Initialize an accumulator array. From this point forward, no new // memory regions can be safely allocated until the accumulator is no // longer being utilized, as the accumulator operates in an open-ended // fashion from this memory pointer; existing memory may still be // accessed and modified, however. bytes memory accumulator = new bytes(AccumulatorDisarmed); // Retrieve the length of the executions array and place on stack. uint256 totalExecutions = executions.length; // Iterate over each execution. for (uint256 i = 0; i < totalExecutions; ) { // Retrieve the execution and the associated received item. Execution memory execution = executions[i]; ReceivedItem memory item = execution.item; // If execution transfers native tokens, reduce value available. if (item.itemType == ItemType.NATIVE) { // Ensure that sufficient native tokens are still available. if (item.amount > etherRemaining) { revert InsufficientEtherSupplied(); } // Skip underflow check as amount is less than ether remaining. unchecked { etherRemaining -= item.amount; } } // Transfer the item specified by the execution. _transfer( item, execution.offerer, execution.conduitKey, accumulator ); // Skip overflow check as for loop is indexed starting at zero. unchecked { ++i; } } // Trigger any remaining accumulated transfers via call to the conduit. _triggerIfArmed(accumulator); // If any ether remains after fulfillments, return it to the caller. if (etherRemaining != 0) { _transferEth(payable(msg.sender), etherRemaining); } // Clear the reentrancy guard. _clearReentrancyGuard(); // Return the array containing available orders. return (availableOrders); } /** * @dev Internal function to match an arbitrary number of full or partial * orders, each with an arbitrary number of items for offer and * consideration, supplying criteria resolvers containing specific * token identifiers and associated proofs as well as fulfillments * allocating offer components to consideration components. * * @param advancedOrders The advanced orders to match. Note that both the * offerer and fulfiller on each order must first * approve this contract (or their conduit if * indicated by the order) to transfer any relevant * tokens on their behalf and each consideration * recipient must implement `onERC1155Received` in * order to receive ERC1155 tokens. Also note that * the offer and consideration components for each * order must have no remainder after multiplying * the respective amount with the supplied fraction * in order for the group of partial fills to be * considered valid. * @param criteriaResolvers An array where each element contains a reference * to a specific order as well as that order's * offer or consideration, a token identifier, and * a proof that the supplied token identifier is * contained in the order's merkle root. Note that * an empty root indicates that any (transferable) * token identifier is valid and that no associated * proof needs to be supplied. * @param fulfillments An array of elements allocating offer components * to consideration components. Note that each * consideration component must be fully met in * order for the match operation to be valid. * * @return executions An array of elements indicating the sequence of * transfers performed as part of matching the given * orders. */ function _matchAdvancedOrders( AdvancedOrder[] memory advancedOrders, CriteriaResolver[] memory criteriaResolvers, Fulfillment[] calldata fulfillments ) internal returns (Execution[] memory executions) { // Validate orders, update order status, and determine item amounts. _validateOrdersAndPrepareToFulfill( advancedOrders, criteriaResolvers, true, // Signifies that invalid orders should revert. advancedOrders.length, address(0) // OrderFulfilled event has no recipient when matching. ); // Fulfill the orders using the supplied fulfillments. return _fulfillAdvancedOrders(advancedOrders, fulfillments); } /** * @dev Internal function to fulfill an arbitrary number of orders, either * full or partial, after validating, adjusting amounts, and applying * criteria resolvers. * * @param advancedOrders The orders to match, including a fraction to * attempt to fill for each order. * @param fulfillments An array of elements allocating offer * components to consideration components. Note * that the final amount of each consideration * component must be zero for a match operation to * be considered valid. * * @return executions An array of elements indicating the sequence of * transfers performed as part of matching the given * orders. */ function _fulfillAdvancedOrders( AdvancedOrder[] memory advancedOrders, Fulfillment[] calldata fulfillments ) internal returns (Execution[] memory executions) { // Retrieve fulfillments array length and place on the stack. uint256 totalFulfillments = fulfillments.length; // Allocate executions by fulfillment and apply them to each execution. executions = new Execution[](totalFulfillments); // Skip overflow checks as all for loops are indexed starting at zero. unchecked { // Track number of filtered executions. uint256 totalFilteredExecutions = 0; // Iterate over each fulfillment. for (uint256 i = 0; i < totalFulfillments; ++i) { /// Retrieve the fulfillment in question. Fulfillment calldata fulfillment = fulfillments[i]; // Derive the execution corresponding with the fulfillment. Execution memory execution = _applyFulfillment( advancedOrders, fulfillment.offerComponents, fulfillment.considerationComponents ); // If offerer and recipient on the execution are the same... if (execution.item.recipient == execution.offerer) { // Increment total filtered executions. ++totalFilteredExecutions; } else { // Otherwise, assign the execution to the executions array. executions[i - totalFilteredExecutions] = execution; } } // If some number of executions have been filtered... if (totalFilteredExecutions != 0) { // reduce the total length of the executions array. assembly { mstore( executions, sub(mload(executions), totalFilteredExecutions) ) } } } // Perform final checks and execute orders. _performFinalChecksAndExecuteOrders(advancedOrders, executions); // Return the executions array. return (executions); } }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.7; // prettier-ignore import { OrderType, BasicOrderType, ItemType, Side } from "./ConsiderationEnums.sol"; /** * @dev An order contains eleven components: an offerer, a zone (or account that * can cancel the order or restrict who can fulfill the order depending on * the type), the order type (specifying partial fill support as well as * restricted order status), the start and end time, a hash that will be * provided to the zone when validating restricted orders, a salt, a key * corresponding to a given conduit, a counter, and an arbitrary number of * offer items that can be spent along with consideration items that must * be received by their respective recipient. */ struct OrderComponents { address offerer; address zone; OfferItem[] offer; ConsiderationItem[] consideration; OrderType orderType; uint256 startTime; uint256 endTime; bytes32 zoneHash; uint256 salt; bytes32 conduitKey; uint256 counter; } /** * @dev An offer item has five components: an item type (ETH or other native * tokens, ERC20, ERC721, and ERC1155, as well as criteria-based ERC721 and * ERC1155), a token address, a dual-purpose "identifierOrCriteria" * component that will either represent a tokenId or a merkle root * depending on the item type, and a start and end amount that support * increasing or decreasing amounts over the duration of the respective * order. */ struct OfferItem { ItemType itemType; address token; uint256 identifierOrCriteria; uint256 startAmount; uint256 endAmount; } /** * @dev A consideration item has the same five components as an offer item and * an additional sixth component designating the required recipient of the * item. */ struct ConsiderationItem { ItemType itemType; address token; uint256 identifierOrCriteria; uint256 startAmount; uint256 endAmount; address payable recipient; } /** * @dev A spent item is translated from a utilized offer item and has four * components: an item type (ETH or other native tokens, ERC20, ERC721, and * ERC1155), a token address, a tokenId, and an amount. */ struct SpentItem { ItemType itemType; address token; uint256 identifier; uint256 amount; } /** * @dev A received item is translated from a utilized consideration item and has * the same four components as a spent item, as well as an additional fifth * component designating the required recipient of the item. */ struct ReceivedItem { ItemType itemType; address token; uint256 identifier; uint256 amount; address payable recipient; } /** * @dev For basic orders involving ETH / native / ERC20 <=> ERC721 / ERC1155 * matching, a group of six functions may be called that only requires a * subset of the usual order arguments. Note the use of a "basicOrderType" * enum; this represents both the usual order type as well as the "route" * of the basic order (a simple derivation function for the basic order * type is `basicOrderType = orderType + (4 * basicOrderRoute)`.) */ struct BasicOrderParameters { // calldata offset address considerationToken; // 0x24 uint256 considerationIdentifier; // 0x44 uint256 considerationAmount; // 0x64 address payable offerer; // 0x84 address zone; // 0xa4 address offerToken; // 0xc4 uint256 offerIdentifier; // 0xe4 uint256 offerAmount; // 0x104 BasicOrderType basicOrderType; // 0x124 uint256 startTime; // 0x144 uint256 endTime; // 0x164 bytes32 zoneHash; // 0x184 uint256 salt; // 0x1a4 bytes32 offererConduitKey; // 0x1c4 bytes32 fulfillerConduitKey; // 0x1e4 uint256 totalOriginalAdditionalRecipients; // 0x204 AdditionalRecipient[] additionalRecipients; // 0x224 bytes signature; // 0x244 // Total length, excluding dynamic array data: 0x264 (580) } /** * @dev Basic orders can supply any number of additional recipients, with the * implied assumption that they are supplied from the offered ETH (or other * native token) or ERC20 token for the order. */ struct AdditionalRecipient { uint256 amount; address payable recipient; } /** * @dev The full set of order components, with the exception of the counter, * must be supplied when fulfilling more sophisticated orders or groups of * orders. The total number of original consideration items must also be * supplied, as the caller may specify additional consideration items. */ struct OrderParameters { address offerer; // 0x00 address zone; // 0x20 OfferItem[] offer; // 0x40 ConsiderationItem[] consideration; // 0x60 OrderType orderType; // 0x80 uint256 startTime; // 0xa0 uint256 endTime; // 0xc0 bytes32 zoneHash; // 0xe0 uint256 salt; // 0x100 bytes32 conduitKey; // 0x120 uint256 totalOriginalConsiderationItems; // 0x140 // offer.length // 0x160 } /** * @dev Orders require a signature in addition to the other order parameters. */ struct Order { OrderParameters parameters; bytes signature; } /** * @dev Advanced orders include a numerator (i.e. a fraction to attempt to fill) * and a denominator (the total size of the order) in addition to the * signature and other order parameters. It also supports an optional field * for supplying extra data; this data will be included in a staticcall to * `isValidOrderIncludingExtraData` on the zone for the order if the order * type is restricted and the offerer or zone are not the caller. */ struct AdvancedOrder { OrderParameters parameters; uint120 numerator; uint120 denominator; bytes signature; bytes extraData; } /** * @dev Orders can be validated (either explicitly via `validate`, or as a * consequence of a full or partial fill), specifically cancelled (they can * also be cancelled in bulk via incrementing a per-zone counter), and * partially or fully filled (with the fraction filled represented by a * numerator and denominator). */ struct OrderStatus { bool isValidated; bool isCancelled; uint120 numerator; uint120 denominator; } /** * @dev A criteria resolver specifies an order, side (offer vs. consideration), * and item index. It then provides a chosen identifier (i.e. tokenId) * alongside a merkle proof demonstrating the identifier meets the required * criteria. */ struct CriteriaResolver { uint256 orderIndex; Side side; uint256 index; uint256 identifier; bytes32[] criteriaProof; } /** * @dev A fulfillment is applied to a group of orders. It decrements a series of * offer and consideration items, then generates a single execution * element. A given fulfillment can be applied to as many offer and * consideration items as desired, but must contain at least one offer and * at least one consideration that match. The fulfillment must also remain * consistent on all key parameters across all offer items (same offerer, * token, type, tokenId, and conduit preference) as well as across all * consideration items (token, type, tokenId, and recipient). */ struct Fulfillment { FulfillmentComponent[] offerComponents; FulfillmentComponent[] considerationComponents; } /** * @dev Each fulfillment component contains one index referencing a specific * order and another referencing a specific offer or consideration item. */ struct FulfillmentComponent { uint256 orderIndex; uint256 itemIndex; } /** * @dev An execution is triggered once all consideration items have been zeroed * out. It sends the item in question from the offerer to the item's * recipient, optionally sourcing approvals from either this contract * directly or from the offerer's chosen conduit if one is specified. An * execution is not provided as an argument, but rather is derived via * orders, criteria resolvers, and fulfillments (where the total number of * executions will be less than or equal to the total number of indicated * fulfillments) and returned as part of `matchOrders`. */ struct Execution { ReceivedItem item; address offerer; bytes32 conduitKey; }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.7; // prettier-ignore import { BasicOrderParameters, OrderComponents, Fulfillment, FulfillmentComponent, Execution, Order, AdvancedOrder, OrderStatus, CriteriaResolver } from "./ConsiderationStructs.sol"; /** * @title ConsiderationInterface * @author 0age * @custom:version 1.1 * @notice Consideration is a generalized ETH/ERC20/ERC721/ERC1155 marketplace. * It minimizes external calls to the greatest extent possible and * provides lightweight methods for common routes as well as more * flexible methods for composing advanced orders. * * @dev ConsiderationInterface contains all external function interfaces for * Consideration. */ interface ConsiderationInterface { /** * @notice Fulfill an order offering an ERC721 token by supplying Ether (or * the native token for the given chain) as consideration for the * order. An arbitrary number of "additional recipients" may also be * supplied which will each receive native tokens from the fulfiller * as consideration. * * @param parameters Additional information on the fulfilled order. Note * that the offerer must first approve this contract (or * their preferred conduit if indicated by the order) for * their offered ERC721 token to be transferred. * * @return fulfilled A boolean indicating whether the order has been * successfully fulfilled. */ function fulfillBasicOrder(BasicOrderParameters calldata parameters) external payable returns (bool fulfilled); /** * @notice Fulfill an order with an arbitrary number of items for offer and * consideration. Note that this function does not support * criteria-based orders or partial filling of orders (though * filling the remainder of a partially-filled order is supported). * * @param order The order to fulfill. Note that both the * offerer and the fulfiller must first approve * this contract (or the corresponding conduit if * indicated) to transfer any relevant tokens on * their behalf and that contracts must implement * `onERC1155Received` to receive ERC1155 tokens * as consideration. * @param fulfillerConduitKey A bytes32 value indicating what conduit, if * any, to source the fulfiller's token approvals * from. The zero hash signifies that no conduit * should be used, with direct approvals set on * Consideration. * * @return fulfilled A boolean indicating whether the order has been * successfully fulfilled. */ function fulfillOrder(Order calldata order, bytes32 fulfillerConduitKey) external payable returns (bool fulfilled); /** * @notice Fill an order, fully or partially, with an arbitrary number of * items for offer and consideration alongside criteria resolvers * containing specific token identifiers and associated proofs. * * @param advancedOrder The order to fulfill along with the fraction * of the order to attempt to fill. Note that * both the offerer and the fulfiller must first * approve this contract (or their preferred * conduit if indicated by the order) to transfer * any relevant tokens on their behalf and that * contracts must implement `onERC1155Received` * to receive ERC1155 tokens as consideration. * Also note that all offer and consideration * components must have no remainder after * multiplication of the respective amount with * the supplied fraction for the partial fill to * be considered valid. * @param criteriaResolvers An array where each element contains a * reference to a specific offer or * consideration, a token identifier, and a proof * that the supplied token identifier is * contained in the merkle root held by the item * in question's criteria element. Note that an * empty criteria indicates that any * (transferable) token identifier on the token * in question is valid and that no associated * proof needs to be supplied. * @param fulfillerConduitKey A bytes32 value indicating what conduit, if * any, to source the fulfiller's token approvals * from. The zero hash signifies that no conduit * should be used, with direct approvals set on * Consideration. * @param recipient The intended recipient for all received items, * with `address(0)` indicating that the caller * should receive the items. * * @return fulfilled A boolean indicating whether the order has been * successfully fulfilled. */ function fulfillAdvancedOrder( AdvancedOrder calldata advancedOrder, CriteriaResolver[] calldata criteriaResolvers, bytes32 fulfillerConduitKey, address recipient ) external payable returns (bool fulfilled); /** * @notice Attempt to fill a group of orders, each with an arbitrary number * of items for offer and consideration. Any order that is not * currently active, has already been fully filled, or has been * cancelled will be omitted. Remaining offer and consideration * items will then be aggregated where possible as indicated by the * supplied offer and consideration component arrays and aggregated * items will be transferred to the fulfiller or to each intended * recipient, respectively. Note that a failing item transfer or an * issue with order formatting will cause the entire batch to fail. * Note that this function does not support criteria-based orders or * partial filling of orders (though filling the remainder of a * partially-filled order is supported). * * @param orders The orders to fulfill. Note that both * the offerer and the fulfiller must first * approve this contract (or the * corresponding conduit if indicated) to * transfer any relevant tokens on their * behalf and that contracts must implement * `onERC1155Received` to receive ERC1155 * tokens as consideration. * @param offerFulfillments An array of FulfillmentComponent arrays * indicating which offer items to attempt * to aggregate when preparing executions. * @param considerationFulfillments An array of FulfillmentComponent arrays * indicating which consideration items to * attempt to aggregate when preparing * executions. * @param fulfillerConduitKey A bytes32 value indicating what conduit, * if any, to source the fulfiller's token * approvals from. The zero hash signifies * that no conduit should be used, with * direct approvals set on this contract. * @param maximumFulfilled The maximum number of orders to fulfill. * * @return availableOrders An array of booleans indicating if each order * with an index corresponding to the index of the * returned boolean was fulfillable or not. * @return executions An array of elements indicating the sequence of * transfers performed as part of matching the given * orders. */ function fulfillAvailableOrders( Order[] calldata orders, FulfillmentComponent[][] calldata offerFulfillments, FulfillmentComponent[][] calldata considerationFulfillments, bytes32 fulfillerConduitKey, uint256 maximumFulfilled ) external payable returns (bool[] memory availableOrders, Execution[] memory executions); /** * @notice Attempt to fill a group of orders, fully or partially, with an * arbitrary number of items for offer and consideration per order * alongside criteria resolvers containing specific token * identifiers and associated proofs. Any order that is not * currently active, has already been fully filled, or has been * cancelled will be omitted. Remaining offer and consideration * items will then be aggregated where possible as indicated by the * supplied offer and consideration component arrays and aggregated * items will be transferred to the fulfiller or to each intended * recipient, respectively. Note that a failing item transfer or an * issue with order formatting will cause the entire batch to fail. * * @param advancedOrders The orders to fulfill along with the * fraction of those orders to attempt to * fill. Note that both the offerer and the * fulfiller must first approve this * contract (or their preferred conduit if * indicated by the order) to transfer any * relevant tokens on their behalf and that * contracts must implement * `onERC1155Received` to enable receipt of * ERC1155 tokens as consideration. Also * note that all offer and consideration * components must have no remainder after * multiplication of the respective amount * with the supplied fraction for an * order's partial fill amount to be * considered valid. * @param criteriaResolvers An array where each element contains a * reference to a specific offer or * consideration, a token identifier, and a * proof that the supplied token identifier * is contained in the merkle root held by * the item in question's criteria element. * Note that an empty criteria indicates * that any (transferable) token * identifier on the token in question is * valid and that no associated proof needs * to be supplied. * @param offerFulfillments An array of FulfillmentComponent arrays * indicating which offer items to attempt * to aggregate when preparing executions. * @param considerationFulfillments An array of FulfillmentComponent arrays * indicating which consideration items to * attempt to aggregate when preparing * executions. * @param fulfillerConduitKey A bytes32 value indicating what conduit, * if any, to source the fulfiller's token * approvals from. The zero hash signifies * that no conduit should be used, with * direct approvals set on this contract. * @param recipient The intended recipient for all received * items, with `address(0)` indicating that * the caller should receive the items. * @param maximumFulfilled The maximum number of orders to fulfill. * * @return availableOrders An array of booleans indicating if each order * with an index corresponding to the index of the * returned boolean was fulfillable or not. * @return executions An array of elements indicating the sequence of * transfers performed as part of matching the given * orders. */ function fulfillAvailableAdvancedOrders( AdvancedOrder[] calldata advancedOrders, CriteriaResolver[] calldata criteriaResolvers, FulfillmentComponent[][] calldata offerFulfillments, FulfillmentComponent[][] calldata considerationFulfillments, bytes32 fulfillerConduitKey, address recipient, uint256 maximumFulfilled ) external payable returns (bool[] memory availableOrders, Execution[] memory executions); /** * @notice Match an arbitrary number of orders, each with an arbitrary * number of items for offer and consideration along with as set of * fulfillments allocating offer components to consideration * components. Note that this function does not support * criteria-based or partial filling of orders (though filling the * remainder of a partially-filled order is supported). * * @param orders The orders to match. Note that both the offerer and * fulfiller on each order must first approve this * contract (or their conduit if indicated by the order) * to transfer any relevant tokens on their behalf and * each consideration recipient must implement * `onERC1155Received` to enable ERC1155 token receipt. * @param fulfillments An array of elements allocating offer components to * consideration components. Note that each * consideration component must be fully met for the * match operation to be valid. * * @return executions An array of elements indicating the sequence of * transfers performed as part of matching the given * orders. */ function matchOrders( Order[] calldata orders, Fulfillment[] calldata fulfillments ) external payable returns (Execution[] memory executions); /** * @notice Match an arbitrary number of full or partial orders, each with an * arbitrary number of items for offer and consideration, supplying * criteria resolvers containing specific token identifiers and * associated proofs as well as fulfillments allocating offer * components to consideration components. * * @param orders The advanced orders to match. Note that both the * offerer and fulfiller on each order must first * approve this contract (or a preferred conduit if * indicated by the order) to transfer any relevant * tokens on their behalf and each consideration * recipient must implement `onERC1155Received` in * order to receive ERC1155 tokens. Also note that * the offer and consideration components for each * order must have no remainder after multiplying * the respective amount with the supplied fraction * in order for the group of partial fills to be * considered valid. * @param criteriaResolvers An array where each element contains a reference * to a specific order as well as that order's * offer or consideration, a token identifier, and * a proof that the supplied token identifier is * contained in the order's merkle root. Note that * an empty root indicates that any (transferable) * token identifier is valid and that no associated * proof needs to be supplied. * @param fulfillments An array of elements allocating offer components * to consideration components. Note that each * consideration component must be fully met in * order for the match operation to be valid. * * @return executions An array of elements indicating the sequence of * transfers performed as part of matching the given * orders. */ function matchAdvancedOrders( AdvancedOrder[] calldata orders, CriteriaResolver[] calldata criteriaResolvers, Fulfillment[] calldata fulfillments ) external payable returns (Execution[] memory executions); /** * @notice Cancel an arbitrary number of orders. Note that only the offerer * or the zone of a given order may cancel it. Callers should ensure * that the intended order was cancelled by calling `getOrderStatus` * and confirming that `isCancelled` returns `true`. * * @param orders The orders to cancel. * * @return cancelled A boolean indicating whether the supplied orders have * been successfully cancelled. */ function cancel(OrderComponents[] calldata orders) external returns (bool cancelled); /** * @notice Validate an arbitrary number of orders, thereby registering their * signatures as valid and allowing the fulfiller to skip signature * verification on fulfillment. Note that validated orders may still * be unfulfillable due to invalid item amounts or other factors; * callers should determine whether validated orders are fulfillable * by simulating the fulfillment call prior to execution. Also note * that anyone can validate a signed order, but only the offerer can * validate an order without supplying a signature. * * @param orders The orders to validate. * * @return validated A boolean indicating whether the supplied orders have * been successfully validated. */ function validate(Order[] calldata orders) external returns (bool validated); /** * @notice Cancel all orders from a given offerer with a given zone in bulk * by incrementing a counter. Note that only the offerer may * increment the counter. * * @return newCounter The new counter. */ function incrementCounter() external returns (uint256 newCounter); /** * @notice Retrieve the order hash for a given order. * * @param order The components of the order. * * @return orderHash The order hash. */ function getOrderHash(OrderComponents calldata order) external view returns (bytes32 orderHash); /** * @notice Retrieve the status of a given order by hash, including whether * the order has been cancelled or validated and the fraction of the * order that has been filled. * * @param orderHash The order hash in question. * * @return isValidated A boolean indicating whether the order in question * has been validated (i.e. previously approved or * partially filled). * @return isCancelled A boolean indicating whether the order in question * has been cancelled. * @return totalFilled The total portion of the order that has been filled * (i.e. the "numerator"). * @return totalSize The total size of the order that is either filled or * unfilled (i.e. the "denominator"). */ function getOrderStatus(bytes32 orderHash) external view returns ( bool isValidated, bool isCancelled, uint256 totalFilled, uint256 totalSize ); /** * @notice Retrieve the current counter for a given offerer. * * @param offerer The offerer in question. * * @return counter The current counter. */ function getCounter(address offerer) external view returns (uint256 counter); /** * @notice Retrieve configuration information for this contract. * * @return version The contract version. * @return domainSeparator The domain separator for this contract. * @return conduitController The conduit Controller set for this contract. */ function information() external view returns ( string memory version, bytes32 domainSeparator, address conduitController ); /** * @notice Retrieve the name of this contract. * * @return contractName The name of this contract. */ function name() external view returns (string memory contractName); }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.7; /* * -------------------------- Disambiguation & Other Notes --------------------- * - The term "head" is used as it is in the documentation for ABI encoding, * but only in reference to dynamic types, i.e. it always refers to the * offset or pointer to the body of a dynamic type. In calldata, the head * is always an offset (relative to the parent object), while in memory, * the head is always the pointer to the body. More information found here: * https://docs.soliditylang.org/en/v0.8.14/abi-spec.html#argument-encoding * - Note that the length of an array is separate from and precedes the * head of the array. * * - The term "body" is used in place of the term "head" used in the ABI * documentation. It refers to the start of the data for a dynamic type, * e.g. the first word of a struct or the first word of the first element * in an array. * * - The term "pointer" is used to describe the absolute position of a value * and never an offset relative to another value. * - The suffix "_ptr" refers to a memory pointer. * - The suffix "_cdPtr" refers to a calldata pointer. * * - The term "offset" is used to describe the position of a value relative * to some parent value. For example, OrderParameters_conduit_offset is the * offset to the "conduit" value in the OrderParameters struct relative to * the start of the body. * - Note: Offsets are used to derive pointers. * * - Some structs have pointers defined for all of their fields in this file. * Lines which are commented out are fields that are not used in the * codebase but have been left in for readability. */ // Declare constants for name, version, and reentrancy sentinel values. // Name is right padded, so it touches the length which is left padded. This // enables writing both values at once. Length goes at byte 95 in memory, and // name fills bytes 96-109, so both values can be written left-padded to 77. uint256 constant NameLengthPtr = 77; uint256 constant NameWithLength = 0x0d436F6E73696465726174696F6E; uint256 constant Version = 0x312e31; uint256 constant Version_length = 3; uint256 constant Version_shift = 0xe8; uint256 constant _NOT_ENTERED = 1; uint256 constant _ENTERED = 2; // Common Offsets // Offsets for identically positioned fields shared by: // OfferItem, ConsiderationItem, SpentItem, ReceivedItem uint256 constant Common_token_offset = 0x20; uint256 constant Common_identifier_offset = 0x40; uint256 constant Common_amount_offset = 0x60; uint256 constant ReceivedItem_size = 0xa0; uint256 constant ReceivedItem_amount_offset = 0x60; uint256 constant ReceivedItem_recipient_offset = 0x80; uint256 constant ReceivedItem_CommonParams_size = 0x60; uint256 constant ConsiderationItem_recipient_offset = 0xa0; // Store the same constant in an abbreviated format for a line length fix. uint256 constant ConsiderItem_recipient_offset = 0xa0; uint256 constant Execution_offerer_offset = 0x20; uint256 constant Execution_conduit_offset = 0x40; uint256 constant InvalidFulfillmentComponentData_error_signature = ( 0x7fda727900000000000000000000000000000000000000000000000000000000 ); uint256 constant InvalidFulfillmentComponentData_error_len = 0x04; uint256 constant Panic_error_signature = ( 0x4e487b7100000000000000000000000000000000000000000000000000000000 ); uint256 constant Panic_error_offset = 0x04; uint256 constant Panic_error_length = 0x24; uint256 constant Panic_arithmetic = 0x11; uint256 constant MissingItemAmount_error_signature = ( 0x91b3e51400000000000000000000000000000000000000000000000000000000 ); uint256 constant MissingItemAmount_error_len = 0x04; uint256 constant OrderParameters_offer_head_offset = 0x40; uint256 constant OrderParameters_consideration_head_offset = 0x60; uint256 constant OrderParameters_conduit_offset = 0x120; uint256 constant OrderParameters_counter_offset = 0x140; uint256 constant Fulfillment_itemIndex_offset = 0x20; uint256 constant AdvancedOrder_numerator_offset = 0x20; uint256 constant AlmostOneWord = 0x1f; uint256 constant OneWord = 0x20; uint256 constant TwoWords = 0x40; uint256 constant ThreeWords = 0x60; uint256 constant FourWords = 0x80; uint256 constant FiveWords = 0xa0; uint256 constant FreeMemoryPointerSlot = 0x40; uint256 constant ZeroSlot = 0x60; uint256 constant DefaultFreeMemoryPointer = 0x80; uint256 constant Slot0x80 = 0x80; uint256 constant Slot0xA0 = 0xa0; uint256 constant BasicOrder_endAmount_cdPtr = 0x104; uint256 constant BasicOrder_common_params_size = 0xa0; uint256 constant BasicOrder_considerationHashesArray_ptr = 0x160; uint256 constant EIP712_Order_size = 0x180; uint256 constant EIP712_OfferItem_size = 0xc0; uint256 constant EIP712_ConsiderationItem_size = 0xe0; uint256 constant AdditionalRecipients_size = 0x40; uint256 constant EIP712_DomainSeparator_offset = 0x02; uint256 constant EIP712_OrderHash_offset = 0x22; uint256 constant EIP712_DigestPayload_size = 0x42; uint256 constant receivedItemsHash_ptr = 0x60; /* * Memory layout in _prepareBasicFulfillmentFromCalldata of * data for OrderFulfilled * * event OrderFulfilled( * bytes32 orderHash, * address indexed offerer, * address indexed zone, * address fulfiller, * SpentItem[] offer, * > (itemType, token, id, amount) * ReceivedItem[] consideration * > (itemType, token, id, amount, recipient) * ) * * - 0x00: orderHash * - 0x20: fulfiller * - 0x40: offer offset (0x80) * - 0x60: consideration offset (0x120) * - 0x80: offer.length (1) * - 0xa0: offerItemType * - 0xc0: offerToken * - 0xe0: offerIdentifier * - 0x100: offerAmount * - 0x120: consideration.length (1 + additionalRecipients.length) * - 0x140: considerationItemType * - 0x160: considerationToken * - 0x180: considerationIdentifier * - 0x1a0: considerationAmount * - 0x1c0: considerationRecipient * - ... */ // Minimum length of the OrderFulfilled event data. // Must be added to the size of the ReceivedItem array for additionalRecipients // (0xa0 * additionalRecipients.length) to calculate full size of the buffer. uint256 constant OrderFulfilled_baseSize = 0x1e0; uint256 constant OrderFulfilled_selector = ( 0x9d9af8e38d66c62e2c12f0225249fd9d721c54b83f48d9352c97c6cacdcb6f31 ); // Minimum offset in memory to OrderFulfilled event data. // Must be added to the size of the EIP712 hash array for additionalRecipients // (32 * additionalRecipients.length) to calculate the pointer to event data. uint256 constant OrderFulfilled_baseOffset = 0x180; uint256 constant OrderFulfilled_consideration_length_baseOffset = 0x2a0; uint256 constant OrderFulfilled_offer_length_baseOffset = 0x200; // uint256 constant OrderFulfilled_orderHash_offset = 0x00; uint256 constant OrderFulfilled_fulfiller_offset = 0x20; uint256 constant OrderFulfilled_offer_head_offset = 0x40; uint256 constant OrderFulfilled_offer_body_offset = 0x80; uint256 constant OrderFulfilled_consideration_head_offset = 0x60; uint256 constant OrderFulfilled_consideration_body_offset = 0x120; // BasicOrderParameters uint256 constant BasicOrder_parameters_cdPtr = 0x04; uint256 constant BasicOrder_considerationToken_cdPtr = 0x24; // uint256 constant BasicOrder_considerationIdentifier_cdPtr = 0x44; uint256 constant BasicOrder_considerationAmount_cdPtr = 0x64; uint256 constant BasicOrder_offerer_cdPtr = 0x84; uint256 constant BasicOrder_zone_cdPtr = 0xa4; uint256 constant BasicOrder_offerToken_cdPtr = 0xc4; // uint256 constant BasicOrder_offerIdentifier_cdPtr = 0xe4; uint256 constant BasicOrder_offerAmount_cdPtr = 0x104; uint256 constant BasicOrder_basicOrderType_cdPtr = 0x124; uint256 constant BasicOrder_startTime_cdPtr = 0x144; // uint256 constant BasicOrder_endTime_cdPtr = 0x164; // uint256 constant BasicOrder_zoneHash_cdPtr = 0x184; // uint256 constant BasicOrder_salt_cdPtr = 0x1a4; uint256 constant BasicOrder_offererConduit_cdPtr = 0x1c4; uint256 constant BasicOrder_fulfillerConduit_cdPtr = 0x1e4; uint256 constant BasicOrder_totalOriginalAdditionalRecipients_cdPtr = 0x204; uint256 constant BasicOrder_additionalRecipients_head_cdPtr = 0x224; uint256 constant BasicOrder_signature_cdPtr = 0x244; uint256 constant BasicOrder_additionalRecipients_length_cdPtr = 0x264; uint256 constant BasicOrder_additionalRecipients_data_cdPtr = 0x284; uint256 constant BasicOrder_parameters_ptr = 0x20; uint256 constant BasicOrder_basicOrderType_range = 0x18; // 24 values /* * Memory layout in _prepareBasicFulfillmentFromCalldata of * EIP712 data for ConsiderationItem * - 0x80: ConsiderationItem EIP-712 typehash (constant) * - 0xa0: itemType * - 0xc0: token * - 0xe0: identifier * - 0x100: startAmount * - 0x120: endAmount * - 0x140: recipient */ uint256 constant BasicOrder_considerationItem_typeHash_ptr = 0x80; // memoryPtr uint256 constant BasicOrder_considerationItem_itemType_ptr = 0xa0; uint256 constant BasicOrder_considerationItem_token_ptr = 0xc0; uint256 constant BasicOrder_considerationItem_identifier_ptr = 0xe0; uint256 constant BasicOrder_considerationItem_startAmount_ptr = 0x100; uint256 constant BasicOrder_considerationItem_endAmount_ptr = 0x120; // uint256 constant BasicOrder_considerationItem_recipient_ptr = 0x140; /* * Memory layout in _prepareBasicFulfillmentFromCalldata of * EIP712 data for OfferItem * - 0x80: OfferItem EIP-712 typehash (constant) * - 0xa0: itemType * - 0xc0: token * - 0xe0: identifier (reused for offeredItemsHash) * - 0x100: startAmount * - 0x120: endAmount */ uint256 constant BasicOrder_offerItem_typeHash_ptr = DefaultFreeMemoryPointer; uint256 constant BasicOrder_offerItem_itemType_ptr = 0xa0; uint256 constant BasicOrder_offerItem_token_ptr = 0xc0; // uint256 constant BasicOrder_offerItem_identifier_ptr = 0xe0; // uint256 constant BasicOrder_offerItem_startAmount_ptr = 0x100; uint256 constant BasicOrder_offerItem_endAmount_ptr = 0x120; /* * Memory layout in _prepareBasicFulfillmentFromCalldata of * EIP712 data for Order * - 0x80: Order EIP-712 typehash (constant) * - 0xa0: orderParameters.offerer * - 0xc0: orderParameters.zone * - 0xe0: keccak256(abi.encodePacked(offerHashes)) * - 0x100: keccak256(abi.encodePacked(considerationHashes)) * - 0x120: orderType * - 0x140: startTime * - 0x160: endTime * - 0x180: zoneHash * - 0x1a0: salt * - 0x1c0: conduit * - 0x1e0: _counters[orderParameters.offerer] (from storage) */ uint256 constant BasicOrder_order_typeHash_ptr = 0x80; uint256 constant BasicOrder_order_offerer_ptr = 0xa0; // uint256 constant BasicOrder_order_zone_ptr = 0xc0; uint256 constant BasicOrder_order_offerHashes_ptr = 0xe0; uint256 constant BasicOrder_order_considerationHashes_ptr = 0x100; uint256 constant BasicOrder_order_orderType_ptr = 0x120; uint256 constant BasicOrder_order_startTime_ptr = 0x140; // uint256 constant BasicOrder_order_endTime_ptr = 0x160; // uint256 constant BasicOrder_order_zoneHash_ptr = 0x180; // uint256 constant BasicOrder_order_salt_ptr = 0x1a0; // uint256 constant BasicOrder_order_conduitKey_ptr = 0x1c0; uint256 constant BasicOrder_order_counter_ptr = 0x1e0; uint256 constant BasicOrder_additionalRecipients_head_ptr = 0x240; uint256 constant BasicOrder_signature_ptr = 0x260; // Signature-related bytes32 constant EIP2098_allButHighestBitMask = ( 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ); bytes32 constant ECDSA_twentySeventhAndTwentyEighthBytesSet = ( 0x0000000000000000000000000000000000000000000000000000000101000000 ); uint256 constant ECDSA_MaxLength = 65; uint256 constant ECDSA_signature_s_offset = 0x40; uint256 constant ECDSA_signature_v_offset = 0x60; bytes32 constant EIP1271_isValidSignature_selector = ( 0x1626ba7e00000000000000000000000000000000000000000000000000000000 ); uint256 constant EIP1271_isValidSignature_signatureHead_negativeOffset = 0x20; uint256 constant EIP1271_isValidSignature_digest_negativeOffset = 0x40; uint256 constant EIP1271_isValidSignature_selector_negativeOffset = 0x44; uint256 constant EIP1271_isValidSignature_calldata_baseLength = 0x64; uint256 constant EIP1271_isValidSignature_signature_head_offset = 0x40; // abi.encodeWithSignature("NoContract(address)") uint256 constant NoContract_error_signature = ( 0x5f15d67200000000000000000000000000000000000000000000000000000000 ); uint256 constant NoContract_error_sig_ptr = 0x0; uint256 constant NoContract_error_token_ptr = 0x4; uint256 constant NoContract_error_length = 0x24; // 4 + 32 == 36 uint256 constant EIP_712_PREFIX = ( 0x1901000000000000000000000000000000000000000000000000000000000000 ); uint256 constant ExtraGasBuffer = 0x20; uint256 constant CostPerWord = 3; uint256 constant MemoryExpansionCoefficient = 0x200; // 512 uint256 constant Create2AddressDerivation_ptr = 0x0b; uint256 constant Create2AddressDerivation_length = 0x55; uint256 constant MaskOverByteTwelve = ( 0x0000000000000000000000ff0000000000000000000000000000000000000000 ); uint256 constant MaskOverLastTwentyBytes = ( 0x000000000000000000000000ffffffffffffffffffffffffffffffffffffffff ); uint256 constant MaskOverFirstFourBytes = ( 0xffffffff00000000000000000000000000000000000000000000000000000000 ); uint256 constant Conduit_execute_signature = ( 0x4ce34aa200000000000000000000000000000000000000000000000000000000 ); uint256 constant MaxUint8 = 0xff; uint256 constant MaxUint120 = 0xffffffffffffffffffffffffffffff; uint256 constant Conduit_execute_ConduitTransfer_ptr = 0x20; uint256 constant Conduit_execute_ConduitTransfer_length = 0x01; uint256 constant Conduit_execute_ConduitTransfer_offset_ptr = 0x04; uint256 constant Conduit_execute_ConduitTransfer_length_ptr = 0x24; uint256 constant Conduit_execute_transferItemType_ptr = 0x44; uint256 constant Conduit_execute_transferToken_ptr = 0x64; uint256 constant Conduit_execute_transferFrom_ptr = 0x84; uint256 constant Conduit_execute_transferTo_ptr = 0xa4; uint256 constant Conduit_execute_transferIdentifier_ptr = 0xc4; uint256 constant Conduit_execute_transferAmount_ptr = 0xe4; uint256 constant OneConduitExecute_size = 0x104; // Sentinel value to indicate that the conduit accumulator is not armed. uint256 constant AccumulatorDisarmed = 0x20; uint256 constant AccumulatorArmed = 0x40; uint256 constant Accumulator_conduitKey_ptr = 0x20; uint256 constant Accumulator_selector_ptr = 0x40; uint256 constant Accumulator_array_offset_ptr = 0x44; uint256 constant Accumulator_array_length_ptr = 0x64; uint256 constant Accumulator_itemSizeOffsetDifference = 0x3c; uint256 constant Accumulator_array_offset = 0x20; uint256 constant Conduit_transferItem_size = 0xc0; uint256 constant Conduit_transferItem_token_ptr = 0x20; uint256 constant Conduit_transferItem_from_ptr = 0x40; uint256 constant Conduit_transferItem_to_ptr = 0x60; uint256 constant Conduit_transferItem_identifier_ptr = 0x80; uint256 constant Conduit_transferItem_amount_ptr = 0xa0; // Declare constant for errors related to amount derivation. // error InexactFraction() @ AmountDerivationErrors.sol uint256 constant InexactFraction_error_signature = ( 0xc63cf08900000000000000000000000000000000000000000000000000000000 ); uint256 constant InexactFraction_error_len = 0x04; // Declare constant for errors related to signature verification. uint256 constant Ecrecover_precompile = 1; uint256 constant Ecrecover_args_size = 0x80; uint256 constant Signature_lower_v = 27; // error BadSignatureV(uint8) @ SignatureVerificationErrors.sol uint256 constant BadSignatureV_error_signature = ( 0x1f003d0a00000000000000000000000000000000000000000000000000000000 ); uint256 constant BadSignatureV_error_offset = 0x04; uint256 constant BadSignatureV_error_length = 0x24; // error InvalidSigner() @ SignatureVerificationErrors.sol uint256 constant InvalidSigner_error_signature = ( 0x815e1d6400000000000000000000000000000000000000000000000000000000 ); uint256 constant InvalidSigner_error_length = 0x04; // error InvalidSignature() @ SignatureVerificationErrors.sol uint256 constant InvalidSignature_error_signature = ( 0x8baa579f00000000000000000000000000000000000000000000000000000000 ); uint256 constant InvalidSignature_error_length = 0x04; // error BadContractSignature() @ SignatureVerificationErrors.sol uint256 constant BadContractSignature_error_signature = ( 0x4f7fb80d00000000000000000000000000000000000000000000000000000000 ); uint256 constant BadContractSignature_error_length = 0x04; uint256 constant NumBitsAfterSelector = 0xe0; // 69 is the lowest modulus for which the remainder // of every selector other than the two match functions // is greater than those of the match functions. uint256 constant NonMatchSelector_MagicModulus = 69; // Of the two match function selectors, the highest // remainder modulo 69 is 29. uint256 constant NonMatchSelector_MagicRemainder = 0x1d;
// SPDX-License-Identifier: MIT pragma solidity ^0.8.13; import { ItemType, Side } from "./ConsiderationEnums.sol"; import { OfferItem, ConsiderationItem, ReceivedItem, OrderParameters, AdvancedOrder, Execution, FulfillmentComponent } from "./ConsiderationStructs.sol"; import "./ConsiderationConstants.sol"; import { FulfillmentApplicationErrors } from "./FulfillmentApplicationErrors.sol"; /** * @title FulfillmentApplier * @author 0age * @notice FulfillmentApplier contains logic related to applying fulfillments, * both as part of order matching (where offer items are matched to * consideration items) as well as fulfilling available orders (where * order items and consideration items are independently aggregated). */ contract FulfillmentApplier is FulfillmentApplicationErrors { /** * @dev Internal pure function to match offer items to consideration items * on a group of orders via a supplied fulfillment. * * @param advancedOrders The orders to match. * @param offerComponents An array designating offer components to * match to consideration components. * @param considerationComponents An array designating consideration * components to match to offer components. * Note that each consideration amount must * be zero in order for the match operation * to be valid. * * @return execution The transfer performed as a result of the fulfillment. */ function _applyFulfillment( AdvancedOrder[] memory advancedOrders, FulfillmentComponent[] calldata offerComponents, FulfillmentComponent[] calldata considerationComponents ) internal pure returns (Execution memory execution) { // Ensure 1+ of both offer and consideration components are supplied. if ( offerComponents.length == 0 || considerationComponents.length == 0 ) { revert OfferAndConsiderationRequiredOnFulfillment(); } // Declare a new Execution struct. Execution memory considerationExecution; // Validate & aggregate consideration items to new Execution object. _aggregateValidFulfillmentConsiderationItems( advancedOrders, considerationComponents, considerationExecution ); // Retrieve the consideration item from the execution struct. ReceivedItem memory considerationItem = considerationExecution.item; // Recipient does not need to be specified because it will always be set // to that of the consideration. // Validate & aggregate offer items to Execution object. _aggregateValidFulfillmentOfferItems( advancedOrders, offerComponents, execution ); // Ensure offer and consideration share types, tokens and identifiers. if ( execution.item.itemType != considerationItem.itemType || execution.item.token != considerationItem.token || execution.item.identifier != considerationItem.identifier ) { revert MismatchedFulfillmentOfferAndConsiderationComponents(); } // If total consideration amount exceeds the offer amount... if (considerationItem.amount > execution.item.amount) { // Retrieve the first consideration component from the fulfillment. FulfillmentComponent memory targetComponent = ( considerationComponents[0] ); // Skip underflow check as the conditional being true implies that // considerationItem.amount > execution.item.amount. unchecked { // Add excess consideration item amount to original order array. advancedOrders[targetComponent.orderIndex] .parameters .consideration[targetComponent.itemIndex] .startAmount = (considerationItem.amount - execution.item.amount); } // Reduce total consideration amount to equal the offer amount. considerationItem.amount = execution.item.amount; } else { // Retrieve the first offer component from the fulfillment. FulfillmentComponent memory targetComponent = offerComponents[0]; // Skip underflow check as the conditional being false implies that // execution.item.amount >= considerationItem.amount. unchecked { // Add excess offer item amount to the original array of orders. advancedOrders[targetComponent.orderIndex] .parameters .offer[targetComponent.itemIndex] .startAmount = (execution.item.amount - considerationItem.amount); } // Reduce total offer amount to equal the consideration amount. execution.item.amount = considerationItem.amount; } // Reuse consideration recipient. execution.item.recipient = considerationItem.recipient; // Return the final execution that will be triggered for relevant items. return execution; // Execution(considerationItem, offerer, conduitKey); } /** * @dev Internal view function to aggregate offer or consideration items * from a group of orders into a single execution via a supplied array * of fulfillment components. Items that are not available to aggregate * will not be included in the aggregated execution. * * @param advancedOrders The orders to aggregate. * @param side The side (i.e. offer or consideration). * @param fulfillmentComponents An array designating item components to * aggregate if part of an available order. * @param fulfillerConduitKey A bytes32 value indicating what conduit, if * any, to source the fulfiller's token * approvals from. The zero hash signifies that * no conduit should be used, with approvals * set directly on this contract. * @param recipient The intended recipient for all received * items. * * @return execution The transfer performed as a result of the fulfillment. */ function _aggregateAvailable( AdvancedOrder[] memory advancedOrders, Side side, FulfillmentComponent[] memory fulfillmentComponents, bytes32 fulfillerConduitKey, address recipient ) internal view returns (Execution memory execution) { // Skip overflow / underflow checks; conditions checked or unreachable. unchecked { // Retrieve fulfillment components array length and place on stack. // Ensure at least one fulfillment component has been supplied. if (fulfillmentComponents.length == 0) { revert MissingFulfillmentComponentOnAggregation(side); } // If the fulfillment components are offer components... if (side == Side.OFFER) { // Set the supplied recipient on the execution item. execution.item.recipient = payable(recipient); // Return execution for aggregated items provided by offerer. _aggregateValidFulfillmentOfferItems( advancedOrders, fulfillmentComponents, execution ); } else { // Otherwise, fulfillment components are consideration // components. Return execution for aggregated items provided by // the fulfiller. _aggregateValidFulfillmentConsiderationItems( advancedOrders, fulfillmentComponents, execution ); // Set the caller as the offerer on the execution. execution.offerer = msg.sender; // Set fulfiller conduit key as the conduit key on execution. execution.conduitKey = fulfillerConduitKey; } // Set the offerer and recipient to null address if execution // amount is zero. This will cause the execution item to be skipped. if (execution.item.amount == 0) { execution.offerer = address(0); execution.item.recipient = payable(0); } } } /** * @dev Internal pure function to aggregate a group of offer items using * supplied directives on which component items are candidates for * aggregation, skipping items on orders that are not available. * * @param advancedOrders The orders to aggregate offer items from. * @param offerComponents An array of FulfillmentComponent structs * indicating the order index and item index of each * candidate offer item for aggregation. * @param execution The execution to apply the aggregation to. */ function _aggregateValidFulfillmentOfferItems( AdvancedOrder[] memory advancedOrders, FulfillmentComponent[] memory offerComponents, Execution memory execution ) internal pure { assembly { // Declare function for reverts on invalid fulfillment data. function throwInvalidFulfillmentComponentData() { // Store the InvalidFulfillmentComponentData error signature. mstore(0, InvalidFulfillmentComponentData_error_signature) // Return, supplying InvalidFulfillmentComponentData signature. revert(0, InvalidFulfillmentComponentData_error_len) } // Declare function for reverts due to arithmetic overflows. function throwOverflow() { // Store the Panic error signature. mstore(0, Panic_error_signature) // Store the arithmetic (0x11) panic code as initial argument. mstore(Panic_error_offset, Panic_arithmetic) // Return, supplying Panic signature and arithmetic code. revert(0, Panic_error_length) } // Get position in offerComponents head. let fulfillmentHeadPtr := add(offerComponents, OneWord) // Retrieve the order index using the fulfillment pointer. let orderIndex := mload(mload(fulfillmentHeadPtr)) // Ensure that the order index is not out of range. if iszero(lt(orderIndex, mload(advancedOrders))) { throwInvalidFulfillmentComponentData() } // Read advancedOrders[orderIndex] pointer from its array head. let orderPtr := mload( // Calculate head position of advancedOrders[orderIndex]. add(add(advancedOrders, OneWord), mul(orderIndex, OneWord)) ) // Read the pointer to OrderParameters from the AdvancedOrder. let paramsPtr := mload(orderPtr) // Load the offer array pointer. let offerArrPtr := mload( add(paramsPtr, OrderParameters_offer_head_offset) ) // Retrieve item index using an offset of the fulfillment pointer. let itemIndex := mload( add(mload(fulfillmentHeadPtr), Fulfillment_itemIndex_offset) ) // Only continue if the fulfillment is not invalid. if iszero(lt(itemIndex, mload(offerArrPtr))) { throwInvalidFulfillmentComponentData() } // Retrieve consideration item pointer using the item index. let offerItemPtr := mload( add( // Get pointer to beginning of receivedItem. add(offerArrPtr, OneWord), // Calculate offset to pointer for desired order. mul(itemIndex, OneWord) ) ) // Declare a variable for the final aggregated item amount. let amount := 0 // Create variable to track errors encountered with amount. let errorBuffer := 0 // Only add offer amount to execution amount on a nonzero numerator. if mload(add(orderPtr, AdvancedOrder_numerator_offset)) { // Retrieve amount pointer using consideration item pointer. let amountPtr := add(offerItemPtr, Common_amount_offset) // Set the amount. amount := mload(amountPtr) // Zero out amount on item to indicate it is credited. mstore(amountPtr, 0) // Buffer indicating whether issues were found. errorBuffer := iszero(amount) } // Retrieve the received item pointer. let receivedItemPtr := mload(execution) // Set the item type on the received item. mstore(receivedItemPtr, mload(offerItemPtr)) // Set the token on the received item. mstore( add(receivedItemPtr, Common_token_offset), mload(add(offerItemPtr, Common_token_offset)) ) // Set the identifier on the received item. mstore( add(receivedItemPtr, Common_identifier_offset), mload(add(offerItemPtr, Common_identifier_offset)) ) // Set the offerer on returned execution using order pointer. mstore(add(execution, Execution_offerer_offset), mload(paramsPtr)) // Set conduitKey on returned execution via offset of order pointer. mstore( add(execution, Execution_conduit_offset), mload(add(paramsPtr, OrderParameters_conduit_offset)) ) // Calculate the hash of (itemType, token, identifier). let dataHash := keccak256( receivedItemPtr, ReceivedItem_CommonParams_size ) // Get position one word past last element in head of array. let endPtr := add( offerComponents, mul(mload(offerComponents), OneWord) ) // Iterate over remaining offer components. // prettier-ignore for {} lt(fulfillmentHeadPtr, endPtr) {} { // Increment the pointer to the fulfillment head by one word. fulfillmentHeadPtr := add(fulfillmentHeadPtr, OneWord) // Get the order index using the fulfillment pointer. orderIndex := mload(mload(fulfillmentHeadPtr)) // Ensure the order index is in range. if iszero(lt(orderIndex, mload(advancedOrders))) { throwInvalidFulfillmentComponentData() } // Get pointer to AdvancedOrder element. orderPtr := mload( add( add(advancedOrders, OneWord), mul(orderIndex, OneWord) ) ) // Only continue if numerator is not zero. if iszero(mload( add(orderPtr, AdvancedOrder_numerator_offset) )) { continue } // Read the pointer to OrderParameters from the AdvancedOrder. paramsPtr := mload(orderPtr) // Load offer array pointer. offerArrPtr := mload( add( paramsPtr, OrderParameters_offer_head_offset ) ) // Get the item index using the fulfillment pointer. itemIndex := mload(add(mload(fulfillmentHeadPtr), OneWord)) // Throw if itemIndex is out of the range of array. if iszero( lt(itemIndex, mload(offerArrPtr)) ) { throwInvalidFulfillmentComponentData() } // Retrieve offer item pointer using index. offerItemPtr := mload( add( // Get pointer to beginning of receivedItem. add(offerArrPtr, OneWord), // Use offset to pointer for desired order. mul(itemIndex, OneWord) ) ) // Retrieve amount pointer using offer item pointer. let amountPtr := add( offerItemPtr, Common_amount_offset ) // Add offer amount to execution amount. let newAmount := add(amount, mload(amountPtr)) // Update error buffer: 1 = zero amount, 2 = overflow, 3 = both. errorBuffer := or( errorBuffer, or( shl(1, lt(newAmount, amount)), iszero(mload(amountPtr)) ) ) // Update the amount to the new, summed amount. amount := newAmount // Zero out amount on original item to indicate it is credited. mstore(amountPtr, 0) // Ensure the indicated item matches original item. if iszero( and( and( // The offerer must match on both items. eq( mload(paramsPtr), mload( add(execution, Execution_offerer_offset) ) ), // The conduit key must match on both items. eq( mload( add( paramsPtr, OrderParameters_conduit_offset ) ), mload( add( execution, Execution_conduit_offset ) ) ) ), // The itemType, token, and identifier must match. eq( dataHash, keccak256( offerItemPtr, ReceivedItem_CommonParams_size ) ) ) ) { // Throw if any of the requirements are not met. throwInvalidFulfillmentComponentData() } } // Write final amount to execution. mstore(add(mload(execution), Common_amount_offset), amount) // Determine whether the error buffer contains a nonzero error code. if errorBuffer { // If errorBuffer is 1, an item had an amount of zero. if eq(errorBuffer, 1) { // Store the MissingItemAmount error signature. mstore(0, MissingItemAmount_error_signature) // Return, supplying MissingItemAmount signature. revert(0, MissingItemAmount_error_len) } // If errorBuffer is not 1 or 0, the sum overflowed. // Panic! throwOverflow() } } } /** * @dev Internal pure function to aggregate a group of consideration items * using supplied directives on which component items are candidates * for aggregation, skipping items on orders that are not available. * * @param advancedOrders The orders to aggregate consideration * items from. * @param considerationComponents An array of FulfillmentComponent structs * indicating the order index and item index * of each candidate consideration item for * aggregation. * @param execution The execution to apply the aggregation to. */ function _aggregateValidFulfillmentConsiderationItems( AdvancedOrder[] memory advancedOrders, FulfillmentComponent[] memory considerationComponents, Execution memory execution ) internal pure { // Utilize assembly in order to efficiently aggregate the items. assembly { // Declare function for reverts on invalid fulfillment data. function throwInvalidFulfillmentComponentData() { // Store the InvalidFulfillmentComponentData error signature. mstore(0, InvalidFulfillmentComponentData_error_signature) // Return, supplying InvalidFulfillmentComponentData signature. revert(0, InvalidFulfillmentComponentData_error_len) } // Declare function for reverts due to arithmetic overflows. function throwOverflow() { // Store the Panic error signature. mstore(0, Panic_error_signature) // Store the arithmetic (0x11) panic code as initial argument. mstore(Panic_error_offset, Panic_arithmetic) // Return, supplying Panic signature and arithmetic code. revert(0, Panic_error_length) } // Get position in considerationComponents head. let fulfillmentHeadPtr := add(considerationComponents, OneWord) // Retrieve the order index using the fulfillment pointer. let orderIndex := mload(mload(fulfillmentHeadPtr)) // Ensure that the order index is not out of range. if iszero(lt(orderIndex, mload(advancedOrders))) { throwInvalidFulfillmentComponentData() } // Read advancedOrders[orderIndex] pointer from its array head. let orderPtr := mload( // Calculate head position of advancedOrders[orderIndex]. add(add(advancedOrders, OneWord), mul(orderIndex, OneWord)) ) // Load consideration array pointer. let considerationArrPtr := mload( add( // Read pointer to OrderParameters from the AdvancedOrder. mload(orderPtr), OrderParameters_consideration_head_offset ) ) // Retrieve item index using an offset of the fulfillment pointer. let itemIndex := mload( add(mload(fulfillmentHeadPtr), Fulfillment_itemIndex_offset) ) // Ensure that the order index is not out of range. if iszero(lt(itemIndex, mload(considerationArrPtr))) { throwInvalidFulfillmentComponentData() } // Retrieve consideration item pointer using the item index. let considerationItemPtr := mload( add( // Get pointer to beginning of receivedItem. add(considerationArrPtr, OneWord), // Calculate offset to pointer for desired order. mul(itemIndex, OneWord) ) ) // Declare a variable for the final aggregated item amount. let amount := 0 // Create variable to track errors encountered with amount. let errorBuffer := 0 // Only add consideration amount to execution amount if numerator is // greater than zero. if mload(add(orderPtr, AdvancedOrder_numerator_offset)) { // Retrieve amount pointer using consideration item pointer. let amountPtr := add(considerationItemPtr, Common_amount_offset) // Set the amount. amount := mload(amountPtr) // Set error bit if amount is zero. errorBuffer := iszero(amount) // Zero out amount on item to indicate it is credited. mstore(amountPtr, 0) } // Retrieve ReceivedItem pointer from Execution. let receivedItem := mload(execution) // Set the item type on the received item. mstore(receivedItem, mload(considerationItemPtr)) // Set the token on the received item. mstore( add(receivedItem, Common_token_offset), mload(add(considerationItemPtr, Common_token_offset)) ) // Set the identifier on the received item. mstore( add(receivedItem, Common_identifier_offset), mload(add(considerationItemPtr, Common_identifier_offset)) ) // Set the recipient on the received item. mstore( add(receivedItem, ReceivedItem_recipient_offset), mload( add( considerationItemPtr, ConsiderationItem_recipient_offset ) ) ) // Calculate the hash of (itemType, token, identifier). let dataHash := keccak256( receivedItem, ReceivedItem_CommonParams_size ) // Get position one word past last element in head of array. let endPtr := add( considerationComponents, mul(mload(considerationComponents), OneWord) ) // Iterate over remaining offer components. // prettier-ignore for {} lt(fulfillmentHeadPtr, endPtr) {} { // Increment position in considerationComponents head. fulfillmentHeadPtr := add(fulfillmentHeadPtr, OneWord) // Get the order index using the fulfillment pointer. orderIndex := mload(mload(fulfillmentHeadPtr)) // Ensure the order index is in range. if iszero(lt(orderIndex, mload(advancedOrders))) { throwInvalidFulfillmentComponentData() } // Get pointer to AdvancedOrder element. orderPtr := mload( add( add(advancedOrders, OneWord), mul(orderIndex, OneWord) ) ) // Only continue if numerator is not zero. if iszero( mload(add(orderPtr, AdvancedOrder_numerator_offset)) ) { continue } // Load consideration array pointer from OrderParameters. considerationArrPtr := mload( add( // Get pointer to OrderParameters from AdvancedOrder. mload(orderPtr), OrderParameters_consideration_head_offset ) ) // Get the item index using the fulfillment pointer. itemIndex := mload(add(mload(fulfillmentHeadPtr), OneWord)) // Check if itemIndex is within the range of array. if iszero(lt(itemIndex, mload(considerationArrPtr))) { throwInvalidFulfillmentComponentData() } // Retrieve consideration item pointer using index. considerationItemPtr := mload( add( // Get pointer to beginning of receivedItem. add(considerationArrPtr, OneWord), // Use offset to pointer for desired order. mul(itemIndex, OneWord) ) ) // Retrieve amount pointer using consideration item pointer. let amountPtr := add( considerationItemPtr, Common_amount_offset ) // Add offer amount to execution amount. let newAmount := add(amount, mload(amountPtr)) // Update error buffer: 1 = zero amount, 2 = overflow, 3 = both. errorBuffer := or( errorBuffer, or( shl(1, lt(newAmount, amount)), iszero(mload(amountPtr)) ) ) // Update the amount to the new, summed amount. amount := newAmount // Zero out amount on original item to indicate it is credited. mstore(amountPtr, 0) // Ensure the indicated item matches original item. if iszero( and( // Item recipients must match. eq( mload( add( considerationItemPtr, ConsiderItem_recipient_offset ) ), mload( add( receivedItem, ReceivedItem_recipient_offset ) ) ), // The itemType, token, identifier must match. eq( dataHash, keccak256( considerationItemPtr, ReceivedItem_CommonParams_size ) ) ) ) { // Throw if any of the requirements are not met. throwInvalidFulfillmentComponentData() } } // Write final amount to execution. mstore(add(receivedItem, Common_amount_offset), amount) // Determine whether the error buffer contains a nonzero error code. if errorBuffer { // If errorBuffer is 1, an item had an amount of zero. if eq(errorBuffer, 1) { // Store the MissingItemAmount error signature. mstore(0, MissingItemAmount_error_signature) // Return, supplying MissingItemAmount signature. revert(0, MissingItemAmount_error_len) } // If errorBuffer is not 1 or 0, the sum overflowed. // Panic! throwOverflow() } } } }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.13; import { ItemType } from "./ConsiderationEnums.sol"; // prettier-ignore import { OfferItem, ConsiderationItem, SpentItem, ReceivedItem, OrderParameters, Order, AdvancedOrder, CriteriaResolver } from "./ConsiderationStructs.sol"; import { BasicOrderFulfiller } from "./BasicOrderFulfiller.sol"; import { CriteriaResolution } from "./CriteriaResolution.sol"; import { AmountDeriver } from "./AmountDeriver.sol"; import "./ConsiderationConstants.sol"; /** * @title OrderFulfiller * @author 0age * @notice OrderFulfiller contains logic related to order fulfillment where a * single order is being fulfilled and where basic order fulfillment is * not available as an option. */ contract OrderFulfiller is BasicOrderFulfiller, CriteriaResolution, AmountDeriver { /** * @dev Derive and set hashes, reference chainId, and associated domain * separator during deployment. * * @param conduitController A contract that deploys conduits, or proxies * that may optionally be used to transfer approved * ERC20/721/1155 tokens. */ constructor(address conduitController) BasicOrderFulfiller(conduitController) {} /** * @dev Internal function to validate an order and update its status, adjust * prices based on current time, apply criteria resolvers, determine * what portion to fill, and transfer relevant tokens. * * @param advancedOrder The order to fulfill as well as the fraction * to fill. Note that all offer and consideration * components must divide with no remainder for * the partial fill to be valid. * @param criteriaResolvers An array where each element contains a * reference to a specific offer or * consideration, a token identifier, and a proof * that the supplied token identifier is * contained in the order's merkle root. Note * that a criteria of zero indicates that any * (transferable) token identifier is valid and * that no proof needs to be supplied. * @param fulfillerConduitKey A bytes32 value indicating what conduit, if * any, to source the fulfiller's token approvals * from. The zero hash signifies that no conduit * should be used, with direct approvals set on * Consideration. * @param recipient The intended recipient for all received items. * * @return A boolean indicating whether the order has been fulfilled. */ function _validateAndFulfillAdvancedOrder( AdvancedOrder memory advancedOrder, CriteriaResolver[] memory criteriaResolvers, bytes32 fulfillerConduitKey, address recipient ) internal returns (bool) { // Ensure this function cannot be triggered during a reentrant call. _setReentrancyGuard(); // Declare empty bytes32 array (unused, will remain empty). bytes32[] memory priorOrderHashes; // Validate order, update status, and determine fraction to fill. ( bytes32 orderHash, uint256 fillNumerator, uint256 fillDenominator ) = _validateOrderAndUpdateStatus( advancedOrder, criteriaResolvers, true, priorOrderHashes ); // Create an array with length 1 containing the order. AdvancedOrder[] memory advancedOrders = new AdvancedOrder[](1); // Populate the order as the first and only element of the new array. advancedOrders[0] = advancedOrder; // Apply criteria resolvers using generated orders and details arrays. _applyCriteriaResolvers(advancedOrders, criteriaResolvers); // Retrieve the order parameters after applying criteria resolvers. OrderParameters memory orderParameters = advancedOrders[0].parameters; // Perform each item transfer with the appropriate fractional amount. _applyFractionsAndTransferEach( orderParameters, fillNumerator, fillDenominator, fulfillerConduitKey, recipient ); // Emit an event signifying that the order has been fulfilled. _emitOrderFulfilledEvent( orderHash, orderParameters.offerer, orderParameters.zone, recipient, orderParameters.offer, orderParameters.consideration ); // Clear the reentrancy guard. _clearReentrancyGuard(); return true; } /** * @dev Internal function to transfer each item contained in a given single * order fulfillment after applying a respective fraction to the amount * being transferred. * * @param orderParameters The parameters for the fulfilled order. * @param numerator A value indicating the portion of the order * that should be filled. * @param denominator A value indicating the total order size. * @param fulfillerConduitKey A bytes32 value indicating what conduit, if * any, to source the fulfiller's token approvals * from. The zero hash signifies that no conduit * should be used, with direct approvals set on * Consideration. * @param recipient The intended recipient for all received items. */ function _applyFractionsAndTransferEach( OrderParameters memory orderParameters, uint256 numerator, uint256 denominator, bytes32 fulfillerConduitKey, address recipient ) internal { // Read start time & end time from order parameters and place on stack. uint256 startTime = orderParameters.startTime; uint256 endTime = orderParameters.endTime; // Initialize an accumulator array. From this point forward, no new // memory regions can be safely allocated until the accumulator is no // longer being utilized, as the accumulator operates in an open-ended // fashion from this memory pointer; existing memory may still be // accessed and modified, however. bytes memory accumulator = new bytes(AccumulatorDisarmed); // As of solidity 0.6.0, inline assembly cannot directly access function // definitions, but can still access locally scoped function variables. // This means that in order to recast the type of a function, we need to // create a local variable to reference the internal function definition // (using the same type) and a local variable with the desired type, // and then cast the original function pointer to the desired type. /** * Repurpose existing OfferItem memory regions on the offer array for * the order by overriding the _transfer function pointer to accept a * modified OfferItem argument in place of the usual ReceivedItem: * * ========= OfferItem ========== ====== ReceivedItem ====== * ItemType itemType; ------------> ItemType itemType; * address token; ----------------> address token; * uint256 identifierOrCriteria; -> uint256 identifier; * uint256 startAmount; ----------> uint256 amount; * uint256 endAmount; ------------> address recipient; */ // Declare a nested scope to minimize stack depth. unchecked { // Declare a virtual function pointer taking an OfferItem argument. function(OfferItem memory, address, bytes32, bytes memory) internal _transferOfferItem; { // Assign _transfer function to a new function pointer (it takes // a ReceivedItem as its initial argument) function(ReceivedItem memory, address, bytes32, bytes memory) internal _transferReceivedItem = _transfer; // Utilize assembly to override the virtual function pointer. assembly { // Cast initial ReceivedItem type to an OfferItem type. _transferOfferItem := _transferReceivedItem } } // Read offer array length from memory and place on stack. uint256 totalOfferItems = orderParameters.offer.length; // Iterate over each offer on the order. // Skip overflow check as for loop is indexed starting at zero. for (uint256 i = 0; i < totalOfferItems; ++i) { // Retrieve the offer item. OfferItem memory offerItem = orderParameters.offer[i]; // Offer items for the native token can not be received // outside of a match order function. if (offerItem.itemType == ItemType.NATIVE) { revert InvalidNativeOfferItem(); } // Declare an additional nested scope to minimize stack depth. { // Apply fill fraction to get offer item amount to transfer. uint256 amount = _applyFraction( offerItem.startAmount, offerItem.endAmount, numerator, denominator, startTime, endTime, false ); // Utilize assembly to set overloaded offerItem arguments. assembly { // Write new fractional amount to startAmount as amount. mstore( add(offerItem, ReceivedItem_amount_offset), amount ) // Write recipient to endAmount. mstore( add(offerItem, ReceivedItem_recipient_offset), recipient ) } } // Transfer the item from the offerer to the recipient. _transferOfferItem( offerItem, orderParameters.offerer, orderParameters.conduitKey, accumulator ); } } // Put ether value supplied by the caller on the stack. uint256 etherRemaining = msg.value; /** * Repurpose existing ConsiderationItem memory regions on the * consideration array for the order by overriding the _transfer * function pointer to accept a modified ConsiderationItem argument in * place of the usual ReceivedItem: * * ====== ConsiderationItem ===== ====== ReceivedItem ====== * ItemType itemType; ------------> ItemType itemType; * address token; ----------------> address token; * uint256 identifierOrCriteria;--> uint256 identifier; * uint256 startAmount; ----------> uint256 amount; * uint256 endAmount; /----> address recipient; * address recipient; ------/ */ // Declare a nested scope to minimize stack depth. unchecked { // Declare virtual function pointer with ConsiderationItem argument. function(ConsiderationItem memory, address, bytes32, bytes memory) internal _transferConsiderationItem; { // Reassign _transfer function to a new function pointer (it // takes a ReceivedItem as its initial argument). function(ReceivedItem memory, address, bytes32, bytes memory) internal _transferReceivedItem = _transfer; // Utilize assembly to override the virtual function pointer. assembly { // Cast ReceivedItem type to ConsiderationItem type. _transferConsiderationItem := _transferReceivedItem } } // Read consideration array length from memory and place on stack. uint256 totalConsiderationItems = orderParameters .consideration .length; // Iterate over each consideration item on the order. // Skip overflow check as for loop is indexed starting at zero. for (uint256 i = 0; i < totalConsiderationItems; ++i) { // Retrieve the consideration item. ConsiderationItem memory considerationItem = ( orderParameters.consideration[i] ); // Apply fraction & derive considerationItem amount to transfer. uint256 amount = _applyFraction( considerationItem.startAmount, considerationItem.endAmount, numerator, denominator, startTime, endTime, true ); // Use assembly to set overloaded considerationItem arguments. assembly { // Write derived fractional amount to startAmount as amount. mstore( add(considerationItem, ReceivedItem_amount_offset), amount ) // Write original recipient to endAmount as recipient. mstore( add(considerationItem, ReceivedItem_recipient_offset), mload( add( considerationItem, ConsiderationItem_recipient_offset ) ) ) } // Reduce available value if offer spent ETH or a native token. if (considerationItem.itemType == ItemType.NATIVE) { // Ensure that sufficient native tokens are still available. if (amount > etherRemaining) { revert InsufficientEtherSupplied(); } // Skip underflow check as a comparison has just been made. etherRemaining -= amount; } // Transfer item from caller to recipient specified by the item. _transferConsiderationItem( considerationItem, msg.sender, fulfillerConduitKey, accumulator ); } } // Trigger any remaining accumulated transfers via call to the conduit. _triggerIfArmed(accumulator); // If any ether remains after fulfillments... if (etherRemaining != 0) { // return it to the caller. _transferEth(payable(msg.sender), etherRemaining); } } /** * @dev Internal function to emit an OrderFulfilled event. OfferItems are * translated into SpentItems and ConsiderationItems are translated * into ReceivedItems. * * @param orderHash The order hash. * @param offerer The offerer for the order. * @param zone The zone for the order. * @param fulfiller The fulfiller of the order, or the null address if * the order was fulfilled via order matching. * @param offer The offer items for the order. * @param consideration The consideration items for the order. */ function _emitOrderFulfilledEvent( bytes32 orderHash, address offerer, address zone, address fulfiller, OfferItem[] memory offer, ConsiderationItem[] memory consideration ) internal { // Cast already-modified offer memory region as spent items. SpentItem[] memory spentItems; assembly { spentItems := offer } // Cast already-modified consideration memory region as received items. ReceivedItem[] memory receivedItems; assembly { receivedItems := consideration } // Emit an event signifying that the order has been fulfilled. emit OrderFulfilled( orderHash, offerer, zone, fulfiller, spentItems, receivedItems ); } /** * @dev Internal pure function to convert an order to an advanced order with * numerator and denominator of 1 and empty extraData. * * @param order The order to convert. * * @return advancedOrder The new advanced order. */ function _convertOrderToAdvanced(Order calldata order) internal pure returns (AdvancedOrder memory advancedOrder) { // Convert to partial order (1/1 or full fill) and return new value. advancedOrder = AdvancedOrder( order.parameters, 1, 1, order.signature, "" ); } /** * @dev Internal pure function to convert an array of orders to an array of * advanced orders with numerator and denominator of 1. * * @param orders The orders to convert. * * @return advancedOrders The new array of partial orders. */ function _convertOrdersToAdvanced(Order[] calldata orders) internal pure returns (AdvancedOrder[] memory advancedOrders) { // Read the number of orders from calldata and place on the stack. uint256 totalOrders = orders.length; // Allocate new empty array for each partial order in memory. advancedOrders = new AdvancedOrder[](totalOrders); // Skip overflow check as the index for the loop starts at zero. unchecked { // Iterate over the given orders. for (uint256 i = 0; i < totalOrders; ++i) { // Convert to partial order (1/1 or full fill) and update array. advancedOrders[i] = _convertOrderToAdvanced(orders[i]); } } // Return the array of advanced orders. return advancedOrders; } }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.7; // prettier-ignore enum OrderType { // 0: no partial fills, anyone can execute FULL_OPEN, // 1: partial fills supported, anyone can execute PARTIAL_OPEN, // 2: no partial fills, only offerer or zone can execute FULL_RESTRICTED, // 3: partial fills supported, only offerer or zone can execute PARTIAL_RESTRICTED } // prettier-ignore enum BasicOrderType { // 0: no partial fills, anyone can execute ETH_TO_ERC721_FULL_OPEN, // 1: partial fills supported, anyone can execute ETH_TO_ERC721_PARTIAL_OPEN, // 2: no partial fills, only offerer or zone can execute ETH_TO_ERC721_FULL_RESTRICTED, // 3: partial fills supported, only offerer or zone can execute ETH_TO_ERC721_PARTIAL_RESTRICTED, // 4: no partial fills, anyone can execute ETH_TO_ERC1155_FULL_OPEN, // 5: partial fills supported, anyone can execute ETH_TO_ERC1155_PARTIAL_OPEN, // 6: no partial fills, only offerer or zone can execute ETH_TO_ERC1155_FULL_RESTRICTED, // 7: partial fills supported, only offerer or zone can execute ETH_TO_ERC1155_PARTIAL_RESTRICTED, // 8: no partial fills, anyone can execute ERC20_TO_ERC721_FULL_OPEN, // 9: partial fills supported, anyone can execute ERC20_TO_ERC721_PARTIAL_OPEN, // 10: no partial fills, only offerer or zone can execute ERC20_TO_ERC721_FULL_RESTRICTED, // 11: partial fills supported, only offerer or zone can execute ERC20_TO_ERC721_PARTIAL_RESTRICTED, // 12: no partial fills, anyone can execute ERC20_TO_ERC1155_FULL_OPEN, // 13: partial fills supported, anyone can execute ERC20_TO_ERC1155_PARTIAL_OPEN, // 14: no partial fills, only offerer or zone can execute ERC20_TO_ERC1155_FULL_RESTRICTED, // 15: partial fills supported, only offerer or zone can execute ERC20_TO_ERC1155_PARTIAL_RESTRICTED, // 16: no partial fills, anyone can execute ERC721_TO_ERC20_FULL_OPEN, // 17: partial fills supported, anyone can execute ERC721_TO_ERC20_PARTIAL_OPEN, // 18: no partial fills, only offerer or zone can execute ERC721_TO_ERC20_FULL_RESTRICTED, // 19: partial fills supported, only offerer or zone can execute ERC721_TO_ERC20_PARTIAL_RESTRICTED, // 20: no partial fills, anyone can execute ERC1155_TO_ERC20_FULL_OPEN, // 21: partial fills supported, anyone can execute ERC1155_TO_ERC20_PARTIAL_OPEN, // 22: no partial fills, only offerer or zone can execute ERC1155_TO_ERC20_FULL_RESTRICTED, // 23: partial fills supported, only offerer or zone can execute ERC1155_TO_ERC20_PARTIAL_RESTRICTED } // prettier-ignore enum BasicOrderRouteType { // 0: provide Ether (or other native token) to receive offered ERC721 item. ETH_TO_ERC721, // 1: provide Ether (or other native token) to receive offered ERC1155 item. ETH_TO_ERC1155, // 2: provide ERC20 item to receive offered ERC721 item. ERC20_TO_ERC721, // 3: provide ERC20 item to receive offered ERC1155 item. ERC20_TO_ERC1155, // 4: provide ERC721 item to receive offered ERC20 item. ERC721_TO_ERC20, // 5: provide ERC1155 item to receive offered ERC20 item. ERC1155_TO_ERC20 } // prettier-ignore enum ItemType { // 0: ETH on mainnet, MATIC on polygon, etc. NATIVE, // 1: ERC20 items (ERC777 and ERC20 analogues could also technically work) ERC20, // 2: ERC721 items ERC721, // 3: ERC1155 items ERC1155, // 4: ERC721 items where a number of tokenIds are supported ERC721_WITH_CRITERIA, // 5: ERC1155 items where a number of ids are supported ERC1155_WITH_CRITERIA } // prettier-ignore enum Side { // 0: Items that can be spent OFFER, // 1: Items that must be received CONSIDERATION }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.13; // prettier-ignore import { AmountDerivationErrors } from "./AmountDerivationErrors.sol"; import "./ConsiderationConstants.sol"; /** * @title AmountDeriver * @author 0age * @notice AmountDeriver contains view and pure functions related to deriving * item amounts based on partial fill quantity and on linear * interpolation based on current time when the start amount and end * amount differ. */ contract AmountDeriver is AmountDerivationErrors { /** * @dev Internal view function to derive the current amount of a given item * based on the current price, the starting price, and the ending * price. If the start and end prices differ, the current price will be * interpolated on a linear basis. Note that this function expects that * the startTime parameter of orderParameters is not greater than the * current block timestamp and that the endTime parameter is greater * than the current block timestamp. If this condition is not upheld, * duration / elapsed / remaining variables will underflow. * * @param startAmount The starting amount of the item. * @param endAmount The ending amount of the item. * @param startTime The starting time of the order. * @param endTime The end time of the order. * @param roundUp A boolean indicating whether the resultant amount * should be rounded up or down. * * @return amount The current amount. */ function _locateCurrentAmount( uint256 startAmount, uint256 endAmount, uint256 startTime, uint256 endTime, bool roundUp ) internal view returns (uint256 amount) { // Only modify end amount if it doesn't already equal start amount. if (startAmount != endAmount) { // Declare variables to derive in the subsequent unchecked scope. uint256 duration; uint256 elapsed; uint256 remaining; // Skip underflow checks as startTime <= block.timestamp < endTime. unchecked { // Derive the duration for the order and place it on the stack. duration = endTime - startTime; // Derive time elapsed since the order started & place on stack. elapsed = block.timestamp - startTime; // Derive time remaining until order expires and place on stack. remaining = duration - elapsed; } // Aggregate new amounts weighted by time with rounding factor. uint256 totalBeforeDivision = ((startAmount * remaining) + (endAmount * elapsed)); // Use assembly to combine operations and skip divide-by-zero check. assembly { // Multiply by iszero(iszero(totalBeforeDivision)) to ensure // amount is set to zero if totalBeforeDivision is zero, // as intermediate overflow can occur if it is zero. amount := mul( iszero(iszero(totalBeforeDivision)), // Subtract 1 from the numerator and add 1 to the result if // roundUp is true to get the proper rounding direction. // Division is performed with no zero check as duration // cannot be zero as long as startTime < endTime. add( div(sub(totalBeforeDivision, roundUp), duration), roundUp ) ) } // Return the current amount. return amount; } // Return the original amount as startAmount == endAmount. return endAmount; } /** * @dev Internal pure function to return a fraction of a given value and to * ensure the resultant value does not have any fractional component. * Note that this function assumes that zero will never be supplied as * the denominator parameter; invalid / undefined behavior will result * should a denominator of zero be provided. * * @param numerator A value indicating the portion of the order that * should be filled. * @param denominator A value indicating the total size of the order. Note * that this value cannot be equal to zero. * @param value The value for which to compute the fraction. * * @return newValue The value after applying the fraction. */ function _getFraction( uint256 numerator, uint256 denominator, uint256 value ) internal pure returns (uint256 newValue) { // Return value early in cases where the fraction resolves to 1. if (numerator == denominator) { return value; } // Ensure fraction can be applied to the value with no remainder. Note // that the denominator cannot be zero. assembly { // Ensure new value contains no remainder via mulmod operator. // Credit to @hrkrshnn + @axic for proposing this optimal solution. if mulmod(value, numerator, denominator) { mstore(0, InexactFraction_error_signature) revert(0, InexactFraction_error_len) } } // Multiply the numerator by the value and ensure no overflow occurs. uint256 valueTimesNumerator = value * numerator; // Divide and check for remainder. Note that denominator cannot be zero. assembly { // Perform division without zero check. newValue := div(valueTimesNumerator, denominator) } } /** * @dev Internal view function to apply a fraction to a consideration * or offer item. * * @param startAmount The starting amount of the item. * @param endAmount The ending amount of the item. * @param numerator A value indicating the portion of the order that * should be filled. * @param denominator A value indicating the total size of the order. * @param startTime The starting time of the order. * @param endTime The end time of the order. * @param roundUp A boolean indicating whether the resultant * amount should be rounded up or down. * * @return amount The received item to transfer with the final amount. */ function _applyFraction( uint256 startAmount, uint256 endAmount, uint256 numerator, uint256 denominator, uint256 startTime, uint256 endTime, bool roundUp ) internal view returns (uint256 amount) { // If start amount equals end amount, apply fraction to end amount. if (startAmount == endAmount) { // Apply fraction to end amount. amount = _getFraction(numerator, denominator, endAmount); } else { // Otherwise, apply fraction to both and interpolated final amount. amount = _locateCurrentAmount( _getFraction(numerator, denominator, startAmount), _getFraction(numerator, denominator, endAmount), startTime, endTime, roundUp ); } } }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.13; import { ItemType, Side } from "./ConsiderationEnums.sol"; // prettier-ignore import { OfferItem, ConsiderationItem, OrderParameters, AdvancedOrder, CriteriaResolver } from "./ConsiderationStructs.sol"; import "./ConsiderationConstants.sol"; // prettier-ignore import { CriteriaResolutionErrors } from "./CriteriaResolutionErrors.sol"; /** * @title CriteriaResolution * @author 0age * @notice CriteriaResolution contains a collection of pure functions related to * resolving criteria-based items. */ contract CriteriaResolution is CriteriaResolutionErrors { /** * @dev Internal pure function to apply criteria resolvers containing * specific token identifiers and associated proofs to order items. * * @param advancedOrders The orders to apply criteria resolvers to. * @param criteriaResolvers An array where each element contains a * reference to a specific order as well as that * order's offer or consideration, a token * identifier, and a proof that the supplied token * identifier is contained in the order's merkle * root. Note that a root of zero indicates that * any transferable token identifier is valid and * that no proof needs to be supplied. */ function _applyCriteriaResolvers( AdvancedOrder[] memory advancedOrders, CriteriaResolver[] memory criteriaResolvers ) internal pure { // Skip overflow checks as all for loops are indexed starting at zero. unchecked { // Retrieve length of criteria resolvers array and place on stack. uint256 totalCriteriaResolvers = criteriaResolvers.length; // Retrieve length of orders array and place on stack. uint256 totalAdvancedOrders = advancedOrders.length; // Iterate over each criteria resolver. for (uint256 i = 0; i < totalCriteriaResolvers; ++i) { // Retrieve the criteria resolver. CriteriaResolver memory criteriaResolver = ( criteriaResolvers[i] ); // Read the order index from memory and place it on the stack. uint256 orderIndex = criteriaResolver.orderIndex; // Ensure that the order index is in range. if (orderIndex >= totalAdvancedOrders) { revert OrderCriteriaResolverOutOfRange(); } // Skip criteria resolution for order if not fulfilled. if (advancedOrders[orderIndex].numerator == 0) { continue; } // Retrieve the parameters for the order. OrderParameters memory orderParameters = ( advancedOrders[orderIndex].parameters ); // Read component index from memory and place it on the stack. uint256 componentIndex = criteriaResolver.index; // Declare values for item's type and criteria. ItemType itemType; uint256 identifierOrCriteria; // If the criteria resolver refers to an offer item... if (criteriaResolver.side == Side.OFFER) { // Retrieve the offer. OfferItem[] memory offer = orderParameters.offer; // Ensure that the component index is in range. if (componentIndex >= offer.length) { revert OfferCriteriaResolverOutOfRange(); } // Retrieve relevant item using the component index. OfferItem memory offerItem = offer[componentIndex]; // Read item type and criteria from memory & place on stack. itemType = offerItem.itemType; identifierOrCriteria = offerItem.identifierOrCriteria; // Optimistically update item type to remove criteria usage. // Use assembly to operate on ItemType enum as a number. ItemType newItemType; assembly { // Item type 4 becomes 2 and item type 5 becomes 3. newItemType := sub(3, eq(itemType, 4)) } offerItem.itemType = newItemType; // Optimistically update identifier w/ supplied identifier. offerItem.identifierOrCriteria = criteriaResolver .identifier; } else { // Otherwise, the resolver refers to a consideration item. ConsiderationItem[] memory consideration = ( orderParameters.consideration ); // Ensure that the component index is in range. if (componentIndex >= consideration.length) { revert ConsiderationCriteriaResolverOutOfRange(); } // Retrieve relevant item using order and component index. ConsiderationItem memory considerationItem = ( consideration[componentIndex] ); // Read item type and criteria from memory & place on stack. itemType = considerationItem.itemType; identifierOrCriteria = ( considerationItem.identifierOrCriteria ); // Optimistically update item type to remove criteria usage. // Use assembly to operate on ItemType enum as a number. ItemType newItemType; assembly { // Item type 4 becomes 2 and item type 5 becomes 3. newItemType := sub(3, eq(itemType, 4)) } considerationItem.itemType = newItemType; // Optimistically update identifier w/ supplied identifier. considerationItem.identifierOrCriteria = ( criteriaResolver.identifier ); } // Ensure the specified item type indicates criteria usage. if (!_isItemWithCriteria(itemType)) { revert CriteriaNotEnabledForItem(); } // If criteria is not 0 (i.e. a collection-wide offer)... if (identifierOrCriteria != uint256(0)) { // Verify identifier inclusion in criteria root using proof. _verifyProof( criteriaResolver.identifier, identifierOrCriteria, criteriaResolver.criteriaProof ); } } // Iterate over each advanced order. for (uint256 i = 0; i < totalAdvancedOrders; ++i) { // Retrieve the advanced order. AdvancedOrder memory advancedOrder = advancedOrders[i]; // Skip criteria resolution for order if not fulfilled. if (advancedOrder.numerator == 0) { continue; } // Retrieve the parameters for the order. OrderParameters memory orderParameters = ( advancedOrder.parameters ); // Read consideration length from memory and place on stack. uint256 totalItems = orderParameters.consideration.length; // Iterate over each consideration item on the order. for (uint256 j = 0; j < totalItems; ++j) { // Ensure item type no longer indicates criteria usage. if ( _isItemWithCriteria( orderParameters.consideration[j].itemType ) ) { revert UnresolvedConsiderationCriteria(); } } // Read offer length from memory and place on stack. totalItems = orderParameters.offer.length; // Iterate over each offer item on the order. for (uint256 j = 0; j < totalItems; ++j) { // Ensure item type no longer indicates criteria usage. if ( _isItemWithCriteria(orderParameters.offer[j].itemType) ) { revert UnresolvedOfferCriteria(); } } } } } /** * @dev Internal pure function to check whether a given item type represents * a criteria-based ERC721 or ERC1155 item (e.g. an item that can be * resolved to one of a number of different identifiers at the time of * order fulfillment). * * @param itemType The item type in question. * * @return withCriteria A boolean indicating that the item type in question * represents a criteria-based item. */ function _isItemWithCriteria(ItemType itemType) internal pure returns (bool withCriteria) { // ERC721WithCriteria is ItemType 4. ERC1155WithCriteria is ItemType 5. assembly { withCriteria := gt(itemType, 3) } } /** * @dev Internal pure function to ensure that a given element is contained * in a merkle root via a supplied proof. * * @param leaf The element for which to prove inclusion. * @param root The merkle root that inclusion will be proved against. * @param proof The merkle proof. */ function _verifyProof( uint256 leaf, uint256 root, bytes32[] memory proof ) internal pure { // Declare a variable that will be used to determine proof validity. bool isValid; // Utilize assembly to efficiently verify the proof against the root. assembly { // Store the leaf at the beginning of scratch space. mstore(0, leaf) // Derive the hash of the leaf to use as the initial proof element. let computedHash := keccak256(0, OneWord) // Based on: https://github.com/Rari-Capital/solmate/blob/v7/src/utils/MerkleProof.sol // Get memory start location of the first element in proof array. let data := add(proof, OneWord) // Iterate over each proof element to compute the root hash. for { // Left shift by 5 is equivalent to multiplying by 0x20. let end := add(data, shl(5, mload(proof))) } lt(data, end) { // Increment by one word at a time. data := add(data, OneWord) } { // Get the proof element. let loadedData := mload(data) // Sort proof elements and place them in scratch space. // Slot of `computedHash` in scratch space. // If the condition is true: 0x20, otherwise: 0x00. let scratch := shl(5, gt(computedHash, loadedData)) // Store elements to hash contiguously in scratch space. Scratch // space is 64 bytes (0x00 - 0x3f) & both elements are 32 bytes. mstore(scratch, computedHash) mstore(xor(scratch, OneWord), loadedData) // Derive the updated hash. computedHash := keccak256(0, TwoWords) } // Compare the final hash to the supplied root. isValid := eq(computedHash, root) } // Revert if computed hash does not equal supplied root. if (!isValid) { revert InvalidProof(); } } }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.13; import { ConduitInterface } from "./ConduitInterface.sol"; // prettier-ignore import { OrderType, ItemType, BasicOrderRouteType } from "./ConsiderationEnums.sol"; // prettier-ignore import { AdditionalRecipient, BasicOrderParameters, OfferItem, ConsiderationItem, SpentItem, ReceivedItem } from "./ConsiderationStructs.sol"; import { OrderValidator } from "./OrderValidator.sol"; import "./ConsiderationConstants.sol"; /** * @title BasicOrderFulfiller * @author 0age * @notice BasicOrderFulfiller contains functionality for fulfilling "basic" * orders with minimal overhead. See documentation for details on what * qualifies as a basic order. */ contract BasicOrderFulfiller is OrderValidator { /** * @dev Derive and set hashes, reference chainId, and associated domain * separator during deployment. * * @param conduitController A contract that deploys conduits, or proxies * that may optionally be used to transfer approved * ERC20/721/1155 tokens. */ constructor(address conduitController) OrderValidator(conduitController) {} /** * @dev Internal function to fulfill an order offering an ERC20, ERC721, or * ERC1155 item by supplying Ether (or other native tokens), ERC20 * tokens, an ERC721 item, or an ERC1155 item as consideration. Six * permutations are supported: Native token to ERC721, Native token to * ERC1155, ERC20 to ERC721, ERC20 to ERC1155, ERC721 to ERC20, and * ERC1155 to ERC20 (with native tokens supplied as msg.value). For an * order to be eligible for fulfillment via this method, it must * contain a single offer item (though that item may have a greater * amount if the item is not an ERC721). An arbitrary number of * "additional recipients" may also be supplied which will each receive * native tokens or ERC20 items from the fulfiller as consideration. * Refer to the documentation for a more comprehensive summary of how * to utilize this method and what orders are compatible with it. * * @param parameters Additional information on the fulfilled order. Note * that the offerer and the fulfiller must first approve * this contract (or their chosen conduit if indicated) * before any tokens can be transferred. Also note that * contract recipients of ERC1155 consideration items must * implement `onERC1155Received` in order to receive those * items. * * @return A boolean indicating whether the order has been fulfilled. */ function _validateAndFulfillBasicOrder( BasicOrderParameters calldata parameters ) internal returns (bool) { // Declare enums for order type & route to extract from basicOrderType. BasicOrderRouteType route; OrderType orderType; // Declare additional recipient item type to derive from the route type. ItemType additionalRecipientsItemType; // Utilize assembly to extract the order type and the basic order route. assembly { // Read basicOrderType from calldata. let basicOrderType := calldataload(BasicOrder_basicOrderType_cdPtr) // Mask all but 2 least-significant bits to derive the order type. orderType := and(basicOrderType, 3) // Divide basicOrderType by four to derive the route. route := shr(2, basicOrderType) // If route > 1 additionalRecipient items are ERC20 (1) else Eth (0) additionalRecipientsItemType := gt(route, 1) } { // Declare temporary variable for enforcing payable status. bool correctPayableStatus; // Utilize assembly to compare the route to the callvalue. assembly { // route 0 and 1 are payable, otherwise route is not payable. correctPayableStatus := eq( additionalRecipientsItemType, iszero(callvalue()) ) } // Revert if msg.value has not been supplied as part of payable // routes or has been supplied as part of non-payable routes. if (!correctPayableStatus) { revert InvalidMsgValue(msg.value); } } // Declare more arguments that will be derived from route and calldata. address additionalRecipientsToken; ItemType offeredItemType; bool offerTypeIsAdditionalRecipientsType; // Declare scope for received item type to manage stack pressure. { ItemType receivedItemType; // Utilize assembly to retrieve function arguments and cast types. assembly { // Check if offered item type == additional recipient item type. offerTypeIsAdditionalRecipientsType := gt(route, 3) // If route > 3 additionalRecipientsToken is at 0xc4 else 0x24. additionalRecipientsToken := calldataload( add( BasicOrder_considerationToken_cdPtr, mul( offerTypeIsAdditionalRecipientsType, BasicOrder_common_params_size ) ) ) // If route > 2, receivedItemType is route - 2. If route is 2, // the receivedItemType is ERC20 (1). Otherwise, it is Eth (0). receivedItemType := add( mul(sub(route, 2), gt(route, 2)), eq(route, 2) ) // If route > 3, offeredItemType is ERC20 (1). Route is 2 or 3, // offeredItemType = route. Route is 0 or 1, it is route + 2. offeredItemType := sub( add(route, mul(iszero(additionalRecipientsItemType), 2)), mul( offerTypeIsAdditionalRecipientsType, add(receivedItemType, 1) ) ) } // Derive & validate order using parameters and update order status. _prepareBasicFulfillmentFromCalldata( parameters, orderType, receivedItemType, additionalRecipientsItemType, additionalRecipientsToken, offeredItemType ); } // Declare conduitKey argument used by transfer functions. bytes32 conduitKey; // Utilize assembly to derive conduit (if relevant) based on route. assembly { // use offerer conduit for routes 0-3, fulfiller conduit otherwise. conduitKey := calldataload( add( BasicOrder_offererConduit_cdPtr, mul(offerTypeIsAdditionalRecipientsType, OneWord) ) ) } // Transfer tokens based on the route. if (additionalRecipientsItemType == ItemType.NATIVE) { // Ensure neither the token nor the identifier parameters are set. if ( (uint160(parameters.considerationToken) | parameters.considerationIdentifier) != 0 ) { revert UnusedItemParameters(); } // Transfer the ERC721 or ERC1155 item, bypassing the accumulator. _transferIndividual721Or1155Item( offeredItemType, parameters.offerToken, parameters.offerer, msg.sender, parameters.offerIdentifier, parameters.offerAmount, conduitKey ); // Transfer native to recipients, return excess to caller & wrap up. _transferEthAndFinalize( parameters.considerationAmount, parameters.offerer, parameters.additionalRecipients ); } else { // Initialize an accumulator array. From this point forward, no new // memory regions can be safely allocated until the accumulator is // no longer being utilized, as the accumulator operates in an // open-ended fashion from this memory pointer; existing memory may // still be accessed and modified, however. bytes memory accumulator = new bytes(AccumulatorDisarmed); // Choose transfer method for ERC721 or ERC1155 item based on route. if (route == BasicOrderRouteType.ERC20_TO_ERC721) { // Transfer ERC721 to caller using offerer's conduit preference. _transferERC721( parameters.offerToken, parameters.offerer, msg.sender, parameters.offerIdentifier, parameters.offerAmount, conduitKey, accumulator ); } else if (route == BasicOrderRouteType.ERC20_TO_ERC1155) { // Transfer ERC1155 to caller with offerer's conduit preference. _transferERC1155( parameters.offerToken, parameters.offerer, msg.sender, parameters.offerIdentifier, parameters.offerAmount, conduitKey, accumulator ); } else if (route == BasicOrderRouteType.ERC721_TO_ERC20) { // Transfer ERC721 to offerer using caller's conduit preference. _transferERC721( parameters.considerationToken, msg.sender, parameters.offerer, parameters.considerationIdentifier, parameters.considerationAmount, conduitKey, accumulator ); } else { // route == BasicOrderRouteType.ERC1155_TO_ERC20 // Transfer ERC1155 to offerer with caller's conduit preference. _transferERC1155( parameters.considerationToken, msg.sender, parameters.offerer, parameters.considerationIdentifier, parameters.considerationAmount, conduitKey, accumulator ); } // Transfer ERC20 tokens to all recipients and wrap up. _transferERC20AndFinalize( parameters.offerer, parameters, offerTypeIsAdditionalRecipientsType, accumulator ); // Trigger any remaining accumulated transfers via call to conduit. _triggerIfArmed(accumulator); } // Clear the reentrancy guard. _clearReentrancyGuard(); return true; } /** * @dev Internal function to prepare fulfillment of a basic order with * manual calldata and memory access. This calculates the order hash, * emits an OrderFulfilled event, and asserts basic order validity. * Note that calldata offsets must be validated as this function * accesses constant calldata pointers for dynamic types that match * default ABI encoding, but valid ABI encoding can use arbitrary * offsets. Checking that the offsets were produced by default encoding * will ensure that other functions using Solidity's calldata accessors * (which calculate pointers from the stored offsets) are reading the * same data as the order hash is derived from. Also note that This * function accesses memory directly. It does not clear the expanded * memory regions used, nor does it update the free memory pointer, so * other direct memory access must not assume that unused memory is * empty. * * @param parameters The parameters of the basic order. * @param orderType The order type. * @param receivedItemType The item type of the initial * consideration item on the order. * @param additionalRecipientsItemType The item type of any additional * consideration item on the order. * @param additionalRecipientsToken The ERC20 token contract address (if * applicable) for any additional * consideration item on the order. * @param offeredItemType The item type of the offered item on * the order. */ function _prepareBasicFulfillmentFromCalldata( BasicOrderParameters calldata parameters, OrderType orderType, ItemType receivedItemType, ItemType additionalRecipientsItemType, address additionalRecipientsToken, ItemType offeredItemType ) internal { // Ensure this function cannot be triggered during a reentrant call. _setReentrancyGuard(); // Ensure current timestamp falls between order start time and end time. _verifyTime(parameters.startTime, parameters.endTime, true); // Verify that calldata offsets for all dynamic types were produced by // default encoding. This ensures that the constants we use for calldata // pointers to dynamic types are the same as those calculated by // Solidity using their offsets. Also verify that the basic order type // is within range. _assertValidBasicOrderParameters(); // Ensure supplied consideration array length is not less than original. _assertConsiderationLengthIsNotLessThanOriginalConsiderationLength( parameters.additionalRecipients.length, parameters.totalOriginalAdditionalRecipients ); // Declare stack element for the order hash. bytes32 orderHash; { /** * First, handle consideration items. Memory Layout: * 0x60: final hash of the array of consideration item hashes * 0x80-0x160: reused space for EIP712 hashing of each item * - 0x80: ConsiderationItem EIP-712 typehash (constant) * - 0xa0: itemType * - 0xc0: token * - 0xe0: identifier * - 0x100: startAmount * - 0x120: endAmount * - 0x140: recipient * 0x160-END_ARR: array of consideration item hashes * - 0x160: primary consideration item EIP712 hash * - 0x180-END_ARR: additional recipient item EIP712 hashes * END_ARR: beginning of data for OrderFulfilled event * - END_ARR + 0x120: length of ReceivedItem array * - END_ARR + 0x140: beginning of data for first ReceivedItem * (Note: END_ARR = 0x180 + RECIPIENTS_LENGTH * 0x20) */ // Load consideration item typehash from runtime and place on stack. bytes32 typeHash = _CONSIDERATION_ITEM_TYPEHASH; // Utilize assembly to enable reuse of memory regions and use // constant pointers when possible. assembly { /* * 1. Calculate the EIP712 ConsiderationItem hash for the * primary consideration item of the basic order. */ // Write ConsiderationItem type hash and item type to memory. mstore(BasicOrder_considerationItem_typeHash_ptr, typeHash) mstore( BasicOrder_considerationItem_itemType_ptr, receivedItemType ) // Copy calldata region with (token, identifier, amount) from // BasicOrderParameters to ConsiderationItem. The // considerationAmount is written to startAmount and endAmount // as basic orders do not have dynamic amounts. calldatacopy( BasicOrder_considerationItem_token_ptr, BasicOrder_considerationToken_cdPtr, ThreeWords ) // Copy calldata region with considerationAmount and offerer // from BasicOrderParameters to endAmount and recipient in // ConsiderationItem. calldatacopy( BasicOrder_considerationItem_endAmount_ptr, BasicOrder_considerationAmount_cdPtr, TwoWords ) // Calculate EIP712 ConsiderationItem hash and store it in the // array of EIP712 consideration hashes. mstore( BasicOrder_considerationHashesArray_ptr, keccak256( BasicOrder_considerationItem_typeHash_ptr, EIP712_ConsiderationItem_size ) ) /* * 2. Write a ReceivedItem struct for the primary consideration * item to the consideration array in OrderFulfilled. */ // Get the length of the additional recipients array. let totalAdditionalRecipients := calldataload( BasicOrder_additionalRecipients_length_cdPtr ) // Calculate pointer to length of OrderFulfilled consideration // array. let eventConsiderationArrPtr := add( OrderFulfilled_consideration_length_baseOffset, mul(totalAdditionalRecipients, OneWord) ) // Set the length of the consideration array to the number of // additional recipients, plus one for the primary consideration // item. mstore( eventConsiderationArrPtr, add( calldataload( BasicOrder_additionalRecipients_length_cdPtr ), 1 ) ) // Overwrite the consideration array pointer so it points to the // body of the first element eventConsiderationArrPtr := add( eventConsiderationArrPtr, OneWord ) // Set itemType at start of the ReceivedItem memory region. mstore(eventConsiderationArrPtr, receivedItemType) // Copy calldata region (token, identifier, amount & recipient) // from BasicOrderParameters to ReceivedItem memory. calldatacopy( add(eventConsiderationArrPtr, Common_token_offset), BasicOrder_considerationToken_cdPtr, FourWords ) /* * 3. Calculate EIP712 ConsiderationItem hashes for original * additional recipients and add a ReceivedItem for each to the * consideration array in the OrderFulfilled event. The original * additional recipients are all the considerations signed by * the offerer aside from the primary consideration of the * order. Uses memory region from 0x80-0x160 as a buffer for * calculating EIP712 ConsiderationItem hashes. */ // Put pointer to consideration hashes array on the stack. // This will be updated as each additional recipient is hashed let considerationHashesPtr := BasicOrder_considerationHashesArray_ptr // Write item type, token, & identifier for additional recipient // to memory region for hashing EIP712 ConsiderationItem; these // values will be reused for each recipient. mstore( BasicOrder_considerationItem_itemType_ptr, additionalRecipientsItemType ) mstore( BasicOrder_considerationItem_token_ptr, additionalRecipientsToken ) mstore(BasicOrder_considerationItem_identifier_ptr, 0) // Read length of the additionalRecipients array from calldata // and iterate. totalAdditionalRecipients := calldataload( BasicOrder_totalOriginalAdditionalRecipients_cdPtr ) let i := 0 // prettier-ignore for {} lt(i, totalAdditionalRecipients) { i := add(i, 1) } { /* * Calculate EIP712 ConsiderationItem hash for recipient. */ // Retrieve calldata pointer for additional recipient. let additionalRecipientCdPtr := add( BasicOrder_additionalRecipients_data_cdPtr, mul(AdditionalRecipients_size, i) ) // Copy startAmount from calldata to the ConsiderationItem // struct. calldatacopy( BasicOrder_considerationItem_startAmount_ptr, additionalRecipientCdPtr, OneWord ) // Copy endAmount and recipient from calldata to the // ConsiderationItem struct. calldatacopy( BasicOrder_considerationItem_endAmount_ptr, additionalRecipientCdPtr, AdditionalRecipients_size ) // Add 1 word to the pointer as part of each loop to reduce // operations needed to get local offset into the array. considerationHashesPtr := add( considerationHashesPtr, OneWord ) // Calculate EIP712 ConsiderationItem hash and store it in // the array of consideration hashes. mstore( considerationHashesPtr, keccak256( BasicOrder_considerationItem_typeHash_ptr, EIP712_ConsiderationItem_size ) ) /* * Write ReceivedItem to OrderFulfilled data. */ // At this point, eventConsiderationArrPtr points to the // beginning of the ReceivedItem struct of the previous // element in the array. Increase it by the size of the // struct to arrive at the pointer for the current element. eventConsiderationArrPtr := add( eventConsiderationArrPtr, ReceivedItem_size ) // Write itemType to the ReceivedItem struct. mstore( eventConsiderationArrPtr, additionalRecipientsItemType ) // Write token to the next word of the ReceivedItem struct. mstore( add(eventConsiderationArrPtr, OneWord), additionalRecipientsToken ) // Copy endAmount & recipient words to ReceivedItem struct. calldatacopy( add( eventConsiderationArrPtr, ReceivedItem_amount_offset ), additionalRecipientCdPtr, TwoWords ) } /* * 4. Hash packed array of ConsiderationItem EIP712 hashes: * `keccak256(abi.encodePacked(receivedItemHashes))` * Note that it is set at 0x60 — all other memory begins at * 0x80. 0x60 is the "zero slot" and will be restored at the end * of the assembly section and before required by the compiler. */ mstore( receivedItemsHash_ptr, keccak256( BasicOrder_considerationHashesArray_ptr, mul(add(totalAdditionalRecipients, 1), OneWord) ) ) /* * 5. Add a ReceivedItem for each tip to the consideration array * in the OrderFulfilled event. The tips are all the * consideration items that were not signed by the offerer and * were provided by the fulfiller. */ // Overwrite length to length of the additionalRecipients array. totalAdditionalRecipients := calldataload( BasicOrder_additionalRecipients_length_cdPtr ) // prettier-ignore for {} lt(i, totalAdditionalRecipients) { i := add(i, 1) } { // Retrieve calldata pointer for additional recipient. let additionalRecipientCdPtr := add( BasicOrder_additionalRecipients_data_cdPtr, mul(AdditionalRecipients_size, i) ) // At this point, eventConsiderationArrPtr points to the // beginning of the ReceivedItem struct of the previous // element in the array. Increase it by the size of the // struct to arrive at the pointer for the current element. eventConsiderationArrPtr := add( eventConsiderationArrPtr, ReceivedItem_size ) // Write itemType to the ReceivedItem struct. mstore( eventConsiderationArrPtr, additionalRecipientsItemType ) // Write token to the next word of the ReceivedItem struct. mstore( add(eventConsiderationArrPtr, OneWord), additionalRecipientsToken ) // Copy endAmount & recipient words to ReceivedItem struct. calldatacopy( add( eventConsiderationArrPtr, ReceivedItem_amount_offset ), additionalRecipientCdPtr, TwoWords ) } } } { /** * Next, handle offered items. Memory Layout: * EIP712 data for OfferItem * - 0x80: OfferItem EIP-712 typehash (constant) * - 0xa0: itemType * - 0xc0: token * - 0xe0: identifier (reused for offeredItemsHash) * - 0x100: startAmount * - 0x120: endAmount */ // Place offer item typehash on the stack. bytes32 typeHash = _OFFER_ITEM_TYPEHASH; // Utilize assembly to enable reuse of memory regions when possible. assembly { /* * 1. Calculate OfferItem EIP712 hash */ // Write the OfferItem typeHash to memory. mstore(BasicOrder_offerItem_typeHash_ptr, typeHash) // Write the OfferItem item type to memory. mstore(BasicOrder_offerItem_itemType_ptr, offeredItemType) // Copy calldata region with (offerToken, offerIdentifier, // offerAmount) from OrderParameters to (token, identifier, // startAmount) in OfferItem struct. The offerAmount is written // to startAmount and endAmount as basic orders do not have // dynamic amounts. calldatacopy( BasicOrder_offerItem_token_ptr, BasicOrder_offerToken_cdPtr, ThreeWords ) // Copy offerAmount from calldata to endAmount in OfferItem // struct. calldatacopy( BasicOrder_offerItem_endAmount_ptr, BasicOrder_offerAmount_cdPtr, OneWord ) // Compute EIP712 OfferItem hash, write result to scratch space: // `keccak256(abi.encode(offeredItem))` mstore( 0, keccak256( BasicOrder_offerItem_typeHash_ptr, EIP712_OfferItem_size ) ) /* * 2. Calculate hash of array of EIP712 hashes and write the * result to the corresponding OfferItem struct: * `keccak256(abi.encodePacked(offerItemHashes))` */ mstore(BasicOrder_order_offerHashes_ptr, keccak256(0, OneWord)) /* * 3. Write SpentItem to offer array in OrderFulfilled event. */ let eventConsiderationArrPtr := add( OrderFulfilled_offer_length_baseOffset, mul( calldataload( BasicOrder_additionalRecipients_length_cdPtr ), OneWord ) ) // Set a length of 1 for the offer array. mstore(eventConsiderationArrPtr, 1) // Write itemType to the SpentItem struct. mstore(add(eventConsiderationArrPtr, OneWord), offeredItemType) // Copy calldata region with (offerToken, offerIdentifier, // offerAmount) from OrderParameters to (token, identifier, // amount) in SpentItem struct. calldatacopy( add(eventConsiderationArrPtr, AdditionalRecipients_size), BasicOrder_offerToken_cdPtr, ThreeWords ) } } { /** * Once consideration items and offer items have been handled, * derive the final order hash. Memory Layout: * 0x80-0x1c0: EIP712 data for order * - 0x80: Order EIP-712 typehash (constant) * - 0xa0: orderParameters.offerer * - 0xc0: orderParameters.zone * - 0xe0: keccak256(abi.encodePacked(offerHashes)) * - 0x100: keccak256(abi.encodePacked(considerationHashes)) * - 0x120: orderParameters.basicOrderType (% 4 = orderType) * - 0x140: orderParameters.startTime * - 0x160: orderParameters.endTime * - 0x180: orderParameters.zoneHash * - 0x1a0: orderParameters.salt * - 0x1c0: orderParameters.conduitKey * - 0x1e0: _counters[orderParameters.offerer] (from storage) */ // Read the offerer from calldata and place on the stack. address offerer; assembly { offerer := calldataload(BasicOrder_offerer_cdPtr) } // Read offerer's current counter from storage and place on stack. uint256 counter = _getCounter(offerer); // Load order typehash from runtime code and place on stack. bytes32 typeHash = _ORDER_TYPEHASH; assembly { // Set the OrderItem typeHash in memory. mstore(BasicOrder_order_typeHash_ptr, typeHash) // Copy offerer and zone from OrderParameters in calldata to the // Order struct. calldatacopy( BasicOrder_order_offerer_ptr, BasicOrder_offerer_cdPtr, TwoWords ) // Copy receivedItemsHash from zero slot to the Order struct. mstore( BasicOrder_order_considerationHashes_ptr, mload(receivedItemsHash_ptr) ) // Write the supplied orderType to the Order struct. mstore(BasicOrder_order_orderType_ptr, orderType) // Copy startTime, endTime, zoneHash, salt & conduit from // calldata to the Order struct. calldatacopy( BasicOrder_order_startTime_ptr, BasicOrder_startTime_cdPtr, FiveWords ) // Write offerer's counter, retrieved from storage, to struct. mstore(BasicOrder_order_counter_ptr, counter) // Compute the EIP712 Order hash. orderHash := keccak256( BasicOrder_order_typeHash_ptr, EIP712_Order_size ) } } assembly { /** * After the order hash has been derived, emit OrderFulfilled event: * event OrderFulfilled( * bytes32 orderHash, * address indexed offerer, * address indexed zone, * address fulfiller, * SpentItem[] offer, * > (itemType, token, id, amount) * ReceivedItem[] consideration * > (itemType, token, id, amount, recipient) * ) * topic0 - OrderFulfilled event signature * topic1 - offerer * topic2 - zone * data: * - 0x00: orderHash * - 0x20: fulfiller * - 0x40: offer arr ptr (0x80) * - 0x60: consideration arr ptr (0x120) * - 0x80: offer arr len (1) * - 0xa0: offer.itemType * - 0xc0: offer.token * - 0xe0: offer.identifier * - 0x100: offer.amount * - 0x120: 1 + recipients.length * - 0x140: recipient 0 */ // Derive pointer to start of OrderFulfilled event data let eventDataPtr := add( OrderFulfilled_baseOffset, mul( calldataload(BasicOrder_additionalRecipients_length_cdPtr), OneWord ) ) // Write the order hash to the head of the event's data region. mstore(eventDataPtr, orderHash) // Write the fulfiller (i.e. the caller) next for receiver argument. mstore(add(eventDataPtr, OrderFulfilled_fulfiller_offset), caller()) // Write the SpentItem and ReceivedItem array offsets (constants). mstore( // SpentItem array offset add(eventDataPtr, OrderFulfilled_offer_head_offset), OrderFulfilled_offer_body_offset ) mstore( // ReceivedItem array offset add(eventDataPtr, OrderFulfilled_consideration_head_offset), OrderFulfilled_consideration_body_offset ) // Derive total data size including SpentItem and ReceivedItem data. // SpentItem portion is already included in the baseSize constant, // as there can only be one element in the array. let dataSize := add( OrderFulfilled_baseSize, mul( calldataload(BasicOrder_additionalRecipients_length_cdPtr), ReceivedItem_size ) ) // Emit OrderFulfilled log with three topics (the event signature // as well as the two indexed arguments, the offerer and the zone). log3( // Supply the pointer for event data in memory. eventDataPtr, // Supply the size of event data in memory. dataSize, // Supply the OrderFulfilled event signature. OrderFulfilled_selector, // Supply the first topic (the offerer). calldataload(BasicOrder_offerer_cdPtr), // Supply the second topic (the zone). calldataload(BasicOrder_zone_cdPtr) ) // Restore the zero slot. mstore(ZeroSlot, 0) } // Determine whether order is restricted and, if so, that it is valid. _assertRestrictedBasicOrderValidity( orderHash, parameters.zoneHash, orderType, parameters.offerer, parameters.zone ); // Verify and update the status of the derived order. _validateBasicOrderAndUpdateStatus( orderHash, parameters.offerer, parameters.signature ); } /** * @dev Internal function to transfer Ether (or other native tokens) to a * given recipient as part of basic order fulfillment. Note that * conduits are not utilized for native tokens as the transferred * amount must be provided as msg.value. * * @param amount The amount to transfer. * @param to The recipient of the native token transfer. * @param additionalRecipients The additional recipients of the order. */ function _transferEthAndFinalize( uint256 amount, address payable to, AdditionalRecipient[] calldata additionalRecipients ) internal { // Put ether value supplied by the caller on the stack. uint256 etherRemaining = msg.value; // Retrieve total number of additional recipients and place on stack. uint256 totalAdditionalRecipients = additionalRecipients.length; // Skip overflow check as for loop is indexed starting at zero. unchecked { // Iterate over each additional recipient. for (uint256 i = 0; i < totalAdditionalRecipients; ++i) { // Retrieve the additional recipient. AdditionalRecipient calldata additionalRecipient = ( additionalRecipients[i] ); // Read ether amount to transfer to recipient & place on stack. uint256 additionalRecipientAmount = additionalRecipient.amount; // Ensure that sufficient Ether is available. if (additionalRecipientAmount > etherRemaining) { revert InsufficientEtherSupplied(); } // Transfer Ether to the additional recipient. _transferEth( additionalRecipient.recipient, additionalRecipientAmount ); // Reduce ether value available. Skip underflow check as // subtracted value is confirmed above as less than remaining. etherRemaining -= additionalRecipientAmount; } } // Ensure that sufficient Ether is still available. if (amount > etherRemaining) { revert InsufficientEtherSupplied(); } // Transfer Ether to the offerer. _transferEth(to, amount); // If any Ether remains after transfers, return it to the caller. if (etherRemaining > amount) { // Skip underflow check as etherRemaining > amount. unchecked { // Transfer remaining Ether to the caller. _transferEth(payable(msg.sender), etherRemaining - amount); } } } /** * @dev Internal function to transfer ERC20 tokens to a given recipient as * part of basic order fulfillment. * * @param offerer The offerer of the fulfiller order. * @param parameters The basic order parameters. * @param fromOfferer A boolean indicating whether to decrement amount from * the offered amount. * @param accumulator An open-ended array that collects transfers to execute * against a given conduit in a single call. */ function _transferERC20AndFinalize( address offerer, BasicOrderParameters calldata parameters, bool fromOfferer, bytes memory accumulator ) internal { // Declare from and to variables determined by fromOfferer value. address from; address to; // Declare token and amount variables determined by fromOfferer value. address token; uint256 amount; // Declare and check identifier variable within an isolated scope. { // Declare identifier variable determined by fromOfferer value. uint256 identifier; // Set ERC20 token transfer variables based on fromOfferer boolean. if (fromOfferer) { // Use offerer as from value and msg.sender as to value. from = offerer; to = msg.sender; // Use offer token and related values if token is from offerer. token = parameters.offerToken; identifier = parameters.offerIdentifier; amount = parameters.offerAmount; } else { // Use msg.sender as from value and offerer as to value. from = msg.sender; to = offerer; // Otherwise, use consideration token and related values. token = parameters.considerationToken; identifier = parameters.considerationIdentifier; amount = parameters.considerationAmount; } // Ensure that no identifier is supplied. if (identifier != 0) { revert UnusedItemParameters(); } } // Determine the appropriate conduit to utilize. bytes32 conduitKey; // Utilize assembly to derive conduit (if relevant) based on route. assembly { // Use offerer conduit if fromOfferer, fulfiller conduit otherwise. conduitKey := calldataload( sub( BasicOrder_fulfillerConduit_cdPtr, mul(fromOfferer, OneWord) ) ) } // Retrieve total number of additional recipients and place on stack. uint256 totalAdditionalRecipients = ( parameters.additionalRecipients.length ); // Iterate over each additional recipient. for (uint256 i = 0; i < totalAdditionalRecipients; ) { // Retrieve the additional recipient. AdditionalRecipient calldata additionalRecipient = ( parameters.additionalRecipients[i] ); uint256 additionalRecipientAmount = additionalRecipient.amount; // Decrement the amount to transfer to fulfiller if indicated. if (fromOfferer) { amount -= additionalRecipientAmount; } // Transfer ERC20 tokens to additional recipient given approval. _transferERC20( token, from, additionalRecipient.recipient, additionalRecipientAmount, conduitKey, accumulator ); // Skip overflow check as for loop is indexed starting at zero. unchecked { ++i; } } // Transfer ERC20 token amount (from account must have proper approval). _transferERC20(token, from, to, amount, conduitKey, accumulator); } }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.7; import { Side } from "./ConsiderationEnums.sol"; /** * @title FulfillmentApplicationErrors * @author 0age * @notice FulfillmentApplicationErrors contains errors related to fulfillment * application and aggregation. */ interface FulfillmentApplicationErrors { /** * @dev Revert with an error when a fulfillment is provided that does not * declare at least one component as part of a call to fulfill * available orders. */ error MissingFulfillmentComponentOnAggregation(Side side); /** * @dev Revert with an error when a fulfillment is provided that does not * declare at least one offer component and at least one consideration * component. */ error OfferAndConsiderationRequiredOnFulfillment(); /** * @dev Revert with an error when the initial offer item named by a * fulfillment component does not match the type, token, identifier, * or conduit preference of the initial consideration item. */ error MismatchedFulfillmentOfferAndConsiderationComponents(); /** * @dev Revert with an error when an order or item index are out of range * or a fulfillment component does not match the type, token, * identifier, or conduit preference of the initial consideration item. */ error InvalidFulfillmentComponentData(); }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.7; /** * @title CriteriaResolutionErrors * @author 0age * @notice CriteriaResolutionErrors contains all errors related to criteria * resolution. */ interface CriteriaResolutionErrors { /** * @dev Revert with an error when providing a criteria resolver that refers * to an order that has not been supplied. */ error OrderCriteriaResolverOutOfRange(); /** * @dev Revert with an error if an offer item still has unresolved criteria * after applying all criteria resolvers. */ error UnresolvedOfferCriteria(); /** * @dev Revert with an error if a consideration item still has unresolved * criteria after applying all criteria resolvers. */ error UnresolvedConsiderationCriteria(); /** * @dev Revert with an error when providing a criteria resolver that refers * to an order with an offer item that has not been supplied. */ error OfferCriteriaResolverOutOfRange(); /** * @dev Revert with an error when providing a criteria resolver that refers * to an order with a consideration item that has not been supplied. */ error ConsiderationCriteriaResolverOutOfRange(); /** * @dev Revert with an error when providing a criteria resolver that refers * to an order with an item that does not expect a criteria to be * resolved. */ error CriteriaNotEnabledForItem(); /** * @dev Revert with an error when providing a criteria resolver that * contains an invalid proof with respect to the given item and * chosen identifier. */ error InvalidProof(); }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.13; import { OrderType } from "./ConsiderationEnums.sol"; // prettier-ignore import { OrderParameters, Order, AdvancedOrder, OrderComponents, OrderStatus, CriteriaResolver } from "./ConsiderationStructs.sol"; import "./ConsiderationConstants.sol"; import { Executor } from "./Executor.sol"; import { ZoneInteraction } from "./ZoneInteraction.sol"; /** * @title OrderValidator * @author 0age * @notice OrderValidator contains functionality related to validating orders * and updating their status. */ contract OrderValidator is Executor, ZoneInteraction { // Track status of each order (validated, cancelled, and fraction filled). mapping(bytes32 => OrderStatus) private _orderStatus; /** * @dev Derive and set hashes, reference chainId, and associated domain * separator during deployment. * * @param conduitController A contract that deploys conduits, or proxies * that may optionally be used to transfer approved * ERC20/721/1155 tokens. */ constructor(address conduitController) Executor(conduitController) {} /** * @dev Internal function to verify and update the status of a basic order. * * @param orderHash The hash of the order. * @param offerer The offerer of the order. * @param signature A signature from the offerer indicating that the order * has been approved. */ function _validateBasicOrderAndUpdateStatus( bytes32 orderHash, address offerer, bytes memory signature ) internal { // Retrieve the order status for the given order hash. OrderStatus storage orderStatus = _orderStatus[orderHash]; // Ensure order is fillable and is not cancelled. _verifyOrderStatus( orderHash, orderStatus, true, // Only allow unused orders when fulfilling basic orders. true // Signifies to revert if the order is invalid. ); // If the order is not already validated, verify the supplied signature. if (!orderStatus.isValidated) { _verifySignature(offerer, orderHash, signature); } // Update order status as fully filled, packing struct values. orderStatus.isValidated = true; orderStatus.isCancelled = false; orderStatus.numerator = 1; orderStatus.denominator = 1; } /** * @dev Internal function to validate an order, determine what portion to * fill, and update its status. The desired fill amount is supplied as * a fraction, as is the returned amount to fill. * * @param advancedOrder The order to fulfill as well as the fraction to * fill. Note that all offer and consideration * amounts must divide with no remainder in order * for a partial fill to be valid. * @param criteriaResolvers An array where each element contains a reference * to a specific offer or consideration, a token * identifier, and a proof that the supplied token * identifier is contained in the order's merkle * root. Note that a criteria of zero indicates * that any (transferable) token identifier is * valid and that no proof needs to be supplied. * @param revertOnInvalid A boolean indicating whether to revert if the * order is invalid due to the time or status. * @param priorOrderHashes The order hashes of each order supplied prior to * the current order as part of a "match" variety * of order fulfillment (e.g. this array will be * empty for single or "fulfill available"). * * @return orderHash The order hash. * @return newNumerator A value indicating the portion of the order that * will be filled. * @return newDenominator A value indicating the total size of the order. */ function _validateOrderAndUpdateStatus( AdvancedOrder memory advancedOrder, CriteriaResolver[] memory criteriaResolvers, bool revertOnInvalid, bytes32[] memory priorOrderHashes ) internal returns ( bytes32 orderHash, uint256 newNumerator, uint256 newDenominator ) { // Retrieve the parameters for the order. OrderParameters memory orderParameters = advancedOrder.parameters; // Ensure current timestamp falls between order start time and end time. if ( !_verifyTime( orderParameters.startTime, orderParameters.endTime, revertOnInvalid ) ) { // Assuming an invalid time and no revert, return zeroed out values. return (bytes32(0), 0, 0); } // Read numerator and denominator from memory and place on the stack. uint256 numerator = uint256(advancedOrder.numerator); uint256 denominator = uint256(advancedOrder.denominator); // Ensure that the supplied numerator and denominator are valid. if (numerator > denominator || numerator == 0) { revert BadFraction(); } // If attempting partial fill (n < d) check order type & ensure support. if ( numerator < denominator && _doesNotSupportPartialFills(orderParameters.orderType) ) { // Revert if partial fill was attempted on an unsupported order. revert PartialFillsNotEnabledForOrder(); } // Retrieve current counter & use it w/ parameters to derive order hash. orderHash = _assertConsiderationLengthAndGetOrderHash(orderParameters); // Ensure restricted orders have a valid submitter or pass a zone check. _assertRestrictedAdvancedOrderValidity( advancedOrder, criteriaResolvers, priorOrderHashes, orderHash, orderParameters.zoneHash, orderParameters.orderType, orderParameters.offerer, orderParameters.zone ); // Retrieve the order status using the derived order hash. OrderStatus storage orderStatus = _orderStatus[orderHash]; // Ensure order is fillable and is not cancelled. if ( !_verifyOrderStatus( orderHash, orderStatus, false, // Allow partially used orders to be filled. revertOnInvalid ) ) { // Assuming an invalid order status and no revert, return zero fill. return (orderHash, 0, 0); } // If the order is not already validated, verify the supplied signature. if (!orderStatus.isValidated) { _verifySignature( orderParameters.offerer, orderHash, advancedOrder.signature ); } // Read filled amount as numerator and denominator and put on the stack. uint256 filledNumerator = orderStatus.numerator; uint256 filledDenominator = orderStatus.denominator; // If order (orderStatus) currently has a non-zero denominator it is // partially filled. if (filledDenominator != 0) { // If denominator of 1 supplied, fill all remaining amount on order. if (denominator == 1) { // Scale numerator & denominator to match current denominator. numerator = filledDenominator; denominator = filledDenominator; } // Otherwise, if supplied denominator differs from current one... else if (filledDenominator != denominator) { // scale current numerator by the supplied denominator, then... filledNumerator *= denominator; // the supplied numerator & denominator by current denominator. numerator *= filledDenominator; denominator *= filledDenominator; } // Once adjusted, if current+supplied numerator exceeds denominator: if (filledNumerator + numerator > denominator) { // Skip underflow check: denominator >= orderStatus.numerator unchecked { // Reduce current numerator so it + supplied = denominator. numerator = denominator - filledNumerator; } } // Increment the filled numerator by the new numerator. filledNumerator += numerator; // Use assembly to ensure fractional amounts are below max uint120. assembly { // Check filledNumerator and denominator for uint120 overflow. if or( gt(filledNumerator, MaxUint120), gt(denominator, MaxUint120) ) { // Derive greatest common divisor using euclidean algorithm. function gcd(_a, _b) -> out { for { } _b { } { let _c := _b _b := mod(_a, _c) _a := _c } out := _a } let scaleDown := gcd( numerator, gcd(filledNumerator, denominator) ) // Ensure that the divisor is at least one. let safeScaleDown := add(scaleDown, iszero(scaleDown)) // Scale all fractional values down by gcd. numerator := div(numerator, safeScaleDown) filledNumerator := div(filledNumerator, safeScaleDown) denominator := div(denominator, safeScaleDown) // Perform the overflow check a second time. if or( gt(filledNumerator, MaxUint120), gt(denominator, MaxUint120) ) { // Store the Panic error signature. mstore(0, Panic_error_signature) // Set arithmetic (0x11) panic code as initial argument. mstore(Panic_error_offset, Panic_arithmetic) // Return, supplying Panic signature & arithmetic code. revert(0, Panic_error_length) } } } // Skip overflow check: checked above unless numerator is reduced. unchecked { // Update order status and fill amount, packing struct values. orderStatus.isValidated = true; orderStatus.isCancelled = false; orderStatus.numerator = uint120(filledNumerator); orderStatus.denominator = uint120(denominator); } } else { // Update order status and fill amount, packing struct values. orderStatus.isValidated = true; orderStatus.isCancelled = false; orderStatus.numerator = uint120(numerator); orderStatus.denominator = uint120(denominator); } // Return order hash, a modified numerator, and a modified denominator. return (orderHash, numerator, denominator); } /** * @dev Internal function to cancel an arbitrary number of orders. Note that * only the offerer or the zone of a given order may cancel it. Callers * should ensure that the intended order was cancelled by calling * `getOrderStatus` and confirming that `isCancelled` returns `true`. * * @param orders The orders to cancel. * * @return cancelled A boolean indicating whether the supplied orders were * successfully cancelled. */ function _cancel(OrderComponents[] calldata orders) internal returns (bool cancelled) { // Ensure that the reentrancy guard is not currently set. _assertNonReentrant(); // Declare variables outside of the loop. OrderStatus storage orderStatus; address offerer; address zone; // Skip overflow check as for loop is indexed starting at zero. unchecked { // Read length of the orders array from memory and place on stack. uint256 totalOrders = orders.length; // Iterate over each order. for (uint256 i = 0; i < totalOrders; ) { // Retrieve the order. OrderComponents calldata order = orders[i]; offerer = order.offerer; zone = order.zone; // Ensure caller is either offerer or zone of the order. if (msg.sender != offerer && msg.sender != zone) { revert InvalidCanceller(); } // Derive order hash using the order parameters and the counter. bytes32 orderHash = _deriveOrderHash( OrderParameters( offerer, zone, order.offer, order.consideration, order.orderType, order.startTime, order.endTime, order.zoneHash, order.salt, order.conduitKey, order.consideration.length ), order.counter ); // Retrieve the order status using the derived order hash. orderStatus = _orderStatus[orderHash]; // Update the order status as not valid and cancelled. orderStatus.isValidated = false; orderStatus.isCancelled = true; // Emit an event signifying that the order has been cancelled. emit OrderCancelled(orderHash, offerer, zone); // Increment counter inside body of loop for gas efficiency. ++i; } } // Return a boolean indicating that orders were successfully cancelled. cancelled = true; } /** * @dev Internal function to validate an arbitrary number of orders, thereby * registering their signatures as valid and allowing the fulfiller to * skip signature verification on fulfillment. Note that validated * orders may still be unfulfillable due to invalid item amounts or * other factors; callers should determine whether validated orders are * fulfillable by simulating the fulfillment call prior to execution. * Also note that anyone can validate a signed order, but only the * offerer can validate an order without supplying a signature. * * @param orders The orders to validate. * * @return validated A boolean indicating whether the supplied orders were * successfully validated. */ function _validate(Order[] calldata orders) internal returns (bool validated) { // Ensure that the reentrancy guard is not currently set. _assertNonReentrant(); // Declare variables outside of the loop. OrderStatus storage orderStatus; bytes32 orderHash; address offerer; // Skip overflow check as for loop is indexed starting at zero. unchecked { // Read length of the orders array from memory and place on stack. uint256 totalOrders = orders.length; // Iterate over each order. for (uint256 i = 0; i < totalOrders; ) { // Retrieve the order. Order calldata order = orders[i]; // Retrieve the order parameters. OrderParameters calldata orderParameters = order.parameters; // Move offerer from memory to the stack. offerer = orderParameters.offerer; // Get current counter & use it w/ params to derive order hash. orderHash = _assertConsiderationLengthAndGetOrderHash( orderParameters ); // Retrieve the order status using the derived order hash. orderStatus = _orderStatus[orderHash]; // Ensure order is fillable and retrieve the filled amount. _verifyOrderStatus( orderHash, orderStatus, false, // Signifies that partially filled orders are valid. true // Signifies to revert if the order is invalid. ); // If the order has not already been validated... if (!orderStatus.isValidated) { // Verify the supplied signature. _verifySignature(offerer, orderHash, order.signature); // Update order status to mark the order as valid. orderStatus.isValidated = true; // Emit an event signifying the order has been validated. emit OrderValidated( orderHash, offerer, orderParameters.zone ); } // Increment counter inside body of the loop for gas efficiency. ++i; } } // Return a boolean indicating that orders were successfully validated. validated = true; } /** * @dev Internal view function to retrieve the status of a given order by * hash, including whether the order has been cancelled or validated * and the fraction of the order that has been filled. * * @param orderHash The order hash in question. * * @return isValidated A boolean indicating whether the order in question * has been validated (i.e. previously approved or * partially filled). * @return isCancelled A boolean indicating whether the order in question * has been cancelled. * @return totalFilled The total portion of the order that has been filled * (i.e. the "numerator"). * @return totalSize The total size of the order that is either filled or * unfilled (i.e. the "denominator"). */ function _getOrderStatus(bytes32 orderHash) internal view returns ( bool isValidated, bool isCancelled, uint256 totalFilled, uint256 totalSize ) { // Retrieve the order status using the order hash. OrderStatus storage orderStatus = _orderStatus[orderHash]; // Return the fields on the order status. return ( orderStatus.isValidated, orderStatus.isCancelled, orderStatus.numerator, orderStatus.denominator ); } /** * @dev Internal pure function to check whether a given order type indicates * that partial fills are not supported (e.g. only "full fills" are * allowed for the order in question). * * @param orderType The order type in question. * * @return isFullOrder A boolean indicating whether the order type only * supports full fills. */ function _doesNotSupportPartialFills(OrderType orderType) internal pure returns (bool isFullOrder) { // The "full" order types are even, while "partial" order types are odd. // Bitwise and by 1 is equivalent to modulo by 2, but 2 gas cheaper. assembly { // Equivalent to `uint256(orderType) & 1 == 0`. isFullOrder := iszero(and(orderType, 1)) } } }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.7; // prettier-ignore import { ConduitTransfer, ConduitBatch1155Transfer } from "./ConduitStructs.sol"; /** * @title ConduitInterface * @author 0age * @notice ConduitInterface contains all external function interfaces, events, * and errors for conduit contracts. */ interface ConduitInterface { /** * @dev Revert with an error when attempting to execute transfers using a * caller that does not have an open channel. */ error ChannelClosed(address channel); /** * @dev Revert with an error when attempting to update a channel to the * current status of that channel. */ error ChannelStatusAlreadySet(address channel, bool isOpen); /** * @dev Revert with an error when attempting to execute a transfer for an * item that does not have an ERC20/721/1155 item type. */ error InvalidItemType(); /** * @dev Revert with an error when attempting to update the status of a * channel from a caller that is not the conduit controller. */ error InvalidController(); /** * @dev Emit an event whenever a channel is opened or closed. * * @param channel The channel that has been updated. * @param open A boolean indicating whether the conduit is open or not. */ event ChannelUpdated(address indexed channel, bool open); /** * @notice Execute a sequence of ERC20/721/1155 transfers. Only a caller * with an open channel can call this function. * * @param transfers The ERC20/721/1155 transfers to perform. * * @return magicValue A magic value indicating that the transfers were * performed successfully. */ function execute(ConduitTransfer[] calldata transfers) external returns (bytes4 magicValue); /** * @notice Execute a sequence of batch 1155 transfers. Only a caller with an * open channel can call this function. * * @param batch1155Transfers The 1155 batch transfers to perform. * * @return magicValue A magic value indicating that the transfers were * performed successfully. */ function executeBatch1155( ConduitBatch1155Transfer[] calldata batch1155Transfers ) external returns (bytes4 magicValue); /** * @notice Execute a sequence of transfers, both single and batch 1155. Only * a caller with an open channel can call this function. * * @param standardTransfers The ERC20/721/1155 transfers to perform. * @param batch1155Transfers The 1155 batch transfers to perform. * * @return magicValue A magic value indicating that the transfers were * performed successfully. */ function executeWithBatch1155( ConduitTransfer[] calldata standardTransfers, ConduitBatch1155Transfer[] calldata batch1155Transfers ) external returns (bytes4 magicValue); /** * @notice Open or close a given channel. Only callable by the controller. * * @param channel The channel to open or close. * @param isOpen The status of the channel (either open or closed). */ function updateChannel(address channel, bool isOpen) external; }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.7; /** * @title AmountDerivationErrors * @author 0age * @notice AmountDerivationErrors contains errors related to amount derivation. */ interface AmountDerivationErrors { /** * @dev Revert with an error when attempting to apply a fraction as part of * a partial fill that does not divide the target amount cleanly. */ error InexactFraction(); }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.13; import { ZoneInterface } from "./ZoneInterface.sol"; import { OrderType } from "./ConsiderationEnums.sol"; // prettier-ignore import { AdvancedOrder, CriteriaResolver } from "./ConsiderationStructs.sol"; import "./ConsiderationConstants.sol"; // prettier-ignore import { ZoneInteractionErrors } from "./ZoneInteractionErrors.sol"; import { LowLevelHelpers } from "./LowLevelHelpers.sol"; /** * @title ZoneInteraction * @author 0age * @notice ZoneInteraction contains logic related to interacting with zones. */ contract ZoneInteraction is ZoneInteractionErrors, LowLevelHelpers { /** * @dev Internal view function to determine if an order has a restricted * order type and, if so, to ensure that either the offerer or the zone * are the fulfiller or that a staticcall to `isValidOrder` on the zone * returns a magic value indicating that the order is currently valid. * * @param orderHash The hash of the order. * @param zoneHash The hash to provide upon calling the zone. * @param orderType The type of the order. * @param offerer The offerer in question. * @param zone The zone in question. */ function _assertRestrictedBasicOrderValidity( bytes32 orderHash, bytes32 zoneHash, OrderType orderType, address offerer, address zone ) internal view { // Order type 2-3 require zone or offerer be caller or zone to approve. if ( uint256(orderType) > 1 && msg.sender != zone && msg.sender != offerer ) { // Perform minimal staticcall to the zone. _callIsValidOrder(zone, orderHash, offerer, zoneHash); } } function _callIsValidOrder( address zone, bytes32 orderHash, address offerer, bytes32 zoneHash ) internal view { // Perform minimal staticcall to the zone. bool success = _staticcall( zone, abi.encodeWithSelector( ZoneInterface.isValidOrder.selector, orderHash, msg.sender, offerer, zoneHash ) ); // Ensure call was successful and returned the correct magic value. _assertIsValidOrderStaticcallSuccess(success, orderHash); } /** * @dev Internal view function to determine whether an order is a restricted * order and, if so, to ensure that it was either submitted by the * offerer or the zone for the order, or that the zone returns the * expected magic value upon performing a staticcall to `isValidOrder` * or `isValidOrderIncludingExtraData` depending on whether the order * fulfillment specifies extra data or criteria resolvers. * * @param advancedOrder The advanced order in question. * @param criteriaResolvers An array where each element contains a reference * to a specific offer or consideration, a token * identifier, and a proof that the supplied token * identifier is contained in the order's merkle * root. Note that a criteria of zero indicates * that any (transferable) token identifier is * valid and that no proof needs to be supplied. * @param priorOrderHashes The order hashes of each order supplied prior to * the current order as part of a "match" variety * of order fulfillment (e.g. this array will be * empty for single or "fulfill available"). * @param orderHash The hash of the order. * @param zoneHash The hash to provide upon calling the zone. * @param orderType The type of the order. * @param offerer The offerer in question. * @param zone The zone in question. */ function _assertRestrictedAdvancedOrderValidity( AdvancedOrder memory advancedOrder, CriteriaResolver[] memory criteriaResolvers, bytes32[] memory priorOrderHashes, bytes32 orderHash, bytes32 zoneHash, OrderType orderType, address offerer, address zone ) internal view { // Order type 2-3 require zone or offerer be caller or zone to approve. if ( uint256(orderType) > 1 && msg.sender != zone && msg.sender != offerer ) { // If no extraData or criteria resolvers are supplied... if ( advancedOrder.extraData.length == 0 && criteriaResolvers.length == 0 ) { // Perform minimal staticcall to the zone. _callIsValidOrder(zone, orderHash, offerer, zoneHash); } else { // Otherwise, extra data or criteria resolvers were supplied; in // that event, perform a more verbose staticcall to the zone. bool success = _staticcall( zone, abi.encodeWithSelector( ZoneInterface.isValidOrderIncludingExtraData.selector, orderHash, msg.sender, advancedOrder, priorOrderHashes, criteriaResolvers ) ); // Ensure call was successful and returned correct magic value. _assertIsValidOrderStaticcallSuccess(success, orderHash); } } } /** * @dev Internal view function to ensure that a staticcall to `isValidOrder` * or `isValidOrderIncludingExtraData` as part of validating a * restricted order that was not submitted by the named offerer or zone * was successful and returned the required magic value. * * @param success A boolean indicating the status of the staticcall. * @param orderHash The order hash of the order in question. */ function _assertIsValidOrderStaticcallSuccess( bool success, bytes32 orderHash ) internal view { // If the call failed... if (!success) { // Revert and pass reason along if one was returned. _revertWithReasonIfOneIsReturned(); // Otherwise, revert with a generic error message. revert InvalidRestrictedOrder(orderHash); } // Ensure result was extracted and matches isValidOrder magic value. if (_doesNotMatchMagic(ZoneInterface.isValidOrder.selector)) { revert InvalidRestrictedOrder(orderHash); } } }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.13; import { ConduitInterface } from "./ConduitInterface.sol"; import { ConduitItemType } from "./ConduitEnums.sol"; import { ItemType } from "./ConsiderationEnums.sol"; import { ReceivedItem } from "./ConsiderationStructs.sol"; import { Verifiers } from "./Verifiers.sol"; import { TokenTransferrer } from "./TokenTransferrer.sol"; import "./ConsiderationConstants.sol"; /** * @title Executor * @author 0age * @notice Executor contains functions related to processing executions (i.e. * transferring items, either directly or via conduits). */ contract Executor is Verifiers, TokenTransferrer { /** * @dev Derive and set hashes, reference chainId, and associated domain * separator during deployment. * * @param conduitController A contract that deploys conduits, or proxies * that may optionally be used to transfer approved * ERC20/721/1155 tokens. */ constructor(address conduitController) Verifiers(conduitController) {} /** * @dev Internal function to transfer a given item, either directly or via * a corresponding conduit. * * @param item The item to transfer, including an amount and a * recipient. * @param from The account supplying the item. * @param conduitKey A bytes32 value indicating what corresponding conduit, * if any, to source token approvals from. The zero hash * signifies that no conduit should be used, with direct * approvals set on this contract. * @param accumulator An open-ended array that collects transfers to execute * against a given conduit in a single call. */ function _transfer( ReceivedItem memory item, address from, bytes32 conduitKey, bytes memory accumulator ) internal { // If the item type indicates Ether or a native token... if (item.itemType == ItemType.NATIVE) { // Ensure neither the token nor the identifier parameters are set. if ((uint160(item.token) | item.identifier) != 0) { revert UnusedItemParameters(); } // transfer the native tokens to the recipient. _transferEth(item.recipient, item.amount); } else if (item.itemType == ItemType.ERC20) { // Ensure that no identifier is supplied. if (item.identifier != 0) { revert UnusedItemParameters(); } // Transfer ERC20 tokens from the source to the recipient. _transferERC20( item.token, from, item.recipient, item.amount, conduitKey, accumulator ); } else if (item.itemType == ItemType.ERC721) { // Transfer ERC721 token from the source to the recipient. _transferERC721( item.token, from, item.recipient, item.identifier, item.amount, conduitKey, accumulator ); } else { // Transfer ERC1155 token from the source to the recipient. _transferERC1155( item.token, from, item.recipient, item.identifier, item.amount, conduitKey, accumulator ); } } /** * @dev Internal function to transfer an individual ERC721 or ERC1155 item * from a given originator to a given recipient. The accumulator will * be bypassed, meaning that this function should be utilized in cases * where multiple item transfers can be accumulated into a single * conduit call. Sufficient approvals must be set, either on the * respective conduit or on this contract itself. * * @param itemType The type of item to transfer, either ERC721 or ERC1155. * @param token The token to transfer. * @param from The originator of the transfer. * @param to The recipient of the transfer. * @param identifier The tokenId to transfer. * @param amount The amount to transfer. * @param conduitKey A bytes32 value indicating what corresponding conduit, * if any, to source token approvals from. The zero hash * signifies that no conduit should be used, with direct * approvals set on this contract. */ function _transferIndividual721Or1155Item( ItemType itemType, address token, address from, address to, uint256 identifier, uint256 amount, bytes32 conduitKey ) internal { // Determine if the transfer is to be performed via a conduit. if (conduitKey != bytes32(0)) { // Use free memory pointer as calldata offset for the conduit call. uint256 callDataOffset; // Utilize assembly to place each argument in free memory. assembly { // Retrieve the free memory pointer and use it as the offset. callDataOffset := mload(FreeMemoryPointerSlot) // Write ConduitInterface.execute.selector to memory. mstore(callDataOffset, Conduit_execute_signature) // Write the offset to the ConduitTransfer array in memory. mstore( add( callDataOffset, Conduit_execute_ConduitTransfer_offset_ptr ), Conduit_execute_ConduitTransfer_ptr ) // Write the length of the ConduitTransfer array to memory. mstore( add( callDataOffset, Conduit_execute_ConduitTransfer_length_ptr ), Conduit_execute_ConduitTransfer_length ) // Write the item type to memory. mstore( add(callDataOffset, Conduit_execute_transferItemType_ptr), itemType ) // Write the token to memory. mstore( add(callDataOffset, Conduit_execute_transferToken_ptr), token ) // Write the transfer source to memory. mstore( add(callDataOffset, Conduit_execute_transferFrom_ptr), from ) // Write the transfer recipient to memory. mstore(add(callDataOffset, Conduit_execute_transferTo_ptr), to) // Write the token identifier to memory. mstore( add(callDataOffset, Conduit_execute_transferIdentifier_ptr), identifier ) // Write the transfer amount to memory. mstore( add(callDataOffset, Conduit_execute_transferAmount_ptr), amount ) } // Perform the call to the conduit. _callConduitUsingOffsets( conduitKey, callDataOffset, OneConduitExecute_size ); } else { // Otherwise, determine whether it is an ERC721 or ERC1155 item. if (itemType == ItemType.ERC721) { // Ensure that exactly one 721 item is being transferred. if (amount != 1) { revert InvalidERC721TransferAmount(); } // Perform transfer via the token contract directly. _performERC721Transfer(token, from, to, identifier); } else { // Perform transfer via the token contract directly. _performERC1155Transfer(token, from, to, identifier, amount); } } } /** * @dev Internal function to transfer Ether or other native tokens to a * given recipient. * * @param to The recipient of the transfer. * @param amount The amount to transfer. */ function _transferEth(address payable to, uint256 amount) internal { // Ensure that the supplied amount is non-zero. _assertNonZeroAmount(amount); // Declare a variable indicating whether the call was successful or not. bool success; assembly { // Transfer the ETH and store if it succeeded or not. success := call(gas(), to, amount, 0, 0, 0, 0) } // If the call fails... if (!success) { // Revert and pass the revert reason along if one was returned. _revertWithReasonIfOneIsReturned(); // Otherwise, revert with a generic error message. revert EtherTransferGenericFailure(to, amount); } } /** * @dev Internal function to transfer ERC20 tokens from a given originator * to a given recipient using a given conduit if applicable. Sufficient * approvals must be set on this contract or on a respective conduit. * * @param token The ERC20 token to transfer. * @param from The originator of the transfer. * @param to The recipient of the transfer. * @param amount The amount to transfer. * @param conduitKey A bytes32 value indicating what corresponding conduit, * if any, to source token approvals from. The zero hash * signifies that no conduit should be used, with direct * approvals set on this contract. * @param accumulator An open-ended array that collects transfers to execute * against a given conduit in a single call. */ function _transferERC20( address token, address from, address to, uint256 amount, bytes32 conduitKey, bytes memory accumulator ) internal { // Ensure that the supplied amount is non-zero. _assertNonZeroAmount(amount); // Trigger accumulated transfers if the conduits differ. _triggerIfArmedAndNotAccumulatable(accumulator, conduitKey); // If no conduit has been specified... if (conduitKey == bytes32(0)) { // Perform the token transfer directly. _performERC20Transfer(token, from, to, amount); } else { // Insert the call to the conduit into the accumulator. _insert( conduitKey, accumulator, ConduitItemType.ERC20, token, from, to, uint256(0), amount ); } } /** * @dev Internal function to transfer a single ERC721 token from a given * originator to a given recipient. Sufficient approvals must be set, * either on the respective conduit or on this contract itself. * * @param token The ERC721 token to transfer. * @param from The originator of the transfer. * @param to The recipient of the transfer. * @param identifier The tokenId to transfer (must be 1 for ERC721). * @param amount The amount to transfer. * @param conduitKey A bytes32 value indicating what corresponding conduit, * if any, to source token approvals from. The zero hash * signifies that no conduit should be used, with direct * approvals set on this contract. * @param accumulator An open-ended array that collects transfers to execute * against a given conduit in a single call. */ function _transferERC721( address token, address from, address to, uint256 identifier, uint256 amount, bytes32 conduitKey, bytes memory accumulator ) internal { // Trigger accumulated transfers if the conduits differ. _triggerIfArmedAndNotAccumulatable(accumulator, conduitKey); // If no conduit has been specified... if (conduitKey == bytes32(0)) { // Ensure that exactly one 721 item is being transferred. if (amount != 1) { revert InvalidERC721TransferAmount(); } // Perform transfer via the token contract directly. _performERC721Transfer(token, from, to, identifier); } else { // Insert the call to the conduit into the accumulator. _insert( conduitKey, accumulator, ConduitItemType.ERC721, token, from, to, identifier, amount ); } } /** * @dev Internal function to transfer ERC1155 tokens from a given originator * to a given recipient. Sufficient approvals must be set, either on * the respective conduit or on this contract itself. * * @param token The ERC1155 token to transfer. * @param from The originator of the transfer. * @param to The recipient of the transfer. * @param identifier The id to transfer. * @param amount The amount to transfer. * @param conduitKey A bytes32 value indicating what corresponding conduit, * if any, to source token approvals from. The zero hash * signifies that no conduit should be used, with direct * approvals set on this contract. * @param accumulator An open-ended array that collects transfers to execute * against a given conduit in a single call. */ function _transferERC1155( address token, address from, address to, uint256 identifier, uint256 amount, bytes32 conduitKey, bytes memory accumulator ) internal { // Ensure that the supplied amount is non-zero. _assertNonZeroAmount(amount); // Trigger accumulated transfers if the conduits differ. _triggerIfArmedAndNotAccumulatable(accumulator, conduitKey); // If no conduit has been specified... if (conduitKey == bytes32(0)) { // Perform transfer via the token contract directly. _performERC1155Transfer(token, from, to, identifier, amount); } else { // Insert the call to the conduit into the accumulator. _insert( conduitKey, accumulator, ConduitItemType.ERC1155, token, from, to, identifier, amount ); } } /** * @dev Internal function to trigger a call to the conduit currently held by * the accumulator if the accumulator contains item transfers (i.e. it * is "armed") and the supplied conduit key does not match the key held * by the accumulator. * * @param accumulator An open-ended array that collects transfers to execute * against a given conduit in a single call. * @param conduitKey A bytes32 value indicating what corresponding conduit, * if any, to source token approvals from. The zero hash * signifies that no conduit should be used, with direct * approvals set on this contract. */ function _triggerIfArmedAndNotAccumulatable( bytes memory accumulator, bytes32 conduitKey ) internal { // Retrieve the current conduit key from the accumulator. bytes32 accumulatorConduitKey = _getAccumulatorConduitKey(accumulator); // Perform conduit call if the set key does not match the supplied key. if (accumulatorConduitKey != conduitKey) { _triggerIfArmed(accumulator); } } /** * @dev Internal function to trigger a call to the conduit currently held by * the accumulator if the accumulator contains item transfers (i.e. it * is "armed"). * * @param accumulator An open-ended array that collects transfers to execute * against a given conduit in a single call. */ function _triggerIfArmed(bytes memory accumulator) internal { // Exit if the accumulator is not "armed". if (accumulator.length != AccumulatorArmed) { return; } // Retrieve the current conduit key from the accumulator. bytes32 accumulatorConduitKey = _getAccumulatorConduitKey(accumulator); // Perform conduit call. _trigger(accumulatorConduitKey, accumulator); } /** * @dev Internal function to trigger a call to the conduit corresponding to * a given conduit key, supplying all accumulated item transfers. The * accumulator will be "disarmed" and reset in the process. * * @param conduitKey A bytes32 value indicating what corresponding conduit, * if any, to source token approvals from. The zero hash * signifies that no conduit should be used, with direct * approvals set on this contract. * @param accumulator An open-ended array that collects transfers to execute * against a given conduit in a single call. */ function _trigger(bytes32 conduitKey, bytes memory accumulator) internal { // Declare variables for offset in memory & size of calldata to conduit. uint256 callDataOffset; uint256 callDataSize; // Call the conduit with all the accumulated transfers. assembly { // Call begins at third word; the first is length or "armed" status, // and the second is the current conduit key. callDataOffset := add(accumulator, TwoWords) // 68 + items * 192 callDataSize := add( Accumulator_array_offset_ptr, mul( mload(add(accumulator, Accumulator_array_length_ptr)), Conduit_transferItem_size ) ) } // Call conduit derived from conduit key & supply accumulated transfers. _callConduitUsingOffsets(conduitKey, callDataOffset, callDataSize); // Reset accumulator length to signal that it is now "disarmed". assembly { mstore(accumulator, AccumulatorDisarmed) } } /** * @dev Internal function to perform a call to the conduit corresponding to * a given conduit key based on the offset and size of the calldata in * question in memory. * * @param conduitKey A bytes32 value indicating what corresponding * conduit, if any, to source token approvals from. * The zero hash signifies that no conduit should be * used, with direct approvals set on this contract. * @param callDataOffset The memory pointer where calldata is contained. * @param callDataSize The size of calldata in memory. */ function _callConduitUsingOffsets( bytes32 conduitKey, uint256 callDataOffset, uint256 callDataSize ) internal { // Derive the address of the conduit using the conduit key. address conduit = _deriveConduit(conduitKey); bool success; bytes4 result; // call the conduit. assembly { // Ensure first word of scratch space is empty. mstore(0, 0) // Perform call, placing first word of return data in scratch space. success := call( gas(), conduit, 0, callDataOffset, callDataSize, 0, OneWord ) // Take value from scratch space and place it on the stack. result := mload(0) } // If the call failed... if (!success) { // Pass along whatever revert reason was given by the conduit. _revertWithReasonIfOneIsReturned(); // Otherwise, revert with a generic error. revert InvalidCallToConduit(conduit); } // Ensure result was extracted and matches EIP-1271 magic value. if (result != ConduitInterface.execute.selector) { revert InvalidConduit(conduitKey, conduit); } } /** * @dev Internal pure function to retrieve the current conduit key set for * the accumulator. * * @param accumulator An open-ended array that collects transfers to execute * against a given conduit in a single call. * * @return accumulatorConduitKey The conduit key currently set for the * accumulator. */ function _getAccumulatorConduitKey(bytes memory accumulator) internal pure returns (bytes32 accumulatorConduitKey) { // Retrieve the current conduit key from the accumulator. assembly { accumulatorConduitKey := mload( add(accumulator, Accumulator_conduitKey_ptr) ) } } /** * @dev Internal pure function to place an item transfer into an accumulator * that collects a series of transfers to execute against a given * conduit in a single call. * * @param conduitKey A bytes32 value indicating what corresponding conduit, * if any, to source token approvals from. The zero hash * signifies that no conduit should be used, with direct * approvals set on this contract. * @param accumulator An open-ended array that collects transfers to execute * against a given conduit in a single call. * @param itemType The type of the item to transfer. * @param token The token to transfer. * @param from The originator of the transfer. * @param to The recipient of the transfer. * @param identifier The tokenId to transfer. * @param amount The amount to transfer. */ function _insert( bytes32 conduitKey, bytes memory accumulator, ConduitItemType itemType, address token, address from, address to, uint256 identifier, uint256 amount ) internal pure { uint256 elements; // "Arm" and prime accumulator if it's not already armed. The sentinel // value is held in the length of the accumulator array. if (accumulator.length == AccumulatorDisarmed) { elements = 1; bytes4 selector = ConduitInterface.execute.selector; assembly { mstore(accumulator, AccumulatorArmed) // "arm" the accumulator. mstore(add(accumulator, Accumulator_conduitKey_ptr), conduitKey) mstore(add(accumulator, Accumulator_selector_ptr), selector) mstore( add(accumulator, Accumulator_array_offset_ptr), Accumulator_array_offset ) mstore(add(accumulator, Accumulator_array_length_ptr), elements) } } else { // Otherwise, increase the number of elements by one. assembly { elements := add( mload(add(accumulator, Accumulator_array_length_ptr)), 1 ) mstore(add(accumulator, Accumulator_array_length_ptr), elements) } } // Insert the item. assembly { let itemPointer := sub( add(accumulator, mul(elements, Conduit_transferItem_size)), Accumulator_itemSizeOffsetDifference ) mstore(itemPointer, itemType) mstore(add(itemPointer, Conduit_transferItem_token_ptr), token) mstore(add(itemPointer, Conduit_transferItem_from_ptr), from) mstore(add(itemPointer, Conduit_transferItem_to_ptr), to) mstore( add(itemPointer, Conduit_transferItem_identifier_ptr), identifier ) mstore(add(itemPointer, Conduit_transferItem_amount_ptr), amount) } } }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.7; import { ConduitItemType } from "./ConduitEnums.sol"; struct ConduitTransfer { ConduitItemType itemType; address token; address from; address to; uint256 identifier; uint256 amount; } struct ConduitBatch1155Transfer { address token; address from; address to; uint256[] ids; uint256[] amounts; }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.13; import "./ConsiderationConstants.sol"; /** * @title LowLevelHelpers * @author 0age * @notice LowLevelHelpers contains logic for performing various low-level * operations. */ contract LowLevelHelpers { /** * @dev Internal view function to staticcall an arbitrary target with given * calldata. Note that no data is written to memory and no contract * size check is performed. * * @param target The account to staticcall. * @param callData The calldata to supply when staticcalling the target. * * @return success The status of the staticcall to the target. */ function _staticcall(address target, bytes memory callData) internal view returns (bool success) { assembly { // Perform the staticcall. success := staticcall( gas(), target, add(callData, OneWord), mload(callData), 0, 0 ) } } /** * @dev Internal view function to revert and pass along the revert reason if * data was returned by the last call and that the size of that data * does not exceed the currently allocated memory size. */ function _revertWithReasonIfOneIsReturned() internal view { assembly { // If it returned a message, bubble it up as long as sufficient gas // remains to do so: if returndatasize() { // Ensure that sufficient gas is available to copy returndata // while expanding memory where necessary. Start by computing // the word size of returndata and allocated memory. let returnDataWords := div( add(returndatasize(), AlmostOneWord), OneWord ) // Note: use the free memory pointer in place of msize() to work // around a Yul warning that prevents accessing msize directly // when the IR pipeline is activated. let msizeWords := div(mload(FreeMemoryPointerSlot), OneWord) // Next, compute the cost of the returndatacopy. let cost := mul(CostPerWord, returnDataWords) // Then, compute cost of new memory allocation. if gt(returnDataWords, msizeWords) { cost := add( cost, add( mul(sub(returnDataWords, msizeWords), CostPerWord), div( sub( mul(returnDataWords, returnDataWords), mul(msizeWords, msizeWords) ), MemoryExpansionCoefficient ) ) ) } // Finally, add a small constant and compare to gas remaining; // bubble up the revert data if enough gas is still available. if lt(add(cost, ExtraGasBuffer), gas()) { // Copy returndata to memory; overwrite existing memory. returndatacopy(0, 0, returndatasize()) // Revert, specifying memory region with copied returndata. revert(0, returndatasize()) } } } } /** * @dev Internal pure function to determine if the first word of returndata * matches an expected magic value. * * @param expected The expected magic value. * * @return A boolean indicating whether the expected value matches the one * located in the first word of returndata. */ function _doesNotMatchMagic(bytes4 expected) internal pure returns (bool) { // Declare a variable for the value held by the return data buffer. bytes4 result; // Utilize assembly in order to read directly from returndata buffer. assembly { // Only put result on stack if return data is exactly one word. if eq(returndatasize(), OneWord) { // Copy the word directly from return data into scratch space. returndatacopy(0, 0, OneWord) // Take value from scratch space and place it on the stack. result := mload(0) } } // Return a boolean indicating whether expected and located value match. return result != expected; } }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.7; /** * @title ZoneInteractionErrors * @author 0age * @notice ZoneInteractionErrors contains errors related to zone interaction. */ interface ZoneInteractionErrors { /** * @dev Revert with an error when attempting to fill an order that specifies * a restricted submitter as its order type when not submitted by * either the offerer or the order's zone or approved as valid by the * zone in question via a staticcall to `isValidOrder`. * * @param orderHash The order hash for the invalid restricted order. */ error InvalidRestrictedOrder(bytes32 orderHash); }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.7; // prettier-ignore import { AdvancedOrder, CriteriaResolver } from "./ConsiderationStructs.sol"; interface ZoneInterface { // Called by Consideration whenever extraData is not provided by the caller. function isValidOrder( bytes32 orderHash, address caller, address offerer, bytes32 zoneHash ) external view returns (bytes4 validOrderMagicValue); // Called by Consideration whenever any extraData is provided by the caller. function isValidOrderIncludingExtraData( bytes32 orderHash, address caller, AdvancedOrder calldata order, bytes32[] calldata priorOrderHashes, CriteriaResolver[] calldata criteriaResolvers ) external view returns (bytes4 validOrderMagicValue); }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.7; import "./TokenTransferrerConstants.sol"; // prettier-ignore import { TokenTransferrerErrors } from "./TokenTransferrerErrors.sol"; import { ConduitBatch1155Transfer } from "./ConduitStructs.sol"; /** * @title TokenTransferrer * @author 0age * @custom:coauthor d1ll0n * @custom:coauthor transmissions11 * @notice TokenTransferrer is a library for performing optimized ERC20, ERC721, * ERC1155, and batch ERC1155 transfers, used by both Seaport as well as * by conduits deployed by the ConduitController. Use great caution when * considering these functions for use in other codebases, as there are * significant side effects and edge cases that need to be thoroughly * understood and carefully addressed. */ contract TokenTransferrer is TokenTransferrerErrors { /** * @dev Internal function to transfer ERC20 tokens from a given originator * to a given recipient. Sufficient approvals must be set on the * contract performing the transfer. * * @param token The ERC20 token to transfer. * @param from The originator of the transfer. * @param to The recipient of the transfer. * @param amount The amount to transfer. */ function _performERC20Transfer( address token, address from, address to, uint256 amount ) internal { // Utilize assembly to perform an optimized ERC20 token transfer. assembly { // The free memory pointer memory slot will be used when populating // call data for the transfer; read the value and restore it later. let memPointer := mload(FreeMemoryPointerSlot) // Write call data into memory, starting with function selector. mstore(ERC20_transferFrom_sig_ptr, ERC20_transferFrom_signature) mstore(ERC20_transferFrom_from_ptr, from) mstore(ERC20_transferFrom_to_ptr, to) mstore(ERC20_transferFrom_amount_ptr, amount) // Make call & copy up to 32 bytes of return data to scratch space. // Scratch space does not need to be cleared ahead of time, as the // subsequent check will ensure that either at least a full word of // return data is received (in which case it will be overwritten) or // that no data is received (in which case scratch space will be // ignored) on a successful call to the given token. let callStatus := call( gas(), token, 0, ERC20_transferFrom_sig_ptr, ERC20_transferFrom_length, 0, OneWord ) // Determine whether transfer was successful using status & result. let success := and( // Set success to whether the call reverted, if not check it // either returned exactly 1 (can't just be non-zero data), or // had no return data. or( and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize()) ), callStatus ) // Handle cases where either the transfer failed or no data was // returned. Group these, as most transfers will succeed with data. // Equivalent to `or(iszero(success), iszero(returndatasize()))` // but after it's inverted for JUMPI this expression is cheaper. if iszero(and(success, iszero(iszero(returndatasize())))) { // If the token has no code or the transfer failed: Equivalent // to `or(iszero(success), iszero(extcodesize(token)))` but // after it's inverted for JUMPI this expression is cheaper. if iszero(and(iszero(iszero(extcodesize(token))), success)) { // If the transfer failed: if iszero(success) { // If it was due to a revert: if iszero(callStatus) { // If it returned a message, bubble it up as long as // sufficient gas remains to do so: if returndatasize() { // Ensure that sufficient gas is available to // copy returndata while expanding memory where // necessary. Start by computing the word size // of returndata and allocated memory. Round up // to the nearest full word. let returnDataWords := div( add(returndatasize(), AlmostOneWord), OneWord ) // Note: use the free memory pointer in place of // msize() to work around a Yul warning that // prevents accessing msize directly when the IR // pipeline is activated. let msizeWords := div(memPointer, OneWord) // Next, compute the cost of the returndatacopy. let cost := mul(CostPerWord, returnDataWords) // Then, compute cost of new memory allocation. if gt(returnDataWords, msizeWords) { cost := add( cost, add( mul( sub( returnDataWords, msizeWords ), CostPerWord ), div( sub( mul( returnDataWords, returnDataWords ), mul(msizeWords, msizeWords) ), MemoryExpansionCoefficient ) ) ) } // Finally, add a small constant and compare to // gas remaining; bubble up the revert data if // enough gas is still available. if lt(add(cost, ExtraGasBuffer), gas()) { // Copy returndata to memory; overwrite // existing memory. returndatacopy(0, 0, returndatasize()) // Revert, specifying memory region with // copied returndata. revert(0, returndatasize()) } } // Otherwise revert with a generic error message. mstore( TokenTransferGenericFailure_error_sig_ptr, TokenTransferGenericFailure_error_signature ) mstore( TokenTransferGenericFailure_error_token_ptr, token ) mstore( TokenTransferGenericFailure_error_from_ptr, from ) mstore(TokenTransferGenericFailure_error_to_ptr, to) mstore(TokenTransferGenericFailure_error_id_ptr, 0) mstore( TokenTransferGenericFailure_error_amount_ptr, amount ) revert( TokenTransferGenericFailure_error_sig_ptr, TokenTransferGenericFailure_error_length ) } // Otherwise revert with a message about the token // returning false or non-compliant return values. mstore( BadReturnValueFromERC20OnTransfer_error_sig_ptr, BadReturnValueFromERC20OnTransfer_error_signature ) mstore( BadReturnValueFromERC20OnTransfer_error_token_ptr, token ) mstore( BadReturnValueFromERC20OnTransfer_error_from_ptr, from ) mstore( BadReturnValueFromERC20OnTransfer_error_to_ptr, to ) mstore( BadReturnValueFromERC20OnTransfer_error_amount_ptr, amount ) revert( BadReturnValueFromERC20OnTransfer_error_sig_ptr, BadReturnValueFromERC20OnTransfer_error_length ) } // Otherwise, revert with error about token not having code: mstore(NoContract_error_sig_ptr, NoContract_error_signature) mstore(NoContract_error_token_ptr, token) revert(NoContract_error_sig_ptr, NoContract_error_length) } // Otherwise, the token just returned no data despite the call // having succeeded; no need to optimize for this as it's not // technically ERC20 compliant. } // Restore the original free memory pointer. mstore(FreeMemoryPointerSlot, memPointer) // Restore the zero slot to zero. mstore(ZeroSlot, 0) } } /** * @dev Internal function to transfer an ERC721 token from a given * originator to a given recipient. Sufficient approvals must be set on * the contract performing the transfer. Note that this function does * not check whether the receiver can accept the ERC721 token (i.e. it * does not use `safeTransferFrom`). * * @param token The ERC721 token to transfer. * @param from The originator of the transfer. * @param to The recipient of the transfer. * @param identifier The tokenId to transfer. */ function _performERC721Transfer( address token, address from, address to, uint256 identifier ) internal { // Utilize assembly to perform an optimized ERC721 token transfer. assembly { // If the token has no code, revert. if iszero(extcodesize(token)) { mstore(NoContract_error_sig_ptr, NoContract_error_signature) mstore(NoContract_error_token_ptr, token) revert(NoContract_error_sig_ptr, NoContract_error_length) } // The free memory pointer memory slot will be used when populating // call data for the transfer; read the value and restore it later. let memPointer := mload(FreeMemoryPointerSlot) // Write call data to memory starting with function selector. mstore(ERC721_transferFrom_sig_ptr, ERC721_transferFrom_signature) mstore(ERC721_transferFrom_from_ptr, from) mstore(ERC721_transferFrom_to_ptr, to) mstore(ERC721_transferFrom_id_ptr, identifier) // Perform the call, ignoring return data. let success := call( gas(), token, 0, ERC721_transferFrom_sig_ptr, ERC721_transferFrom_length, 0, 0 ) // If the transfer reverted: if iszero(success) { // If it returned a message, bubble it up as long as sufficient // gas remains to do so: if returndatasize() { // Ensure that sufficient gas is available to copy // returndata while expanding memory where necessary. Start // by computing word size of returndata & allocated memory. // Round up to the nearest full word. let returnDataWords := div( add(returndatasize(), AlmostOneWord), OneWord ) // Note: use the free memory pointer in place of msize() to // work around a Yul warning that prevents accessing msize // directly when the IR pipeline is activated. let msizeWords := div(memPointer, OneWord) // Next, compute the cost of the returndatacopy. let cost := mul(CostPerWord, returnDataWords) // Then, compute cost of new memory allocation. if gt(returnDataWords, msizeWords) { cost := add( cost, add( mul( sub(returnDataWords, msizeWords), CostPerWord ), div( sub( mul(returnDataWords, returnDataWords), mul(msizeWords, msizeWords) ), MemoryExpansionCoefficient ) ) ) } // Finally, add a small constant and compare to gas // remaining; bubble up the revert data if enough gas is // still available. if lt(add(cost, ExtraGasBuffer), gas()) { // Copy returndata to memory; overwrite existing memory. returndatacopy(0, 0, returndatasize()) // Revert, giving memory region with copied returndata. revert(0, returndatasize()) } } // Otherwise revert with a generic error message. mstore( TokenTransferGenericFailure_error_sig_ptr, TokenTransferGenericFailure_error_signature ) mstore(TokenTransferGenericFailure_error_token_ptr, token) mstore(TokenTransferGenericFailure_error_from_ptr, from) mstore(TokenTransferGenericFailure_error_to_ptr, to) mstore(TokenTransferGenericFailure_error_id_ptr, identifier) mstore(TokenTransferGenericFailure_error_amount_ptr, 1) revert( TokenTransferGenericFailure_error_sig_ptr, TokenTransferGenericFailure_error_length ) } // Restore the original free memory pointer. mstore(FreeMemoryPointerSlot, memPointer) // Restore the zero slot to zero. mstore(ZeroSlot, 0) } } /** * @dev Internal function to transfer ERC1155 tokens from a given * originator to a given recipient. Sufficient approvals must be set on * the contract performing the transfer and contract recipients must * implement the ERC1155TokenReceiver interface to indicate that they * are willing to accept the transfer. * * @param token The ERC1155 token to transfer. * @param from The originator of the transfer. * @param to The recipient of the transfer. * @param identifier The id to transfer. * @param amount The amount to transfer. */ function _performERC1155Transfer( address token, address from, address to, uint256 identifier, uint256 amount ) internal { // Utilize assembly to perform an optimized ERC1155 token transfer. assembly { // If the token has no code, revert. if iszero(extcodesize(token)) { mstore(NoContract_error_sig_ptr, NoContract_error_signature) mstore(NoContract_error_token_ptr, token) revert(NoContract_error_sig_ptr, NoContract_error_length) } // The following memory slots will be used when populating call data // for the transfer; read the values and restore them later. let memPointer := mload(FreeMemoryPointerSlot) let slot0x80 := mload(Slot0x80) let slot0xA0 := mload(Slot0xA0) let slot0xC0 := mload(Slot0xC0) // Write call data into memory, beginning with function selector. mstore( ERC1155_safeTransferFrom_sig_ptr, ERC1155_safeTransferFrom_signature ) mstore(ERC1155_safeTransferFrom_from_ptr, from) mstore(ERC1155_safeTransferFrom_to_ptr, to) mstore(ERC1155_safeTransferFrom_id_ptr, identifier) mstore(ERC1155_safeTransferFrom_amount_ptr, amount) mstore( ERC1155_safeTransferFrom_data_offset_ptr, ERC1155_safeTransferFrom_data_length_offset ) mstore(ERC1155_safeTransferFrom_data_length_ptr, 0) // Perform the call, ignoring return data. let success := call( gas(), token, 0, ERC1155_safeTransferFrom_sig_ptr, ERC1155_safeTransferFrom_length, 0, 0 ) // If the transfer reverted: if iszero(success) { // If it returned a message, bubble it up as long as sufficient // gas remains to do so: if returndatasize() { // Ensure that sufficient gas is available to copy // returndata while expanding memory where necessary. Start // by computing word size of returndata & allocated memory. // Round up to the nearest full word. let returnDataWords := div( add(returndatasize(), AlmostOneWord), OneWord ) // Note: use the free memory pointer in place of msize() to // work around a Yul warning that prevents accessing msize // directly when the IR pipeline is activated. let msizeWords := div(memPointer, OneWord) // Next, compute the cost of the returndatacopy. let cost := mul(CostPerWord, returnDataWords) // Then, compute cost of new memory allocation. if gt(returnDataWords, msizeWords) { cost := add( cost, add( mul( sub(returnDataWords, msizeWords), CostPerWord ), div( sub( mul(returnDataWords, returnDataWords), mul(msizeWords, msizeWords) ), MemoryExpansionCoefficient ) ) ) } // Finally, add a small constant and compare to gas // remaining; bubble up the revert data if enough gas is // still available. if lt(add(cost, ExtraGasBuffer), gas()) { // Copy returndata to memory; overwrite existing memory. returndatacopy(0, 0, returndatasize()) // Revert, giving memory region with copied returndata. revert(0, returndatasize()) } } // Otherwise revert with a generic error message. mstore( TokenTransferGenericFailure_error_sig_ptr, TokenTransferGenericFailure_error_signature ) mstore(TokenTransferGenericFailure_error_token_ptr, token) mstore(TokenTransferGenericFailure_error_from_ptr, from) mstore(TokenTransferGenericFailure_error_to_ptr, to) mstore(TokenTransferGenericFailure_error_id_ptr, identifier) mstore(TokenTransferGenericFailure_error_amount_ptr, amount) revert( TokenTransferGenericFailure_error_sig_ptr, TokenTransferGenericFailure_error_length ) } mstore(Slot0x80, slot0x80) // Restore slot 0x80. mstore(Slot0xA0, slot0xA0) // Restore slot 0xA0. mstore(Slot0xC0, slot0xC0) // Restore slot 0xC0. // Restore the original free memory pointer. mstore(FreeMemoryPointerSlot, memPointer) // Restore the zero slot to zero. mstore(ZeroSlot, 0) } } /** * @dev Internal function to transfer ERC1155 tokens from a given * originator to a given recipient. Sufficient approvals must be set on * the contract performing the transfer and contract recipients must * implement the ERC1155TokenReceiver interface to indicate that they * are willing to accept the transfer. NOTE: this function is not * memory-safe; it will overwrite existing memory, restore the free * memory pointer to the default value, and overwrite the zero slot. * This function should only be called once memory is no longer * required and when uninitialized arrays are not utilized, and memory * should be considered fully corrupted (aside from the existence of a * default-value free memory pointer) after calling this function. * * @param batchTransfers The group of 1155 batch transfers to perform. */ function _performERC1155BatchTransfers( ConduitBatch1155Transfer[] calldata batchTransfers ) internal { // Utilize assembly to perform optimized batch 1155 transfers. assembly { let len := batchTransfers.length // Pointer to first head in the array, which is offset to the struct // at each index. This gets incremented after each loop to avoid // multiplying by 32 to get the offset for each element. let nextElementHeadPtr := batchTransfers.offset // Pointer to beginning of the head of the array. This is the // reference position each offset references. It's held static to // let each loop calculate the data position for an element. let arrayHeadPtr := nextElementHeadPtr // Write the function selector, which will be reused for each call: // safeBatchTransferFrom(address,address,uint256[],uint256[],bytes) mstore( ConduitBatch1155Transfer_from_offset, ERC1155_safeBatchTransferFrom_signature ) // Iterate over each batch transfer. for { let i := 0 } lt(i, len) { i := add(i, 1) } { // Read the offset to the beginning of the element and add // it to pointer to the beginning of the array head to get // the absolute position of the element in calldata. let elementPtr := add( arrayHeadPtr, calldataload(nextElementHeadPtr) ) // Retrieve the token from calldata. let token := calldataload(elementPtr) // If the token has no code, revert. if iszero(extcodesize(token)) { mstore(NoContract_error_sig_ptr, NoContract_error_signature) mstore(NoContract_error_token_ptr, token) revert(NoContract_error_sig_ptr, NoContract_error_length) } // Get the total number of supplied ids. let idsLength := calldataload( add(elementPtr, ConduitBatch1155Transfer_ids_length_offset) ) // Determine the expected offset for the amounts array. let expectedAmountsOffset := add( ConduitBatch1155Transfer_amounts_length_baseOffset, mul(idsLength, OneWord) ) // Validate struct encoding. let invalidEncoding := iszero( and( // ids.length == amounts.length eq( idsLength, calldataload(add(elementPtr, expectedAmountsOffset)) ), and( // ids_offset == 0xa0 eq( calldataload( add( elementPtr, ConduitBatch1155Transfer_ids_head_offset ) ), ConduitBatch1155Transfer_ids_length_offset ), // amounts_offset == 0xc0 + ids.length*32 eq( calldataload( add( elementPtr, ConduitBatchTransfer_amounts_head_offset ) ), expectedAmountsOffset ) ) ) ) // Revert with an error if the encoding is not valid. if invalidEncoding { mstore( Invalid1155BatchTransferEncoding_ptr, Invalid1155BatchTransferEncoding_selector ) revert( Invalid1155BatchTransferEncoding_ptr, Invalid1155BatchTransferEncoding_length ) } // Update the offset position for the next loop nextElementHeadPtr := add(nextElementHeadPtr, OneWord) // Copy the first section of calldata (before dynamic values). calldatacopy( BatchTransfer1155Params_ptr, add(elementPtr, ConduitBatch1155Transfer_from_offset), ConduitBatch1155Transfer_usable_head_size ) // Determine size of calldata required for ids and amounts. Note // that the size includes both lengths as well as the data. let idsAndAmountsSize := add(TwoWords, mul(idsLength, TwoWords)) // Update the offset for the data array in memory. mstore( BatchTransfer1155Params_data_head_ptr, add( BatchTransfer1155Params_ids_length_offset, idsAndAmountsSize ) ) // Set the length of the data array in memory to zero. mstore( add( BatchTransfer1155Params_data_length_basePtr, idsAndAmountsSize ), 0 ) // Determine the total calldata size for the call to transfer. let transferDataSize := add( BatchTransfer1155Params_calldata_baseSize, idsAndAmountsSize ) // Copy second section of calldata (including dynamic values). calldatacopy( BatchTransfer1155Params_ids_length_ptr, add(elementPtr, ConduitBatch1155Transfer_ids_length_offset), idsAndAmountsSize ) // Perform the call to transfer 1155 tokens. let success := call( gas(), token, 0, ConduitBatch1155Transfer_from_offset, // Data portion start. transferDataSize, // Location of the length of callData. 0, 0 ) // If the transfer reverted: if iszero(success) { // If it returned a message, bubble it up as long as // sufficient gas remains to do so: if returndatasize() { // Ensure that sufficient gas is available to copy // returndata while expanding memory where necessary. // Start by computing word size of returndata and // allocated memory. Round up to the nearest full word. let returnDataWords := div( add(returndatasize(), AlmostOneWord), OneWord ) // Note: use transferDataSize in place of msize() to // work around a Yul warning that prevents accessing // msize directly when the IR pipeline is activated. // The free memory pointer is not used here because // this function does almost all memory management // manually and does not update it, and transferDataSize // should be the largest memory value used (unless a // previous batch was larger). let msizeWords := div(transferDataSize, OneWord) // Next, compute the cost of the returndatacopy. let cost := mul(CostPerWord, returnDataWords) // Then, compute cost of new memory allocation. if gt(returnDataWords, msizeWords) { cost := add( cost, add( mul( sub(returnDataWords, msizeWords), CostPerWord ), div( sub( mul( returnDataWords, returnDataWords ), mul(msizeWords, msizeWords) ), MemoryExpansionCoefficient ) ) ) } // Finally, add a small constant and compare to gas // remaining; bubble up the revert data if enough gas is // still available. if lt(add(cost, ExtraGasBuffer), gas()) { // Copy returndata to memory; overwrite existing. returndatacopy(0, 0, returndatasize()) // Revert with memory region containing returndata. revert(0, returndatasize()) } } // Set the error signature. mstore( 0, ERC1155BatchTransferGenericFailure_error_signature ) // Write the token. mstore(ERC1155BatchTransferGenericFailure_token_ptr, token) // Increase the offset to ids by 32. mstore( BatchTransfer1155Params_ids_head_ptr, ERC1155BatchTransferGenericFailure_ids_offset ) // Increase the offset to amounts by 32. mstore( BatchTransfer1155Params_amounts_head_ptr, add( OneWord, mload(BatchTransfer1155Params_amounts_head_ptr) ) ) // Return modified region. The total size stays the same as // `token` uses the same number of bytes as `data.length`. revert(0, transferDataSize) } } // Reset the free memory pointer to the default value; memory must // be assumed to be dirtied and not reused from this point forward. // Also note that the zero slot is not reset to zero, meaning empty // arrays cannot be safely created or utilized until it is restored. mstore(FreeMemoryPointerSlot, DefaultFreeMemoryPointer) } } }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.13; import { OrderStatus } from "./ConsiderationStructs.sol"; import { Assertions } from "./Assertions.sol"; import { SignatureVerification } from "./SignatureVerification.sol"; /** * @title Verifiers * @author 0age * @notice Verifiers contains functions for performing verifications. */ contract Verifiers is Assertions, SignatureVerification { /** * @dev Derive and set hashes, reference chainId, and associated domain * separator during deployment. * * @param conduitController A contract that deploys conduits, or proxies * that may optionally be used to transfer approved * ERC20/721/1155 tokens. */ constructor(address conduitController) Assertions(conduitController) {} /** * @dev Internal view function to ensure that the current time falls within * an order's valid timespan. * * @param startTime The time at which the order becomes active. * @param endTime The time at which the order becomes inactive. * @param revertOnInvalid A boolean indicating whether to revert if the * order is not active. * * @return valid A boolean indicating whether the order is active. */ function _verifyTime( uint256 startTime, uint256 endTime, bool revertOnInvalid ) internal view returns (bool valid) { // Revert if order's timespan hasn't started yet or has already ended. if (startTime > block.timestamp || endTime <= block.timestamp) { // Only revert if revertOnInvalid has been supplied as true. if (revertOnInvalid) { revert InvalidTime(); } // Return false as the order is invalid. return false; } // Return true as the order time is valid. valid = true; } /** * @dev Internal view function to verify the signature of an order. An * ERC-1271 fallback will be attempted if either the signature length * is not 32 or 33 bytes or if the recovered signer does not match the * supplied offerer. Note that in cases where a 32 or 33 byte signature * is supplied, only standard ECDSA signatures that recover to a * non-zero address are supported. * * @param offerer The offerer for the order. * @param orderHash The order hash. * @param signature A signature from the offerer indicating that the order * has been approved. */ function _verifySignature( address offerer, bytes32 orderHash, bytes memory signature ) internal view { // Skip signature verification if the offerer is the caller. if (offerer == msg.sender) { return; } // Derive EIP-712 digest using the domain separator and the order hash. bytes32 digest = _deriveEIP712Digest(_domainSeparator(), orderHash); // Ensure that the signature for the digest is valid for the offerer. _assertValidSignature(offerer, digest, signature); } /** * @dev Internal view function to validate that a given order is fillable * and not cancelled based on the order status. * * @param orderHash The order hash. * @param orderStatus The status of the order, including whether it has * been cancelled and the fraction filled. * @param onlyAllowUnused A boolean flag indicating whether partial fills * are supported by the calling function. * @param revertOnInvalid A boolean indicating whether to revert if the * order has been cancelled or filled beyond the * allowable amount. * * @return valid A boolean indicating whether the order is valid. */ function _verifyOrderStatus( bytes32 orderHash, OrderStatus storage orderStatus, bool onlyAllowUnused, bool revertOnInvalid ) internal view returns (bool valid) { // Ensure that the order has not been cancelled. if (orderStatus.isCancelled) { // Only revert if revertOnInvalid has been supplied as true. if (revertOnInvalid) { revert OrderIsCancelled(orderHash); } // Return false as the order status is invalid. return false; } // Read order status numerator from storage and place on stack. uint256 orderStatusNumerator = orderStatus.numerator; // If the order is not entirely unused... if (orderStatusNumerator != 0) { // ensure the order has not been partially filled when not allowed. if (onlyAllowUnused) { // Always revert on partial fills when onlyAllowUnused is true. revert OrderPartiallyFilled(orderHash); } // Otherwise, ensure that order has not been entirely filled. else if (orderStatusNumerator >= orderStatus.denominator) { // Only revert if revertOnInvalid has been supplied as true. if (revertOnInvalid) { revert OrderAlreadyFilled(orderHash); } // Return false as the order status is invalid. return false; } } // Return true as the order status is valid. valid = true; } }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.7; enum ConduitItemType { NATIVE, // unused ERC20, ERC721, ERC1155 }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.13; import { EIP1271Interface } from "./EIP1271Interface.sol"; // prettier-ignore import { SignatureVerificationErrors } from "./SignatureVerificationErrors.sol"; import { LowLevelHelpers } from "./LowLevelHelpers.sol"; import "./ConsiderationConstants.sol"; /** * @title SignatureVerification * @author 0age * @notice SignatureVerification contains logic for verifying signatures. */ contract SignatureVerification is SignatureVerificationErrors, LowLevelHelpers { /** * @dev Internal view function to verify the signature of an order. An * ERC-1271 fallback will be attempted if either the signature length * is not 64 or 65 bytes or if the recovered signer does not match the * supplied signer. * * @param signer The signer for the order. * @param digest The digest to verify the signature against. * @param signature A signature from the signer indicating that the order * has been approved. */ function _assertValidSignature( address signer, bytes32 digest, bytes memory signature ) internal view { // Declare value for ecrecover equality or 1271 call success status. bool success; // Utilize assembly to perform optimized signature verification check. assembly { // Ensure that first word of scratch space is empty. mstore(0, 0) // Declare value for v signature parameter. let v // Get the length of the signature. let signatureLength := mload(signature) // Get the pointer to the value preceding the signature length. // This will be used for temporary memory overrides - either the // signature head for isValidSignature or the digest for ecrecover. let wordBeforeSignaturePtr := sub(signature, OneWord) // Cache the current value behind the signature to restore it later. let cachedWordBeforeSignature := mload(wordBeforeSignaturePtr) // Declare lenDiff + recoveredSigner scope to manage stack pressure. { // Take the difference between the max ECDSA signature length // and the actual signature length. Overflow desired for any // values > 65. If the diff is not 0 or 1, it is not a valid // ECDSA signature - move on to EIP1271 check. let lenDiff := sub(ECDSA_MaxLength, signatureLength) // Declare variable for recovered signer. let recoveredSigner // If diff is 0 or 1, it may be an ECDSA signature. // Try to recover signer. if iszero(gt(lenDiff, 1)) { // Read the signature `s` value. let originalSignatureS := mload( add(signature, ECDSA_signature_s_offset) ) // Read the first byte of the word after `s`. If the // signature is 65 bytes, this will be the real `v` value. // If not, it will need to be modified - doing it this way // saves an extra condition. v := byte( 0, mload(add(signature, ECDSA_signature_v_offset)) ) // If lenDiff is 1, parse 64-byte signature as ECDSA. if lenDiff { // Extract yParity from highest bit of vs and add 27 to // get v. v := add( shr(MaxUint8, originalSignatureS), Signature_lower_v ) // Extract canonical s from vs, all but the highest bit. // Temporarily overwrite the original `s` value in the // signature. mstore( add(signature, ECDSA_signature_s_offset), and( originalSignatureS, EIP2098_allButHighestBitMask ) ) } // Temporarily overwrite the signature length with `v` to // conform to the expected input for ecrecover. mstore(signature, v) // Temporarily overwrite the word before the length with // `digest` to conform to the expected input for ecrecover. mstore(wordBeforeSignaturePtr, digest) // Attempt to recover the signer for the given signature. Do // not check the call status as ecrecover will return a null // address if the signature is invalid. pop( staticcall( gas(), Ecrecover_precompile, // Call ecrecover precompile. wordBeforeSignaturePtr, // Use data memory location. Ecrecover_args_size, // Size of digest, v, r, and s. 0, // Write result to scratch space. OneWord // Provide size of returned result. ) ) // Restore cached word before signature. mstore(wordBeforeSignaturePtr, cachedWordBeforeSignature) // Restore cached signature length. mstore(signature, signatureLength) // Restore cached signature `s` value. mstore( add(signature, ECDSA_signature_s_offset), originalSignatureS ) // Read the recovered signer from the buffer given as return // space for ecrecover. recoveredSigner := mload(0) } // Set success to true if the signature provided was a valid // ECDSA signature and the signer is not the null address. Use // gt instead of direct as success is used outside of assembly. success := and(eq(signer, recoveredSigner), gt(signer, 0)) } // If the signature was not verified with ecrecover, try EIP1271. if iszero(success) { // Temporarily overwrite the word before the signature length // and use it as the head of the signature input to // `isValidSignature`, which has a value of 64. mstore( wordBeforeSignaturePtr, EIP1271_isValidSignature_signature_head_offset ) // Get pointer to use for the selector of `isValidSignature`. let selectorPtr := sub( signature, EIP1271_isValidSignature_selector_negativeOffset ) // Cache the value currently stored at the selector pointer. let cachedWordOverwrittenBySelector := mload(selectorPtr) // Get pointer to use for `digest` input to `isValidSignature`. let digestPtr := sub( signature, EIP1271_isValidSignature_digest_negativeOffset ) // Cache the value currently stored at the digest pointer. let cachedWordOverwrittenByDigest := mload(digestPtr) // Write the selector first, since it overlaps the digest. mstore(selectorPtr, EIP1271_isValidSignature_selector) // Next, write the digest. mstore(digestPtr, digest) // Call signer with `isValidSignature` to validate signature. success := staticcall( gas(), signer, selectorPtr, add( signatureLength, EIP1271_isValidSignature_calldata_baseLength ), 0, OneWord ) // Determine if the signature is valid on successful calls. if success { // If first word of scratch space does not contain EIP-1271 // signature selector, revert. if iszero(eq(mload(0), EIP1271_isValidSignature_selector)) { // Revert with bad 1271 signature if signer has code. if extcodesize(signer) { // Bad contract signature. mstore(0, BadContractSignature_error_signature) revert(0, BadContractSignature_error_length) } // Check if signature length was invalid. if gt(sub(ECDSA_MaxLength, signatureLength), 1) { // Revert with generic invalid signature error. mstore(0, InvalidSignature_error_signature) revert(0, InvalidSignature_error_length) } // Check if v was invalid. if iszero( byte(v, ECDSA_twentySeventhAndTwentyEighthBytesSet) ) { // Revert with invalid v value. mstore(0, BadSignatureV_error_signature) mstore(BadSignatureV_error_offset, v) revert(0, BadSignatureV_error_length) } // Revert with generic invalid signer error message. mstore(0, InvalidSigner_error_signature) revert(0, InvalidSigner_error_length) } } // Restore the cached values overwritten by selector, digest and // signature head. mstore(wordBeforeSignaturePtr, cachedWordBeforeSignature) mstore(selectorPtr, cachedWordOverwrittenBySelector) mstore(digestPtr, cachedWordOverwrittenByDigest) } } // If the call failed... if (!success) { // Revert and pass reason along if one was returned. _revertWithReasonIfOneIsReturned(); // Otherwise, revert with error indicating bad contract signature. assembly { mstore(0, BadContractSignature_error_signature) revert(0, BadContractSignature_error_length) } } } }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.13; import { OrderParameters } from "./ConsiderationStructs.sol"; import { GettersAndDerivers } from "./GettersAndDerivers.sol"; // prettier-ignore import { TokenTransferrerErrors } from "./TokenTransferrerErrors.sol"; import { CounterManager } from "./CounterManager.sol"; import "./ConsiderationConstants.sol"; /** * @title Assertions * @author 0age * @notice Assertions contains logic for making various assertions that do not * fit neatly within a dedicated semantic scope. */ contract Assertions is GettersAndDerivers, CounterManager, TokenTransferrerErrors { /** * @dev Derive and set hashes, reference chainId, and associated domain * separator during deployment. * * @param conduitController A contract that deploys conduits, or proxies * that may optionally be used to transfer approved * ERC20/721/1155 tokens. */ constructor(address conduitController) GettersAndDerivers(conduitController) {} /** * @dev Internal view function to ensure that the supplied consideration * array length on a given set of order parameters is not less than the * original consideration array length for that order and to retrieve * the current counter for a given order's offerer and zone and use it * to derive the order hash. * * @param orderParameters The parameters of the order to hash. * * @return The hash. */ function _assertConsiderationLengthAndGetOrderHash( OrderParameters memory orderParameters ) internal view returns (bytes32) { // Ensure supplied consideration array length is not less than original. _assertConsiderationLengthIsNotLessThanOriginalConsiderationLength( orderParameters.consideration.length, orderParameters.totalOriginalConsiderationItems ); // Derive and return order hash using current counter for the offerer. return _deriveOrderHash( orderParameters, _getCounter(orderParameters.offerer) ); } /** * @dev Internal pure function to ensure that the supplied consideration * array length for an order to be fulfilled is not less than the * original consideration array length for that order. * * @param suppliedConsiderationItemTotal The number of consideration items * supplied when fulfilling the order. * @param originalConsiderationItemTotal The number of consideration items * supplied on initial order creation. */ function _assertConsiderationLengthIsNotLessThanOriginalConsiderationLength( uint256 suppliedConsiderationItemTotal, uint256 originalConsiderationItemTotal ) internal pure { // Ensure supplied consideration array length is not less than original. if (suppliedConsiderationItemTotal < originalConsiderationItemTotal) { revert MissingOriginalConsiderationItems(); } } /** * @dev Internal pure function to ensure that a given item amount is not * zero. * * @param amount The amount to check. */ function _assertNonZeroAmount(uint256 amount) internal pure { // Revert if the supplied amount is equal to zero. if (amount == 0) { revert MissingItemAmount(); } } /** * @dev Internal pure function to validate calldata offsets for dynamic * types in BasicOrderParameters and other parameters. This ensures * that functions using the calldata object normally will be using the * same data as the assembly functions and that values that are bound * to a given range are within that range. Note that no parameters are * supplied as all basic order functions use the same calldata * encoding. */ function _assertValidBasicOrderParameters() internal pure { // Declare a boolean designating basic order parameter offset validity. bool validOffsets; // Utilize assembly in order to read offset data directly from calldata. assembly { /* * Checks: * 1. Order parameters struct offset == 0x20 * 2. Additional recipients arr offset == 0x240 * 3. Signature offset == 0x260 + (recipients.length * 0x40) * 4. BasicOrderType between 0 and 23 (i.e. < 24) */ validOffsets := and( // Order parameters at calldata 0x04 must have offset of 0x20. eq( calldataload(BasicOrder_parameters_cdPtr), BasicOrder_parameters_ptr ), // Additional recipients at cd 0x224 must have offset of 0x240. eq( calldataload(BasicOrder_additionalRecipients_head_cdPtr), BasicOrder_additionalRecipients_head_ptr ) ) validOffsets := and( validOffsets, eq( // Load signature offset from calldata 0x244. calldataload(BasicOrder_signature_cdPtr), // Derive expected offset as start of recipients + len * 64. add( BasicOrder_signature_ptr, mul( // Additional recipients length at calldata 0x264. calldataload( BasicOrder_additionalRecipients_length_cdPtr ), // Each additional recipient has a length of 0x40. AdditionalRecipients_size ) ) ) ) validOffsets := and( validOffsets, lt( // BasicOrderType parameter at calldata offset 0x124. calldataload(BasicOrder_basicOrderType_cdPtr), // Value should be less than 24. BasicOrder_basicOrderType_range ) ) } // Revert with an error if basic order parameter offsets are invalid. if (!validOffsets) { revert InvalidBasicOrderParameterEncoding(); } } }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.7; /** * @title TokenTransferrerErrors */ interface TokenTransferrerErrors { /** * @dev Revert with an error when an ERC721 transfer with amount other than * one is attempted. */ error InvalidERC721TransferAmount(); /** * @dev Revert with an error when attempting to fulfill an order where an * item has an amount of zero. */ error MissingItemAmount(); /** * @dev Revert with an error when attempting to fulfill an order where an * item has unused parameters. This includes both the token and the * identifier parameters for native transfers as well as the identifier * parameter for ERC20 transfers. Note that the conduit does not * perform this check, leaving it up to the calling channel to enforce * when desired. */ error UnusedItemParameters(); /** * @dev Revert with an error when an ERC20, ERC721, or ERC1155 token * transfer reverts. * * @param token The token for which the transfer was attempted. * @param from The source of the attempted transfer. * @param to The recipient of the attempted transfer. * @param identifier The identifier for the attempted transfer. * @param amount The amount for the attempted transfer. */ error TokenTransferGenericFailure( address token, address from, address to, uint256 identifier, uint256 amount ); /** * @dev Revert with an error when a batch ERC1155 token transfer reverts. * * @param token The token for which the transfer was attempted. * @param from The source of the attempted transfer. * @param to The recipient of the attempted transfer. * @param identifiers The identifiers for the attempted transfer. * @param amounts The amounts for the attempted transfer. */ error ERC1155BatchTransferGenericFailure( address token, address from, address to, uint256[] identifiers, uint256[] amounts ); /** * @dev Revert with an error when an ERC20 token transfer returns a falsey * value. * * @param token The token for which the ERC20 transfer was attempted. * @param from The source of the attempted ERC20 transfer. * @param to The recipient of the attempted ERC20 transfer. * @param amount The amount for the attempted ERC20 transfer. */ error BadReturnValueFromERC20OnTransfer( address token, address from, address to, uint256 amount ); /** * @dev Revert with an error when an account being called as an assumed * contract does not have code and returns no data. * * @param account The account that should contain code. */ error NoContract(address account); /** * @dev Revert with an error when attempting to execute an 1155 batch * transfer using calldata not produced by default ABI encoding or with * different lengths for ids and amounts arrays. */ error Invalid1155BatchTransferEncoding(); }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.7; /* * -------------------------- Disambiguation & Other Notes --------------------- * - The term "head" is used as it is in the documentation for ABI encoding, * but only in reference to dynamic types, i.e. it always refers to the * offset or pointer to the body of a dynamic type. In calldata, the head * is always an offset (relative to the parent object), while in memory, * the head is always the pointer to the body. More information found here: * https://docs.soliditylang.org/en/v0.8.14/abi-spec.html#argument-encoding * - Note that the length of an array is separate from and precedes the * head of the array. * * - The term "body" is used in place of the term "head" used in the ABI * documentation. It refers to the start of the data for a dynamic type, * e.g. the first word of a struct or the first word of the first element * in an array. * * - The term "pointer" is used to describe the absolute position of a value * and never an offset relative to another value. * - The suffix "_ptr" refers to a memory pointer. * - The suffix "_cdPtr" refers to a calldata pointer. * * - The term "offset" is used to describe the position of a value relative * to some parent value. For example, OrderParameters_conduit_offset is the * offset to the "conduit" value in the OrderParameters struct relative to * the start of the body. * - Note: Offsets are used to derive pointers. * * - Some structs have pointers defined for all of their fields in this file. * Lines which are commented out are fields that are not used in the * codebase but have been left in for readability. */ uint256 constant AlmostOneWord = 0x1f; uint256 constant OneWord = 0x20; uint256 constant TwoWords = 0x40; uint256 constant ThreeWords = 0x60; uint256 constant FreeMemoryPointerSlot = 0x40; uint256 constant ZeroSlot = 0x60; uint256 constant DefaultFreeMemoryPointer = 0x80; uint256 constant Slot0x80 = 0x80; uint256 constant Slot0xA0 = 0xa0; uint256 constant Slot0xC0 = 0xc0; // abi.encodeWithSignature("transferFrom(address,address,uint256)") uint256 constant ERC20_transferFrom_signature = ( 0x23b872dd00000000000000000000000000000000000000000000000000000000 ); uint256 constant ERC20_transferFrom_sig_ptr = 0x0; uint256 constant ERC20_transferFrom_from_ptr = 0x04; uint256 constant ERC20_transferFrom_to_ptr = 0x24; uint256 constant ERC20_transferFrom_amount_ptr = 0x44; uint256 constant ERC20_transferFrom_length = 0x64; // 4 + 32 * 3 == 100 // abi.encodeWithSignature( // "safeTransferFrom(address,address,uint256,uint256,bytes)" // ) uint256 constant ERC1155_safeTransferFrom_signature = ( 0xf242432a00000000000000000000000000000000000000000000000000000000 ); uint256 constant ERC1155_safeTransferFrom_sig_ptr = 0x0; uint256 constant ERC1155_safeTransferFrom_from_ptr = 0x04; uint256 constant ERC1155_safeTransferFrom_to_ptr = 0x24; uint256 constant ERC1155_safeTransferFrom_id_ptr = 0x44; uint256 constant ERC1155_safeTransferFrom_amount_ptr = 0x64; uint256 constant ERC1155_safeTransferFrom_data_offset_ptr = 0x84; uint256 constant ERC1155_safeTransferFrom_data_length_ptr = 0xa4; uint256 constant ERC1155_safeTransferFrom_length = 0xc4; // 4 + 32 * 6 == 196 uint256 constant ERC1155_safeTransferFrom_data_length_offset = 0xa0; // abi.encodeWithSignature( // "safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)" // ) uint256 constant ERC1155_safeBatchTransferFrom_signature = ( 0x2eb2c2d600000000000000000000000000000000000000000000000000000000 ); bytes4 constant ERC1155_safeBatchTransferFrom_selector = bytes4( bytes32(ERC1155_safeBatchTransferFrom_signature) ); uint256 constant ERC721_transferFrom_signature = ERC20_transferFrom_signature; uint256 constant ERC721_transferFrom_sig_ptr = 0x0; uint256 constant ERC721_transferFrom_from_ptr = 0x04; uint256 constant ERC721_transferFrom_to_ptr = 0x24; uint256 constant ERC721_transferFrom_id_ptr = 0x44; uint256 constant ERC721_transferFrom_length = 0x64; // 4 + 32 * 3 == 100 // abi.encodeWithSignature("NoContract(address)") uint256 constant NoContract_error_signature = ( 0x5f15d67200000000000000000000000000000000000000000000000000000000 ); uint256 constant NoContract_error_sig_ptr = 0x0; uint256 constant NoContract_error_token_ptr = 0x4; uint256 constant NoContract_error_length = 0x24; // 4 + 32 == 36 // abi.encodeWithSignature( // "TokenTransferGenericFailure(address,address,address,uint256,uint256)" // ) uint256 constant TokenTransferGenericFailure_error_signature = ( 0xf486bc8700000000000000000000000000000000000000000000000000000000 ); uint256 constant TokenTransferGenericFailure_error_sig_ptr = 0x0; uint256 constant TokenTransferGenericFailure_error_token_ptr = 0x4; uint256 constant TokenTransferGenericFailure_error_from_ptr = 0x24; uint256 constant TokenTransferGenericFailure_error_to_ptr = 0x44; uint256 constant TokenTransferGenericFailure_error_id_ptr = 0x64; uint256 constant TokenTransferGenericFailure_error_amount_ptr = 0x84; // 4 + 32 * 5 == 164 uint256 constant TokenTransferGenericFailure_error_length = 0xa4; // abi.encodeWithSignature( // "BadReturnValueFromERC20OnTransfer(address,address,address,uint256)" // ) uint256 constant BadReturnValueFromERC20OnTransfer_error_signature = ( 0x9889192300000000000000000000000000000000000000000000000000000000 ); uint256 constant BadReturnValueFromERC20OnTransfer_error_sig_ptr = 0x0; uint256 constant BadReturnValueFromERC20OnTransfer_error_token_ptr = 0x4; uint256 constant BadReturnValueFromERC20OnTransfer_error_from_ptr = 0x24; uint256 constant BadReturnValueFromERC20OnTransfer_error_to_ptr = 0x44; uint256 constant BadReturnValueFromERC20OnTransfer_error_amount_ptr = 0x64; // 4 + 32 * 4 == 132 uint256 constant BadReturnValueFromERC20OnTransfer_error_length = 0x84; uint256 constant ExtraGasBuffer = 0x20; uint256 constant CostPerWord = 3; uint256 constant MemoryExpansionCoefficient = 0x200; // Values are offset by 32 bytes in order to write the token to the beginning // in the event of a revert uint256 constant BatchTransfer1155Params_ptr = 0x24; uint256 constant BatchTransfer1155Params_ids_head_ptr = 0x64; uint256 constant BatchTransfer1155Params_amounts_head_ptr = 0x84; uint256 constant BatchTransfer1155Params_data_head_ptr = 0xa4; uint256 constant BatchTransfer1155Params_data_length_basePtr = 0xc4; uint256 constant BatchTransfer1155Params_calldata_baseSize = 0xc4; uint256 constant BatchTransfer1155Params_ids_length_ptr = 0xc4; uint256 constant BatchTransfer1155Params_ids_length_offset = 0xa0; uint256 constant BatchTransfer1155Params_amounts_length_baseOffset = 0xc0; uint256 constant BatchTransfer1155Params_data_length_baseOffset = 0xe0; uint256 constant ConduitBatch1155Transfer_usable_head_size = 0x80; uint256 constant ConduitBatch1155Transfer_from_offset = 0x20; uint256 constant ConduitBatch1155Transfer_ids_head_offset = 0x60; uint256 constant ConduitBatch1155Transfer_amounts_head_offset = 0x80; uint256 constant ConduitBatch1155Transfer_ids_length_offset = 0xa0; uint256 constant ConduitBatch1155Transfer_amounts_length_baseOffset = 0xc0; uint256 constant ConduitBatch1155Transfer_calldata_baseSize = 0xc0; // Note: abbreviated version of above constant to adhere to line length limit. uint256 constant ConduitBatchTransfer_amounts_head_offset = 0x80; uint256 constant Invalid1155BatchTransferEncoding_ptr = 0x00; uint256 constant Invalid1155BatchTransferEncoding_length = 0x04; uint256 constant Invalid1155BatchTransferEncoding_selector = ( 0xeba2084c00000000000000000000000000000000000000000000000000000000 ); uint256 constant ERC1155BatchTransferGenericFailure_error_signature = ( 0xafc445e200000000000000000000000000000000000000000000000000000000 ); uint256 constant ERC1155BatchTransferGenericFailure_token_ptr = 0x04; uint256 constant ERC1155BatchTransferGenericFailure_ids_offset = 0xc0;
// SPDX-License-Identifier: MIT pragma solidity >=0.8.7; /** * @title SignatureVerificationErrors * @author 0age * @notice SignatureVerificationErrors contains all errors related to signature * verification. */ interface SignatureVerificationErrors { /** * @dev Revert with an error when a signature that does not contain a v * value of 27 or 28 has been supplied. * * @param v The invalid v value. */ error BadSignatureV(uint8 v); /** * @dev Revert with an error when the signer recovered by the supplied * signature does not match the offerer or an allowed EIP-1271 signer * as specified by the offerer in the event they are a contract. */ error InvalidSigner(); /** * @dev Revert with an error when a signer cannot be recovered from the * supplied signature. */ error InvalidSignature(); /** * @dev Revert with an error when an EIP-1271 call to an account fails. */ error BadContractSignature(); }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.7; interface EIP1271Interface { function isValidSignature(bytes32 digest, bytes calldata signature) external view returns (bytes4); }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.13; // prettier-ignore import { ConsiderationEventsAndErrors } from "./ConsiderationEventsAndErrors.sol"; import { ReentrancyGuard } from "./ReentrancyGuard.sol"; /** * @title CounterManager * @author 0age * @notice CounterManager contains a storage mapping and related functionality * for retrieving and incrementing a per-offerer counter. */ contract CounterManager is ConsiderationEventsAndErrors, ReentrancyGuard { // Only orders signed using an offerer's current counter are fulfillable. mapping(address => uint256) private _counters; /** * @dev Internal function to cancel all orders from a given offerer with a * given zone in bulk by incrementing a counter. Note that only the * offerer may increment the counter. * * @return newCounter The new counter. */ function _incrementCounter() internal returns (uint256 newCounter) { // Ensure that the reentrancy guard is not currently set. _assertNonReentrant(); // Skip overflow check as counter cannot be incremented that far. unchecked { // Increment current counter for the supplied offerer. newCounter = ++_counters[msg.sender]; } // Emit an event containing the new counter. emit CounterIncremented(newCounter, msg.sender); } /** * @dev Internal view function to retrieve the current counter for a given * offerer. * * @param offerer The offerer in question. * * @return currentCounter The current counter. */ function _getCounter(address offerer) internal view returns (uint256 currentCounter) { // Return the counter for the supplied offerer. currentCounter = _counters[offerer]; } }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.13; import { OrderParameters } from "./ConsiderationStructs.sol"; import { ConsiderationBase } from "./ConsiderationBase.sol"; import "./ConsiderationConstants.sol"; /** * @title GettersAndDerivers * @author 0age * @notice ConsiderationInternal contains pure and internal view functions * related to getting or deriving various values. */ contract GettersAndDerivers is ConsiderationBase { /** * @dev Derive and set hashes, reference chainId, and associated domain * separator during deployment. * * @param conduitController A contract that deploys conduits, or proxies * that may optionally be used to transfer approved * ERC20/721/1155 tokens. */ constructor(address conduitController) ConsiderationBase(conduitController) {} /** * @dev Internal view function to derive the order hash for a given order. * Note that only the original consideration items are included in the * order hash, as additional consideration items may be supplied by the * caller. * * @param orderParameters The parameters of the order to hash. * @param counter The counter of the order to hash. * * @return orderHash The hash. */ function _deriveOrderHash( OrderParameters memory orderParameters, uint256 counter ) internal view returns (bytes32 orderHash) { // Get length of original consideration array and place it on the stack. uint256 originalConsiderationLength = ( orderParameters.totalOriginalConsiderationItems ); /* * Memory layout for an array of structs (dynamic or not) is similar * to ABI encoding of dynamic types, with a head segment followed by * a data segment. The main difference is that the head of an element * is a memory pointer rather than an offset. */ // Declare a variable for the derived hash of the offer array. bytes32 offerHash; // Read offer item EIP-712 typehash from runtime code & place on stack. bytes32 typeHash = _OFFER_ITEM_TYPEHASH; // Utilize assembly so that memory regions can be reused across hashes. assembly { // Retrieve the free memory pointer and place on the stack. let hashArrPtr := mload(FreeMemoryPointerSlot) // Get the pointer to the offers array. let offerArrPtr := mload( add(orderParameters, OrderParameters_offer_head_offset) ) // Load the length. let offerLength := mload(offerArrPtr) // Set the pointer to the first offer's head. offerArrPtr := add(offerArrPtr, OneWord) // Iterate over the offer items. // prettier-ignore for { let i := 0 } lt(i, offerLength) { i := add(i, 1) } { // Read the pointer to the offer data and subtract one word // to get typeHash pointer. let ptr := sub(mload(offerArrPtr), OneWord) // Read the current value before the offer data. let value := mload(ptr) // Write the type hash to the previous word. mstore(ptr, typeHash) // Take the EIP712 hash and store it in the hash array. mstore(hashArrPtr, keccak256(ptr, EIP712_OfferItem_size)) // Restore the previous word. mstore(ptr, value) // Increment the array pointers by one word. offerArrPtr := add(offerArrPtr, OneWord) hashArrPtr := add(hashArrPtr, OneWord) } // Derive the offer hash using the hashes of each item. offerHash := keccak256( mload(FreeMemoryPointerSlot), mul(offerLength, OneWord) ) } // Declare a variable for the derived hash of the consideration array. bytes32 considerationHash; // Read consideration item typehash from runtime code & place on stack. typeHash = _CONSIDERATION_ITEM_TYPEHASH; // Utilize assembly so that memory regions can be reused across hashes. assembly { // Retrieve the free memory pointer and place on the stack. let hashArrPtr := mload(FreeMemoryPointerSlot) // Get the pointer to the consideration array. let considerationArrPtr := add( mload( add( orderParameters, OrderParameters_consideration_head_offset ) ), OneWord ) // Iterate over the consideration items (not including tips). // prettier-ignore for { let i := 0 } lt(i, originalConsiderationLength) { i := add(i, 1) } { // Read the pointer to the consideration data and subtract one // word to get typeHash pointer. let ptr := sub(mload(considerationArrPtr), OneWord) // Read the current value before the consideration data. let value := mload(ptr) // Write the type hash to the previous word. mstore(ptr, typeHash) // Take the EIP712 hash and store it in the hash array. mstore( hashArrPtr, keccak256(ptr, EIP712_ConsiderationItem_size) ) // Restore the previous word. mstore(ptr, value) // Increment the array pointers by one word. considerationArrPtr := add(considerationArrPtr, OneWord) hashArrPtr := add(hashArrPtr, OneWord) } // Derive the consideration hash using the hashes of each item. considerationHash := keccak256( mload(FreeMemoryPointerSlot), mul(originalConsiderationLength, OneWord) ) } // Read order item EIP-712 typehash from runtime code & place on stack. typeHash = _ORDER_TYPEHASH; // Utilize assembly to access derived hashes & other arguments directly. assembly { // Retrieve pointer to the region located just behind parameters. let typeHashPtr := sub(orderParameters, OneWord) // Store the value at that pointer location to restore later. let previousValue := mload(typeHashPtr) // Store the order item EIP-712 typehash at the typehash location. mstore(typeHashPtr, typeHash) // Retrieve the pointer for the offer array head. let offerHeadPtr := add( orderParameters, OrderParameters_offer_head_offset ) // Retrieve the data pointer referenced by the offer head. let offerDataPtr := mload(offerHeadPtr) // Store the offer hash at the retrieved memory location. mstore(offerHeadPtr, offerHash) // Retrieve the pointer for the consideration array head. let considerationHeadPtr := add( orderParameters, OrderParameters_consideration_head_offset ) // Retrieve the data pointer referenced by the consideration head. let considerationDataPtr := mload(considerationHeadPtr) // Store the consideration hash at the retrieved memory location. mstore(considerationHeadPtr, considerationHash) // Retrieve the pointer for the counter. let counterPtr := add( orderParameters, OrderParameters_counter_offset ) // Store the counter at the retrieved memory location. mstore(counterPtr, counter) // Derive the order hash using the full range of order parameters. orderHash := keccak256(typeHashPtr, EIP712_Order_size) // Restore the value previously held at typehash pointer location. mstore(typeHashPtr, previousValue) // Restore offer data pointer at the offer head pointer location. mstore(offerHeadPtr, offerDataPtr) // Restore consideration data pointer at the consideration head ptr. mstore(considerationHeadPtr, considerationDataPtr) // Restore consideration item length at the counter pointer. mstore(counterPtr, originalConsiderationLength) } } /** * @dev Internal view function to derive the address of a given conduit * using a corresponding conduit key. * * @param conduitKey A bytes32 value indicating what corresponding conduit, * if any, to source token approvals from. This value is * the "salt" parameter supplied by the deployer (i.e. the * conduit controller) when deploying the given conduit. * * @return conduit The address of the conduit associated with the given * conduit key. */ function _deriveConduit(bytes32 conduitKey) internal view returns (address conduit) { // Read conduit controller address from runtime and place on the stack. address conduitController = address(_CONDUIT_CONTROLLER); // Read conduit creation code hash from runtime and place on the stack. bytes32 conduitCreationCodeHash = _CONDUIT_CREATION_CODE_HASH; // Leverage scratch space to perform an efficient hash. assembly { // Retrieve the free memory pointer; it will be replaced afterwards. let freeMemoryPointer := mload(FreeMemoryPointerSlot) // Place the control character and the conduit controller in scratch // space; note that eleven bytes at the beginning are left unused. mstore(0, or(MaskOverByteTwelve, conduitController)) // Place the conduit key in the next region of scratch space. mstore(OneWord, conduitKey) // Place conduit creation code hash in free memory pointer location. mstore(TwoWords, conduitCreationCodeHash) // Derive conduit by hashing and applying a mask over last 20 bytes. conduit := and( // Hash the relevant region. keccak256( // The region starts at memory pointer 11. Create2AddressDerivation_ptr, // The region is 85 bytes long (1 + 20 + 32 + 32). Create2AddressDerivation_length ), // The address equals the last twenty bytes of the hash. MaskOverLastTwentyBytes ) // Restore the free memory pointer. mstore(FreeMemoryPointerSlot, freeMemoryPointer) } } /** * @dev Internal view function to get the EIP-712 domain separator. If the * chainId matches the chainId set on deployment, the cached domain * separator will be returned; otherwise, it will be derived from * scratch. * * @return The domain separator. */ function _domainSeparator() internal view returns (bytes32) { // prettier-ignore return block.chainid == _CHAIN_ID ? _DOMAIN_SEPARATOR : _deriveDomainSeparator(); } /** * @dev Internal view function to retrieve configuration information for * this contract. * * @return version The contract version. * @return domainSeparator The domain separator for this contract. * @return conduitController The conduit Controller set for this contract. */ function _information() internal view returns ( string memory version, bytes32 domainSeparator, address conduitController ) { // Derive the domain separator. domainSeparator = _domainSeparator(); // Declare variable as immutables cannot be accessed within assembly. conduitController = address(_CONDUIT_CONTROLLER); // Allocate a string with the intended length. version = new string(Version_length); // Set the version as data on the newly allocated string. assembly { mstore(add(version, OneWord), shl(Version_shift, Version)) } } /** * @dev Internal pure function to efficiently derive an digest to sign for * an order in accordance with EIP-712. * * @param domainSeparator The domain separator. * @param orderHash The order hash. * * @return value The hash. */ function _deriveEIP712Digest(bytes32 domainSeparator, bytes32 orderHash) internal pure returns (bytes32 value) { // Leverage scratch space to perform an efficient hash. assembly { // Place the EIP-712 prefix at the start of scratch space. mstore(0, EIP_712_PREFIX) // Place the domain separator in the next region of scratch space. mstore(EIP712_DomainSeparator_offset, domainSeparator) // Place the order hash in scratch space, spilling into the first // two bytes of the free memory pointer — this should never be set // as memory cannot be expanded to that size, and will be zeroed out // after the hash is performed. mstore(EIP712_OrderHash_offset, orderHash) // Hash the relevant region (65 bytes). value := keccak256(0, EIP712_DigestPayload_size) // Clear out the dirtied bits in the memory pointer. mstore(EIP712_OrderHash_offset, 0) } } }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.13; // prettier-ignore import { ConduitControllerInterface } from "./ConduitControllerInterface.sol"; // prettier-ignore import { ConsiderationEventsAndErrors } from "./ConsiderationEventsAndErrors.sol"; import "./ConsiderationConstants.sol"; /** * @title ConsiderationBase * @author 0age * @notice ConsiderationBase contains immutable constants and constructor logic. */ contract ConsiderationBase is ConsiderationEventsAndErrors { // Precompute hashes, original chainId, and domain separator on deployment. bytes32 internal immutable _NAME_HASH; bytes32 internal immutable _VERSION_HASH; bytes32 internal immutable _EIP_712_DOMAIN_TYPEHASH; bytes32 internal immutable _OFFER_ITEM_TYPEHASH; bytes32 internal immutable _CONSIDERATION_ITEM_TYPEHASH; bytes32 internal immutable _ORDER_TYPEHASH; uint256 internal immutable _CHAIN_ID; bytes32 internal immutable _DOMAIN_SEPARATOR; // Allow for interaction with the conduit controller. ConduitControllerInterface internal immutable _CONDUIT_CONTROLLER; // Cache the conduit creation code hash used by the conduit controller. bytes32 internal immutable _CONDUIT_CREATION_CODE_HASH; /** * @dev Derive and set hashes, reference chainId, and associated domain * separator during deployment. * * @param conduitController A contract that deploys conduits, or proxies * that may optionally be used to transfer approved * ERC20/721/1155 tokens. */ constructor(address conduitController) { // Derive name and version hashes alongside required EIP-712 typehashes. ( _NAME_HASH, _VERSION_HASH, _EIP_712_DOMAIN_TYPEHASH, _OFFER_ITEM_TYPEHASH, _CONSIDERATION_ITEM_TYPEHASH, _ORDER_TYPEHASH ) = _deriveTypehashes(); // Store the current chainId and derive the current domain separator. _CHAIN_ID = block.chainid; _DOMAIN_SEPARATOR = _deriveDomainSeparator(); // Set the supplied conduit controller. _CONDUIT_CONTROLLER = ConduitControllerInterface(conduitController); // Retrieve the conduit creation code hash from the supplied controller. (_CONDUIT_CREATION_CODE_HASH, ) = ( _CONDUIT_CONTROLLER.getConduitCodeHashes() ); } /** * @dev Internal view function to derive the EIP-712 domain separator. * * @return The derived domain separator. */ function _deriveDomainSeparator() internal view returns (bytes32) { // prettier-ignore return keccak256( abi.encode( _EIP_712_DOMAIN_TYPEHASH, _NAME_HASH, _VERSION_HASH, block.chainid, address(this) ) ); } /** * @dev Internal pure function to retrieve the default name of this * contract and return. * * @return The name of this contract. */ function _name() internal pure virtual returns (string memory) { // Return the name of the contract. assembly { // First element is the offset for the returned string. Offset the // value in memory by one word so that the free memory pointer will // be overwritten by the next write. mstore(OneWord, OneWord) // Name is right padded, so it touches the length which is left // padded. This enables writing both values at once. The free memory // pointer will be overwritten in the process. mstore(NameLengthPtr, NameWithLength) // Standard ABI encoding pads returned data to the nearest word. Use // the already empty zero slot memory region for this purpose and // return the final name string, offset by the original single word. return(OneWord, ThreeWords) } } /** * @dev Internal pure function to retrieve the default name of this contract * as a string that can be used internally. * * @return The name of this contract. */ function _nameString() internal pure virtual returns (string memory) { // Return the name of the contract. return "Consideration"; } /** * @dev Internal pure function to derive required EIP-712 typehashes and * other hashes during contract creation. * * @return nameHash The hash of the name of the contract. * @return versionHash The hash of the version string of the * contract. * @return eip712DomainTypehash The primary EIP-712 domain typehash. * @return offerItemTypehash The EIP-712 typehash for OfferItem * types. * @return considerationItemTypehash The EIP-712 typehash for * ConsiderationItem types. * @return orderTypehash The EIP-712 typehash for Order types. */ function _deriveTypehashes() internal pure returns ( bytes32 nameHash, bytes32 versionHash, bytes32 eip712DomainTypehash, bytes32 offerItemTypehash, bytes32 considerationItemTypehash, bytes32 orderTypehash ) { // Derive hash of the name of the contract. nameHash = keccak256(bytes(_nameString())); // Derive hash of the version string of the contract. versionHash = keccak256(bytes("1.1")); // Construct the OfferItem type string. // prettier-ignore bytes memory offerItemTypeString = abi.encodePacked( "OfferItem(", "uint8 itemType,", "address token,", "uint256 identifierOrCriteria,", "uint256 startAmount,", "uint256 endAmount", ")" ); // Construct the ConsiderationItem type string. // prettier-ignore bytes memory considerationItemTypeString = abi.encodePacked( "ConsiderationItem(", "uint8 itemType,", "address token,", "uint256 identifierOrCriteria,", "uint256 startAmount,", "uint256 endAmount,", "address recipient", ")" ); // Construct the OrderComponents type string, not including the above. // prettier-ignore bytes memory orderComponentsPartialTypeString = abi.encodePacked( "OrderComponents(", "address offerer,", "address zone,", "OfferItem[] offer,", "ConsiderationItem[] consideration,", "uint8 orderType,", "uint256 startTime,", "uint256 endTime,", "bytes32 zoneHash,", "uint256 salt,", "bytes32 conduitKey,", "uint256 counter", ")" ); // Construct the primary EIP-712 domain type string. // prettier-ignore eip712DomainTypehash = keccak256( abi.encodePacked( "EIP712Domain(", "string name,", "string version,", "uint256 chainId,", "address verifyingContract", ")" ) ); // Derive the OfferItem type hash using the corresponding type string. offerItemTypehash = keccak256(offerItemTypeString); // Derive ConsiderationItem type hash using corresponding type string. considerationItemTypehash = keccak256(considerationItemTypeString); // Derive OrderItem type hash via combination of relevant type strings. orderTypehash = keccak256( abi.encodePacked( orderComponentsPartialTypeString, considerationItemTypeString, offerItemTypeString ) ); } }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.13; import { ReentrancyErrors } from "./ReentrancyErrors.sol"; import "./ConsiderationConstants.sol"; /** * @title ReentrancyGuard * @author 0age * @notice ReentrancyGuard contains a storage variable and related functionality * for protecting against reentrancy. */ contract ReentrancyGuard is ReentrancyErrors { // Prevent reentrant calls on protected functions. uint256 private _reentrancyGuard; /** * @dev Initialize the reentrancy guard during deployment. */ constructor() { // Initialize the reentrancy guard in a cleared state. _reentrancyGuard = _NOT_ENTERED; } /** * @dev Internal function to ensure that the sentinel value for the * reentrancy guard is not currently set and, if not, to set the * sentinel value for the reentrancy guard. */ function _setReentrancyGuard() internal { // Ensure that the reentrancy guard is not already set. _assertNonReentrant(); // Set the reentrancy guard. _reentrancyGuard = _ENTERED; } /** * @dev Internal function to unset the reentrancy guard sentinel value. */ function _clearReentrancyGuard() internal { // Clear the reentrancy guard. _reentrancyGuard = _NOT_ENTERED; } /** * @dev Internal view function to ensure that the sentinel value for the reentrancy guard is not currently set. */ function _assertNonReentrant() internal view { // Ensure that the reentrancy guard is not currently set. if (_reentrancyGuard != _NOT_ENTERED) { revert NoReentrantCalls(); } } }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.7; import { SpentItem, ReceivedItem } from "./ConsiderationStructs.sol"; /** * @title ConsiderationEventsAndErrors * @author 0age * @notice ConsiderationEventsAndErrors contains all events and errors. */ interface ConsiderationEventsAndErrors { /** * @dev Emit an event whenever an order is successfully fulfilled. * * @param orderHash The hash of the fulfilled order. * @param offerer The offerer of the fulfilled order. * @param zone The zone of the fulfilled order. * @param recipient The recipient of each spent item on the fulfilled * order, or the null address if there is no specific * fulfiller (i.e. the order is part of a group of * orders). Defaults to the caller unless explicitly * specified otherwise by the fulfiller. * @param offer The offer items spent as part of the order. * @param consideration The consideration items received as part of the * order along with the recipients of each item. */ event OrderFulfilled( bytes32 orderHash, address indexed offerer, address indexed zone, address recipient, SpentItem[] offer, ReceivedItem[] consideration ); /** * @dev Emit an event whenever an order is successfully cancelled. * * @param orderHash The hash of the cancelled order. * @param offerer The offerer of the cancelled order. * @param zone The zone of the cancelled order. */ event OrderCancelled( bytes32 orderHash, address indexed offerer, address indexed zone ); /** * @dev Emit an event whenever an order is explicitly validated. Note that * this event will not be emitted on partial fills even though they do * validate the order as part of partial fulfillment. * * @param orderHash The hash of the validated order. * @param offerer The offerer of the validated order. * @param zone The zone of the validated order. */ event OrderValidated( bytes32 orderHash, address indexed offerer, address indexed zone ); /** * @dev Emit an event whenever a counter for a given offerer is incremented. * * @param newCounter The new counter for the offerer. * @param offerer The offerer in question. */ event CounterIncremented(uint256 newCounter, address indexed offerer); /** * @dev Revert with an error when attempting to fill an order that has * already been fully filled. * * @param orderHash The order hash on which a fill was attempted. */ error OrderAlreadyFilled(bytes32 orderHash); /** * @dev Revert with an error when attempting to fill an order outside the * specified start time and end time. */ error InvalidTime(); /** * @dev Revert with an error when attempting to fill an order referencing an * invalid conduit (i.e. one that has not been deployed). */ error InvalidConduit(bytes32 conduitKey, address conduit); /** * @dev Revert with an error when an order is supplied for fulfillment with * a consideration array that is shorter than the original array. */ error MissingOriginalConsiderationItems(); /** * @dev Revert with an error when a call to a conduit fails with revert data * that is too expensive to return. */ error InvalidCallToConduit(address conduit); /** * @dev Revert with an error if a consideration amount has not been fully * zeroed out after applying all fulfillments. * * @param orderIndex The index of the order with the consideration * item with a shortfall. * @param considerationIndex The index of the consideration item on the * order. * @param shortfallAmount The unfulfilled consideration amount. */ error ConsiderationNotMet( uint256 orderIndex, uint256 considerationIndex, uint256 shortfallAmount ); /** * @dev Revert with an error when insufficient ether is supplied as part of * msg.value when fulfilling orders. */ error InsufficientEtherSupplied(); /** * @dev Revert with an error when an ether transfer reverts. */ error EtherTransferGenericFailure(address account, uint256 amount); /** * @dev Revert with an error when a partial fill is attempted on an order * that does not specify partial fill support in its order type. */ error PartialFillsNotEnabledForOrder(); /** * @dev Revert with an error when attempting to fill an order that has been * cancelled. * * @param orderHash The hash of the cancelled order. */ error OrderIsCancelled(bytes32 orderHash); /** * @dev Revert with an error when attempting to fill a basic order that has * been partially filled. * * @param orderHash The hash of the partially used order. */ error OrderPartiallyFilled(bytes32 orderHash); /** * @dev Revert with an error when attempting to cancel an order as a caller * other than the indicated offerer or zone. */ error InvalidCanceller(); /** * @dev Revert with an error when supplying a fraction with a value of zero * for the numerator or denominator, or one where the numerator exceeds * the denominator. */ error BadFraction(); /** * @dev Revert with an error when a caller attempts to supply callvalue to a * non-payable basic order route or does not supply any callvalue to a * payable basic order route. */ error InvalidMsgValue(uint256 value); /** * @dev Revert with an error when attempting to fill a basic order using * calldata not produced by default ABI encoding. */ error InvalidBasicOrderParameterEncoding(); /** * @dev Revert with an error when attempting to fulfill any number of * available orders when none are fulfillable. */ error NoSpecifiedOrdersAvailable(); /** * @dev Revert with an error when attempting to fulfill an order with an * offer for ETH outside of matching orders. */ error InvalidNativeOfferItem(); }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.7; /** * @title ReentrancyErrors * @author 0age * @notice ReentrancyErrors contains errors related to reentrancy. */ interface ReentrancyErrors { /** * @dev Revert with an error when a caller attempts to reenter a protected * function. */ error NoReentrantCalls(); }
// SPDX-License-Identifier: MIT pragma solidity >=0.8.7; /** * @title ConduitControllerInterface * @author 0age * @notice ConduitControllerInterface contains all external function interfaces, * structs, events, and errors for the conduit controller. */ interface ConduitControllerInterface { /** * @dev Track the conduit key, current owner, new potential owner, and open * channels for each deployed conduit. */ struct ConduitProperties { bytes32 key; address owner; address potentialOwner; address[] channels; mapping(address => uint256) channelIndexesPlusOne; } /** * @dev Emit an event whenever a new conduit is created. * * @param conduit The newly created conduit. * @param conduitKey The conduit key used to create the new conduit. */ event NewConduit(address conduit, bytes32 conduitKey); /** * @dev Emit an event whenever conduit ownership is transferred. * * @param conduit The conduit for which ownership has been * transferred. * @param previousOwner The previous owner of the conduit. * @param newOwner The new owner of the conduit. */ event OwnershipTransferred( address indexed conduit, address indexed previousOwner, address indexed newOwner ); /** * @dev Emit an event whenever a conduit owner registers a new potential * owner for that conduit. * * @param newPotentialOwner The new potential owner of the conduit. */ event PotentialOwnerUpdated(address indexed newPotentialOwner); /** * @dev Revert with an error when attempting to create a new conduit using a * conduit key where the first twenty bytes of the key do not match the * address of the caller. */ error InvalidCreator(); /** * @dev Revert with an error when attempting to create a new conduit when no * initial owner address is supplied. */ error InvalidInitialOwner(); /** * @dev Revert with an error when attempting to set a new potential owner * that is already set. */ error NewPotentialOwnerAlreadySet( address conduit, address newPotentialOwner ); /** * @dev Revert with an error when attempting to cancel ownership transfer * when no new potential owner is currently set. */ error NoPotentialOwnerCurrentlySet(address conduit); /** * @dev Revert with an error when attempting to interact with a conduit that * does not yet exist. */ error NoConduit(); /** * @dev Revert with an error when attempting to create a conduit that * already exists. */ error ConduitAlreadyExists(address conduit); /** * @dev Revert with an error when attempting to update channels or transfer * ownership of a conduit when the caller is not the owner of the * conduit in question. */ error CallerIsNotOwner(address conduit); /** * @dev Revert with an error when attempting to register a new potential * owner and supplying the null address. */ error NewPotentialOwnerIsZeroAddress(address conduit); /** * @dev Revert with an error when attempting to claim ownership of a conduit * with a caller that is not the current potential owner for the * conduit in question. */ error CallerIsNotNewPotentialOwner(address conduit); /** * @dev Revert with an error when attempting to retrieve a channel using an * index that is out of range. */ error ChannelOutOfRange(address conduit); /** * @notice Deploy a new conduit using a supplied conduit key and assigning * an initial owner for the deployed conduit. Note that the first * twenty bytes of the supplied conduit key must match the caller * and that a new conduit cannot be created if one has already been * deployed using the same conduit key. * * @param conduitKey The conduit key used to deploy the conduit. Note that * the first twenty bytes of the conduit key must match * the caller of this contract. * @param initialOwner The initial owner to set for the new conduit. * * @return conduit The address of the newly deployed conduit. */ function createConduit(bytes32 conduitKey, address initialOwner) external returns (address conduit); /** * @notice Open or close a channel on a given conduit, thereby allowing the * specified account to execute transfers against that conduit. * Extreme care must be taken when updating channels, as malicious * or vulnerable channels can transfer any ERC20, ERC721 and ERC1155 * tokens where the token holder has granted the conduit approval. * Only the owner of the conduit in question may call this function. * * @param conduit The conduit for which to open or close the channel. * @param channel The channel to open or close on the conduit. * @param isOpen A boolean indicating whether to open or close the channel. */ function updateChannel( address conduit, address channel, bool isOpen ) external; /** * @notice Initiate conduit ownership transfer by assigning a new potential * owner for the given conduit. Once set, the new potential owner * may call `acceptOwnership` to claim ownership of the conduit. * Only the owner of the conduit in question may call this function. * * @param conduit The conduit for which to initiate ownership transfer. * @param newPotentialOwner The new potential owner of the conduit. */ function transferOwnership(address conduit, address newPotentialOwner) external; /** * @notice Clear the currently set potential owner, if any, from a conduit. * Only the owner of the conduit in question may call this function. * * @param conduit The conduit for which to cancel ownership transfer. */ function cancelOwnershipTransfer(address conduit) external; /** * @notice Accept ownership of a supplied conduit. Only accounts that the * current owner has set as the new potential owner may call this * function. * * @param conduit The conduit for which to accept ownership. */ function acceptOwnership(address conduit) external; /** * @notice Retrieve the current owner of a deployed conduit. * * @param conduit The conduit for which to retrieve the associated owner. * * @return owner The owner of the supplied conduit. */ function ownerOf(address conduit) external view returns (address owner); /** * @notice Retrieve the conduit key for a deployed conduit via reverse * lookup. * * @param conduit The conduit for which to retrieve the associated conduit * key. * * @return conduitKey The conduit key used to deploy the supplied conduit. */ function getKey(address conduit) external view returns (bytes32 conduitKey); /** * @notice Derive the conduit associated with a given conduit key and * determine whether that conduit exists (i.e. whether it has been * deployed). * * @param conduitKey The conduit key used to derive the conduit. * * @return conduit The derived address of the conduit. * @return exists A boolean indicating whether the derived conduit has been * deployed or not. */ function getConduit(bytes32 conduitKey) external view returns (address conduit, bool exists); /** * @notice Retrieve the potential owner, if any, for a given conduit. The * current owner may set a new potential owner via * `transferOwnership` and that owner may then accept ownership of * the conduit in question via `acceptOwnership`. * * @param conduit The conduit for which to retrieve the potential owner. * * @return potentialOwner The potential owner, if any, for the conduit. */ function getPotentialOwner(address conduit) external view returns (address potentialOwner); /** * @notice Retrieve the status (either open or closed) of a given channel on * a conduit. * * @param conduit The conduit for which to retrieve the channel status. * @param channel The channel for which to retrieve the status. * * @return isOpen The status of the channel on the given conduit. */ function getChannelStatus(address conduit, address channel) external view returns (bool isOpen); /** * @notice Retrieve the total number of open channels for a given conduit. * * @param conduit The conduit for which to retrieve the total channel count. * * @return totalChannels The total number of open channels for the conduit. */ function getTotalChannels(address conduit) external view returns (uint256 totalChannels); /** * @notice Retrieve an open channel at a specific index for a given conduit. * Note that the index of a channel can change as a result of other * channels being closed on the conduit. * * @param conduit The conduit for which to retrieve the open channel. * @param channelIndex The index of the channel in question. * * @return channel The open channel, if any, at the specified channel index. */ function getChannel(address conduit, uint256 channelIndex) external view returns (address channel); /** * @notice Retrieve all open channels for a given conduit. Note that calling * this function for a conduit with many channels will revert with * an out-of-gas error. * * @param conduit The conduit for which to retrieve open channels. * * @return channels An array of open channels on the given conduit. */ function getChannels(address conduit) external view returns (address[] memory channels); /** * @dev Retrieve the conduit creation code and runtime code hashes. */ function getConduitCodeHashes() external view returns (bytes32 creationCodeHash, bytes32 runtimeCodeHash); }
{ "optimizer": { "enabled": true, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "abi" ] } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"conduitController","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"BadContractSignature","type":"error"},{"inputs":[],"name":"BadFraction","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"BadReturnValueFromERC20OnTransfer","type":"error"},{"inputs":[{"internalType":"uint8","name":"v","type":"uint8"}],"name":"BadSignatureV","type":"error"},{"inputs":[],"name":"ConsiderationCriteriaResolverOutOfRange","type":"error"},{"inputs":[{"internalType":"uint256","name":"orderIndex","type":"uint256"},{"internalType":"uint256","name":"considerationIndex","type":"uint256"},{"internalType":"uint256","name":"shortfallAmount","type":"uint256"}],"name":"ConsiderationNotMet","type":"error"},{"inputs":[],"name":"CriteriaNotEnabledForItem","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256[]","name":"identifiers","type":"uint256[]"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"name":"ERC1155BatchTransferGenericFailure","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"EtherTransferGenericFailure","type":"error"},{"inputs":[],"name":"InexactFraction","type":"error"},{"inputs":[],"name":"InsufficientEtherSupplied","type":"error"},{"inputs":[],"name":"Invalid1155BatchTransferEncoding","type":"error"},{"inputs":[],"name":"InvalidBasicOrderParameterEncoding","type":"error"},{"inputs":[{"internalType":"address","name":"conduit","type":"address"}],"name":"InvalidCallToConduit","type":"error"},{"inputs":[],"name":"InvalidCanceller","type":"error"},{"inputs":[{"internalType":"bytes32","name":"conduitKey","type":"bytes32"},{"internalType":"address","name":"conduit","type":"address"}],"name":"InvalidConduit","type":"error"},{"inputs":[],"name":"InvalidERC721TransferAmount","type":"error"},{"inputs":[],"name":"InvalidFulfillmentComponentData","type":"error"},{"inputs":[{"internalType":"uint256","name":"value","type":"uint256"}],"name":"InvalidMsgValue","type":"error"},{"inputs":[],"name":"InvalidNativeOfferItem","type":"error"},{"inputs":[],"name":"InvalidProof","type":"error"},{"inputs":[{"internalType":"bytes32","name":"orderHash","type":"bytes32"}],"name":"InvalidRestrictedOrder","type":"error"},{"inputs":[],"name":"InvalidSignature","type":"error"},{"inputs":[],"name":"InvalidSigner","type":"error"},{"inputs":[],"name":"InvalidTime","type":"error"},{"inputs":[],"name":"MismatchedFulfillmentOfferAndConsiderationComponents","type":"error"},{"inputs":[{"internalType":"enum Side","name":"side","type":"uint8"}],"name":"MissingFulfillmentComponentOnAggregation","type":"error"},{"inputs":[],"name":"MissingItemAmount","type":"error"},{"inputs":[],"name":"MissingOriginalConsiderationItems","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"NoContract","type":"error"},{"inputs":[],"name":"NoReentrantCalls","type":"error"},{"inputs":[],"name":"NoSpecifiedOrdersAvailable","type":"error"},{"inputs":[],"name":"OfferAndConsiderationRequiredOnFulfillment","type":"error"},{"inputs":[],"name":"OfferCriteriaResolverOutOfRange","type":"error"},{"inputs":[{"internalType":"bytes32","name":"orderHash","type":"bytes32"}],"name":"OrderAlreadyFilled","type":"error"},{"inputs":[],"name":"OrderCriteriaResolverOutOfRange","type":"error"},{"inputs":[{"internalType":"bytes32","name":"orderHash","type":"bytes32"}],"name":"OrderIsCancelled","type":"error"},{"inputs":[{"internalType":"bytes32","name":"orderHash","type":"bytes32"}],"name":"OrderPartiallyFilled","type":"error"},{"inputs":[],"name":"PartialFillsNotEnabledForOrder","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"identifier","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"TokenTransferGenericFailure","type":"error"},{"inputs":[],"name":"UnresolvedConsiderationCriteria","type":"error"},{"inputs":[],"name":"UnresolvedOfferCriteria","type":"error"},{"inputs":[],"name":"UnusedItemParameters","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newCounter","type":"uint256"},{"indexed":true,"internalType":"address","name":"offerer","type":"address"}],"name":"CounterIncremented","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"orderHash","type":"bytes32"},{"indexed":true,"internalType":"address","name":"offerer","type":"address"},{"indexed":true,"internalType":"address","name":"zone","type":"address"}],"name":"OrderCancelled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"orderHash","type":"bytes32"},{"indexed":true,"internalType":"address","name":"offerer","type":"address"},{"indexed":true,"internalType":"address","name":"zone","type":"address"},{"indexed":false,"internalType":"address","name":"recipient","type":"address"},{"components":[{"internalType":"enum ItemType","name":"itemType","type":"uint8"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"identifier","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"}],"indexed":false,"internalType":"struct SpentItem[]","name":"offer","type":"tuple[]"},{"components":[{"internalType":"enum ItemType","name":"itemType","type":"uint8"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"identifier","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address payable","name":"recipient","type":"address"}],"indexed":false,"internalType":"struct ReceivedItem[]","name":"consideration","type":"tuple[]"}],"name":"OrderFulfilled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"orderHash","type":"bytes32"},{"indexed":true,"internalType":"address","name":"offerer","type":"address"},{"indexed":true,"internalType":"address","name":"zone","type":"address"}],"name":"OrderValidated","type":"event"},{"inputs":[{"components":[{"internalType":"address","name":"offerer","type":"address"},{"internalType":"address","name":"zone","type":"address"},{"components":[{"internalType":"enum ItemType","name":"itemType","type":"uint8"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"identifierOrCriteria","type":"uint256"},{"internalType":"uint256","name":"startAmount","type":"uint256"},{"internalType":"uint256","name":"endAmount","type":"uint256"}],"internalType":"struct OfferItem[]","name":"offer","type":"tuple[]"},{"components":[{"internalType":"enum ItemType","name":"itemType","type":"uint8"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"identifierOrCriteria","type":"uint256"},{"internalType":"uint256","name":"startAmount","type":"uint256"},{"internalType":"uint256","name":"endAmount","type":"uint256"},{"internalType":"address payable","name":"recipient","type":"address"}],"internalType":"struct ConsiderationItem[]","name":"consideration","type":"tuple[]"},{"internalType":"enum OrderType","name":"orderType","type":"uint8"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"endTime","type":"uint256"},{"internalType":"bytes32","name":"zoneHash","type":"bytes32"},{"internalType":"uint256","name":"salt","type":"uint256"},{"internalType":"bytes32","name":"conduitKey","type":"bytes32"},{"internalType":"uint256","name":"counter","type":"uint256"}],"internalType":"struct OrderComponents[]","name":"orders","type":"tuple[]"}],"name":"cancel","outputs":[{"internalType":"bool","name":"cancelled","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"address","name":"offerer","type":"address"},{"internalType":"address","name":"zone","type":"address"},{"components":[{"internalType":"enum ItemType","name":"itemType","type":"uint8"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"identifierOrCriteria","type":"uint256"},{"internalType":"uint256","name":"startAmount","type":"uint256"},{"internalType":"uint256","name":"endAmount","type":"uint256"}],"internalType":"struct OfferItem[]","name":"offer","type":"tuple[]"},{"components":[{"internalType":"enum ItemType","name":"itemType","type":"uint8"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"identifierOrCriteria","type":"uint256"},{"internalType":"uint256","name":"startAmount","type":"uint256"},{"internalType":"uint256","name":"endAmount","type":"uint256"},{"internalType":"address payable","name":"recipient","type":"address"}],"internalType":"struct ConsiderationItem[]","name":"consideration","type":"tuple[]"},{"internalType":"enum OrderType","name":"orderType","type":"uint8"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"endTime","type":"uint256"},{"internalType":"bytes32","name":"zoneHash","type":"bytes32"},{"internalType":"uint256","name":"salt","type":"uint256"},{"internalType":"bytes32","name":"conduitKey","type":"bytes32"},{"internalType":"uint256","name":"totalOriginalConsiderationItems","type":"uint256"}],"internalType":"struct OrderParameters","name":"parameters","type":"tuple"},{"internalType":"uint120","name":"numerator","type":"uint120"},{"internalType":"uint120","name":"denominator","type":"uint120"},{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"bytes","name":"extraData","type":"bytes"}],"internalType":"struct AdvancedOrder","name":"advancedOrder","type":"tuple"},{"components":[{"internalType":"uint256","name":"orderIndex","type":"uint256"},{"internalType":"enum Side","name":"side","type":"uint8"},{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"uint256","name":"identifier","type":"uint256"},{"internalType":"bytes32[]","name":"criteriaProof","type":"bytes32[]"}],"internalType":"struct CriteriaResolver[]","name":"criteriaResolvers","type":"tuple[]"},{"internalType":"bytes32","name":"fulfillerConduitKey","type":"bytes32"},{"internalType":"address","name":"recipient","type":"address"}],"name":"fulfillAdvancedOrder","outputs":[{"internalType":"bool","name":"fulfilled","type":"bool"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"address","name":"offerer","type":"address"},{"internalType":"address","name":"zone","type":"address"},{"components":[{"internalType":"enum ItemType","name":"itemType","type":"uint8"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"identifierOrCriteria","type":"uint256"},{"internalType":"uint256","name":"startAmount","type":"uint256"},{"internalType":"uint256","name":"endAmount","type":"uint256"}],"internalType":"struct OfferItem[]","name":"offer","type":"tuple[]"},{"components":[{"internalType":"enum ItemType","name":"itemType","type":"uint8"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"identifierOrCriteria","type":"uint256"},{"internalType":"uint256","name":"startAmount","type":"uint256"},{"internalType":"uint256","name":"endAmount","type":"uint256"},{"internalType":"address payable","name":"recipient","type":"address"}],"internalType":"struct ConsiderationItem[]","name":"consideration","type":"tuple[]"},{"internalType":"enum OrderType","name":"orderType","type":"uint8"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"endTime","type":"uint256"},{"internalType":"bytes32","name":"zoneHash","type":"bytes32"},{"internalType":"uint256","name":"salt","type":"uint256"},{"internalType":"bytes32","name":"conduitKey","type":"bytes32"},{"internalType":"uint256","name":"totalOriginalConsiderationItems","type":"uint256"}],"internalType":"struct OrderParameters","name":"parameters","type":"tuple"},{"internalType":"uint120","name":"numerator","type":"uint120"},{"internalType":"uint120","name":"denominator","type":"uint120"},{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"bytes","name":"extraData","type":"bytes"}],"internalType":"struct AdvancedOrder[]","name":"advancedOrders","type":"tuple[]"},{"components":[{"internalType":"uint256","name":"orderIndex","type":"uint256"},{"internalType":"enum Side","name":"side","type":"uint8"},{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"uint256","name":"identifier","type":"uint256"},{"internalType":"bytes32[]","name":"criteriaProof","type":"bytes32[]"}],"internalType":"struct CriteriaResolver[]","name":"criteriaResolvers","type":"tuple[]"},{"components":[{"internalType":"uint256","name":"orderIndex","type":"uint256"},{"internalType":"uint256","name":"itemIndex","type":"uint256"}],"internalType":"struct FulfillmentComponent[][]","name":"offerFulfillments","type":"tuple[][]"},{"components":[{"internalType":"uint256","name":"orderIndex","type":"uint256"},{"internalType":"uint256","name":"itemIndex","type":"uint256"}],"internalType":"struct FulfillmentComponent[][]","name":"considerationFulfillments","type":"tuple[][]"},{"internalType":"bytes32","name":"fulfillerConduitKey","type":"bytes32"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"maximumFulfilled","type":"uint256"}],"name":"fulfillAvailableAdvancedOrders","outputs":[{"internalType":"bool[]","name":"availableOrders","type":"bool[]"},{"components":[{"components":[{"internalType":"enum ItemType","name":"itemType","type":"uint8"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"identifier","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address payable","name":"recipient","type":"address"}],"internalType":"struct ReceivedItem","name":"item","type":"tuple"},{"internalType":"address","name":"offerer","type":"address"},{"internalType":"bytes32","name":"conduitKey","type":"bytes32"}],"internalType":"struct Execution[]","name":"executions","type":"tuple[]"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"address","name":"offerer","type":"address"},{"internalType":"address","name":"zone","type":"address"},{"components":[{"internalType":"enum ItemType","name":"itemType","type":"uint8"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"identifierOrCriteria","type":"uint256"},{"internalType":"uint256","name":"startAmount","type":"uint256"},{"internalType":"uint256","name":"endAmount","type":"uint256"}],"internalType":"struct OfferItem[]","name":"offer","type":"tuple[]"},{"components":[{"internalType":"enum ItemType","name":"itemType","type":"uint8"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"identifierOrCriteria","type":"uint256"},{"internalType":"uint256","name":"startAmount","type":"uint256"},{"internalType":"uint256","name":"endAmount","type":"uint256"},{"internalType":"address payable","name":"recipient","type":"address"}],"internalType":"struct ConsiderationItem[]","name":"consideration","type":"tuple[]"},{"internalType":"enum OrderType","name":"orderType","type":"uint8"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"endTime","type":"uint256"},{"internalType":"bytes32","name":"zoneHash","type":"bytes32"},{"internalType":"uint256","name":"salt","type":"uint256"},{"internalType":"bytes32","name":"conduitKey","type":"bytes32"},{"internalType":"uint256","name":"totalOriginalConsiderationItems","type":"uint256"}],"internalType":"struct OrderParameters","name":"parameters","type":"tuple"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct Order[]","name":"orders","type":"tuple[]"},{"components":[{"internalType":"uint256","name":"orderIndex","type":"uint256"},{"internalType":"uint256","name":"itemIndex","type":"uint256"}],"internalType":"struct FulfillmentComponent[][]","name":"offerFulfillments","type":"tuple[][]"},{"components":[{"internalType":"uint256","name":"orderIndex","type":"uint256"},{"internalType":"uint256","name":"itemIndex","type":"uint256"}],"internalType":"struct FulfillmentComponent[][]","name":"considerationFulfillments","type":"tuple[][]"},{"internalType":"bytes32","name":"fulfillerConduitKey","type":"bytes32"},{"internalType":"uint256","name":"maximumFulfilled","type":"uint256"}],"name":"fulfillAvailableOrders","outputs":[{"internalType":"bool[]","name":"availableOrders","type":"bool[]"},{"components":[{"components":[{"internalType":"enum ItemType","name":"itemType","type":"uint8"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"identifier","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address payable","name":"recipient","type":"address"}],"internalType":"struct ReceivedItem","name":"item","type":"tuple"},{"internalType":"address","name":"offerer","type":"address"},{"internalType":"bytes32","name":"conduitKey","type":"bytes32"}],"internalType":"struct Execution[]","name":"executions","type":"tuple[]"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"considerationToken","type":"address"},{"internalType":"uint256","name":"considerationIdentifier","type":"uint256"},{"internalType":"uint256","name":"considerationAmount","type":"uint256"},{"internalType":"address payable","name":"offerer","type":"address"},{"internalType":"address","name":"zone","type":"address"},{"internalType":"address","name":"offerToken","type":"address"},{"internalType":"uint256","name":"offerIdentifier","type":"uint256"},{"internalType":"uint256","name":"offerAmount","type":"uint256"},{"internalType":"enum BasicOrderType","name":"basicOrderType","type":"uint8"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"endTime","type":"uint256"},{"internalType":"bytes32","name":"zoneHash","type":"bytes32"},{"internalType":"uint256","name":"salt","type":"uint256"},{"internalType":"bytes32","name":"offererConduitKey","type":"bytes32"},{"internalType":"bytes32","name":"fulfillerConduitKey","type":"bytes32"},{"internalType":"uint256","name":"totalOriginalAdditionalRecipients","type":"uint256"},{"components":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address payable","name":"recipient","type":"address"}],"internalType":"struct AdditionalRecipient[]","name":"additionalRecipients","type":"tuple[]"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct BasicOrderParameters","name":"parameters","type":"tuple"}],"name":"fulfillBasicOrder","outputs":[{"internalType":"bool","name":"fulfilled","type":"bool"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"address","name":"offerer","type":"address"},{"internalType":"address","name":"zone","type":"address"},{"components":[{"internalType":"enum ItemType","name":"itemType","type":"uint8"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"identifierOrCriteria","type":"uint256"},{"internalType":"uint256","name":"startAmount","type":"uint256"},{"internalType":"uint256","name":"endAmount","type":"uint256"}],"internalType":"struct OfferItem[]","name":"offer","type":"tuple[]"},{"components":[{"internalType":"enum ItemType","name":"itemType","type":"uint8"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"identifierOrCriteria","type":"uint256"},{"internalType":"uint256","name":"startAmount","type":"uint256"},{"internalType":"uint256","name":"endAmount","type":"uint256"},{"internalType":"address payable","name":"recipient","type":"address"}],"internalType":"struct ConsiderationItem[]","name":"consideration","type":"tuple[]"},{"internalType":"enum OrderType","name":"orderType","type":"uint8"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"endTime","type":"uint256"},{"internalType":"bytes32","name":"zoneHash","type":"bytes32"},{"internalType":"uint256","name":"salt","type":"uint256"},{"internalType":"bytes32","name":"conduitKey","type":"bytes32"},{"internalType":"uint256","name":"totalOriginalConsiderationItems","type":"uint256"}],"internalType":"struct OrderParameters","name":"parameters","type":"tuple"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct Order","name":"order","type":"tuple"},{"internalType":"bytes32","name":"fulfillerConduitKey","type":"bytes32"}],"name":"fulfillOrder","outputs":[{"internalType":"bool","name":"fulfilled","type":"bool"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"offerer","type":"address"}],"name":"getCounter","outputs":[{"internalType":"uint256","name":"counter","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"offerer","type":"address"},{"internalType":"address","name":"zone","type":"address"},{"components":[{"internalType":"enum ItemType","name":"itemType","type":"uint8"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"identifierOrCriteria","type":"uint256"},{"internalType":"uint256","name":"startAmount","type":"uint256"},{"internalType":"uint256","name":"endAmount","type":"uint256"}],"internalType":"struct OfferItem[]","name":"offer","type":"tuple[]"},{"components":[{"internalType":"enum ItemType","name":"itemType","type":"uint8"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"identifierOrCriteria","type":"uint256"},{"internalType":"uint256","name":"startAmount","type":"uint256"},{"internalType":"uint256","name":"endAmount","type":"uint256"},{"internalType":"address payable","name":"recipient","type":"address"}],"internalType":"struct ConsiderationItem[]","name":"consideration","type":"tuple[]"},{"internalType":"enum OrderType","name":"orderType","type":"uint8"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"endTime","type":"uint256"},{"internalType":"bytes32","name":"zoneHash","type":"bytes32"},{"internalType":"uint256","name":"salt","type":"uint256"},{"internalType":"bytes32","name":"conduitKey","type":"bytes32"},{"internalType":"uint256","name":"counter","type":"uint256"}],"internalType":"struct OrderComponents","name":"order","type":"tuple"}],"name":"getOrderHash","outputs":[{"internalType":"bytes32","name":"orderHash","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"orderHash","type":"bytes32"}],"name":"getOrderStatus","outputs":[{"internalType":"bool","name":"isValidated","type":"bool"},{"internalType":"bool","name":"isCancelled","type":"bool"},{"internalType":"uint256","name":"totalFilled","type":"uint256"},{"internalType":"uint256","name":"totalSize","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"incrementCounter","outputs":[{"internalType":"uint256","name":"newCounter","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"information","outputs":[{"internalType":"string","name":"version","type":"string"},{"internalType":"bytes32","name":"domainSeparator","type":"bytes32"},{"internalType":"address","name":"conduitController","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"address","name":"offerer","type":"address"},{"internalType":"address","name":"zone","type":"address"},{"components":[{"internalType":"enum ItemType","name":"itemType","type":"uint8"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"identifierOrCriteria","type":"uint256"},{"internalType":"uint256","name":"startAmount","type":"uint256"},{"internalType":"uint256","name":"endAmount","type":"uint256"}],"internalType":"struct OfferItem[]","name":"offer","type":"tuple[]"},{"components":[{"internalType":"enum ItemType","name":"itemType","type":"uint8"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"identifierOrCriteria","type":"uint256"},{"internalType":"uint256","name":"startAmount","type":"uint256"},{"internalType":"uint256","name":"endAmount","type":"uint256"},{"internalType":"address payable","name":"recipient","type":"address"}],"internalType":"struct ConsiderationItem[]","name":"consideration","type":"tuple[]"},{"internalType":"enum OrderType","name":"orderType","type":"uint8"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"endTime","type":"uint256"},{"internalType":"bytes32","name":"zoneHash","type":"bytes32"},{"internalType":"uint256","name":"salt","type":"uint256"},{"internalType":"bytes32","name":"conduitKey","type":"bytes32"},{"internalType":"uint256","name":"totalOriginalConsiderationItems","type":"uint256"}],"internalType":"struct OrderParameters","name":"parameters","type":"tuple"},{"internalType":"uint120","name":"numerator","type":"uint120"},{"internalType":"uint120","name":"denominator","type":"uint120"},{"internalType":"bytes","name":"signature","type":"bytes"},{"internalType":"bytes","name":"extraData","type":"bytes"}],"internalType":"struct AdvancedOrder[]","name":"advancedOrders","type":"tuple[]"},{"components":[{"internalType":"uint256","name":"orderIndex","type":"uint256"},{"internalType":"enum Side","name":"side","type":"uint8"},{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"uint256","name":"identifier","type":"uint256"},{"internalType":"bytes32[]","name":"criteriaProof","type":"bytes32[]"}],"internalType":"struct CriteriaResolver[]","name":"criteriaResolvers","type":"tuple[]"},{"components":[{"components":[{"internalType":"uint256","name":"orderIndex","type":"uint256"},{"internalType":"uint256","name":"itemIndex","type":"uint256"}],"internalType":"struct FulfillmentComponent[]","name":"offerComponents","type":"tuple[]"},{"components":[{"internalType":"uint256","name":"orderIndex","type":"uint256"},{"internalType":"uint256","name":"itemIndex","type":"uint256"}],"internalType":"struct FulfillmentComponent[]","name":"considerationComponents","type":"tuple[]"}],"internalType":"struct Fulfillment[]","name":"fulfillments","type":"tuple[]"}],"name":"matchAdvancedOrders","outputs":[{"components":[{"components":[{"internalType":"enum ItemType","name":"itemType","type":"uint8"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"identifier","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address payable","name":"recipient","type":"address"}],"internalType":"struct ReceivedItem","name":"item","type":"tuple"},{"internalType":"address","name":"offerer","type":"address"},{"internalType":"bytes32","name":"conduitKey","type":"bytes32"}],"internalType":"struct Execution[]","name":"executions","type":"tuple[]"}],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"address","name":"offerer","type":"address"},{"internalType":"address","name":"zone","type":"address"},{"components":[{"internalType":"enum ItemType","name":"itemType","type":"uint8"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"identifierOrCriteria","type":"uint256"},{"internalType":"uint256","name":"startAmount","type":"uint256"},{"internalType":"uint256","name":"endAmount","type":"uint256"}],"internalType":"struct OfferItem[]","name":"offer","type":"tuple[]"},{"components":[{"internalType":"enum ItemType","name":"itemType","type":"uint8"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"identifierOrCriteria","type":"uint256"},{"internalType":"uint256","name":"startAmount","type":"uint256"},{"internalType":"uint256","name":"endAmount","type":"uint256"},{"internalType":"address payable","name":"recipient","type":"address"}],"internalType":"struct ConsiderationItem[]","name":"consideration","type":"tuple[]"},{"internalType":"enum OrderType","name":"orderType","type":"uint8"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"endTime","type":"uint256"},{"internalType":"bytes32","name":"zoneHash","type":"bytes32"},{"internalType":"uint256","name":"salt","type":"uint256"},{"internalType":"bytes32","name":"conduitKey","type":"bytes32"},{"internalType":"uint256","name":"totalOriginalConsiderationItems","type":"uint256"}],"internalType":"struct OrderParameters","name":"parameters","type":"tuple"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct Order[]","name":"orders","type":"tuple[]"},{"components":[{"components":[{"internalType":"uint256","name":"orderIndex","type":"uint256"},{"internalType":"uint256","name":"itemIndex","type":"uint256"}],"internalType":"struct FulfillmentComponent[]","name":"offerComponents","type":"tuple[]"},{"components":[{"internalType":"uint256","name":"orderIndex","type":"uint256"},{"internalType":"uint256","name":"itemIndex","type":"uint256"}],"internalType":"struct FulfillmentComponent[]","name":"considerationComponents","type":"tuple[]"}],"internalType":"struct Fulfillment[]","name":"fulfillments","type":"tuple[]"}],"name":"matchOrders","outputs":[{"components":[{"components":[{"internalType":"enum ItemType","name":"itemType","type":"uint8"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"identifier","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address payable","name":"recipient","type":"address"}],"internalType":"struct ReceivedItem","name":"item","type":"tuple"},{"internalType":"address","name":"offerer","type":"address"},{"internalType":"bytes32","name":"conduitKey","type":"bytes32"}],"internalType":"struct Execution[]","name":"executions","type":"tuple[]"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"contractName","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"address","name":"offerer","type":"address"},{"internalType":"address","name":"zone","type":"address"},{"components":[{"internalType":"enum ItemType","name":"itemType","type":"uint8"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"identifierOrCriteria","type":"uint256"},{"internalType":"uint256","name":"startAmount","type":"uint256"},{"internalType":"uint256","name":"endAmount","type":"uint256"}],"internalType":"struct OfferItem[]","name":"offer","type":"tuple[]"},{"components":[{"internalType":"enum ItemType","name":"itemType","type":"uint8"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"identifierOrCriteria","type":"uint256"},{"internalType":"uint256","name":"startAmount","type":"uint256"},{"internalType":"uint256","name":"endAmount","type":"uint256"},{"internalType":"address payable","name":"recipient","type":"address"}],"internalType":"struct ConsiderationItem[]","name":"consideration","type":"tuple[]"},{"internalType":"enum OrderType","name":"orderType","type":"uint8"},{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"endTime","type":"uint256"},{"internalType":"bytes32","name":"zoneHash","type":"bytes32"},{"internalType":"uint256","name":"salt","type":"uint256"},{"internalType":"bytes32","name":"conduitKey","type":"bytes32"},{"internalType":"uint256","name":"totalOriginalConsiderationItems","type":"uint256"}],"internalType":"struct OrderParameters","name":"parameters","type":"tuple"},{"internalType":"bytes","name":"signature","type":"bytes"}],"internalType":"struct Order[]","name":"orders","type":"tuple[]"}],"name":"validate","outputs":[{"internalType":"bool","name":"validated","type":"bool"}],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
6101c06040523480156200001257600080fd5b5060405162005b9b38038062005b9b8339810160408190526200003591620005c6565b808080808080808080806200004962000132565b610120526101005260e05260c081815260a0838152608085815246610140819052604080516020818101979097528082019890985260608801969096529086015230858201528351808603909101815293019091528151910120610160526001600160a01b03811661018081905260408051630a96ad3960e01b81528151630a96ad39926004808401939192918290030181865afa158015620000f0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620001169190620005f8565b506101a052505060016000555062000688975050505050505050565b600080808080806200015e60408051808201909152600781526614d9585c1bdc9d60ca1b602082015290565b80516020918201206040805180820182526003815262312e3160e81b90840152519097507f722c0e0c80487266e8c6a45e3a1a803aab23378a9c32e6ebe029d4fad7bfc96596506000916200026391016909ecccccae492e8cada560b31b81526e1d5a5b9d0e081a5d195b551e5c194b608a1b600a8201526d1859191c995cdcc81d1bdad95b8b60921b60198201527f75696e74323536206964656e7469666965724f7243726974657269612c00000060278201527f75696e74323536207374617274416d6f756e742c0000000000000000000000006044820152701d5a5b9d0c8d4d88195b99105b5bdd5b9d607a1b6058820152602960f81b6069820152606a0190565b60408051601f1981840301815282825271086dedce6d2c8cae4c2e8d2dedc92e8cada560731b60208401526e1d5a5b9d0e081a5d195b551e5c194b608a1b60328401526d1859191c995cdcc81d1bdad95b8b60921b60418401527f75696e74323536206964656e7469666965724f7243726974657269612c000000604f8401527f75696e74323536207374617274416d6f756e742c000000000000000000000000606c840152711d5a5b9d0c8d4d88195b99105b5bdd5b9d0b60721b6080840152701859191c995cdcc81c9958da5c1a595b9d607a1b6092840152602960f81b60a384018190528251808503608401815260a485019093526f09ee4c8cae486dedae0dedccadce8e6560831b60c48501526f1859191c995cdcc81bd999995c995c8b60821b60d48501526c1859191c995cdcc81e9bdb994b609a1b60e48501527113d999995c925d195b56d7481bd999995c8b60721b60f18501527f436f6e73696465726174696f6e4974656d5b5d20636f6e73696465726174696f610103850152611b8b60f21b6101238501526f1d5a5b9d0e081bdc99195c951e5c194b60821b610125850152711d5a5b9d0c8d4d881cdd185c9d151a5b594b60721b6101358501526f1d5a5b9d0c8d4d88195b99151a5b594b60821b61014785015270189e5d195ccccc881e9bdb9952185cda0b607a1b6101578501526c1d5a5b9d0c8d4d881cd85b1d0b609a1b6101688501527f6279746573333220636f6e647569744b65792c000000000000000000000000006101758501526e3ab4b73a191a9b1031b7bab73a32b960891b6101888501526101978401529250906000906101980160408051601f19818403018152908290526c08a92a06e626488dedac2d2dc5609b1b60208301526b1cdd1c9a5b99c81b985b594b60a21b602d8301526e1cdd1c9a5b99c81d995c9cda5bdb8b608a1b60398301526f1d5a5b9d0c8d4d8818da185a5b92590b60821b60488301527f6164647265737320766572696679696e67436f6e7472616374000000000000006058830152602960f81b6071830152915060720160408051601f19818403018152908290528051602091820120855186830120855186840120919a5098509650620005a391839185918791016200065b565b604051602081830303815290604052805190602001209350505050909192939495565b600060208284031215620005d957600080fd5b81516001600160a01b0381168114620005f157600080fd5b9392505050565b600080604083850312156200060c57600080fd5b505080516020909101519092909150565b6000815160005b8181101562000640576020818501810151868301520162000624565b8181111562000650576000828601525b509290920192915050565b60006200067f620006786200067184886200061d565b866200061d565b846200061d565b95945050505050565b60805160a05160c05160e05161010051610120516101405161016051610180516101a05161547b6200072060003960006135a7015260008181610d21015261357601526000612313015260006122430152600081816108b0015261252101526000818161083f015261237f0152600081816107d8015261249a01526000612271015260006122bf01526000612297015261547b6000f3fe6080604052600436106100e85760003560e01c8063a81744041161008a578063f07ec37311610059578063f07ec37314610290578063f47b7740146102b0578063fb0f3ee1146102d4578063fd9f1e10146102e757600080fd5b8063a817440414610244578063b3a34c4c14610257578063e7acab241461026a578063ed98a5741461027d57600080fd5b80635b34b966116100c65780635b34b966146101b057806379df72bd146101d357806387201b41146101f3578063881477321461021457600080fd5b806306fdde03146100ed57806346423aa71461011857806355944a4214610190575b600080fd5b3480156100f957600080fd5b50610102610307565b60405161010f9190613fe2565b60405180910390f35b34801561012457600080fd5b5061016e610133366004613ff5565b60009081526002602052604090205460ff808216926101008304909116916001600160781b03620100008204811692600160881b9092041690565b604080519415158552921515602085015291830152606082015260800161010f565b6101a361019e3660046145c4565b610316565b60405161010f9190614726565b3480156101bc57600080fd5b506101c5610339565b60405190815260200161010f565b3480156101df57600080fd5b506101c56101ee366004614739565b610343565b610206610201366004614774565b6104da565b60405161010f929190614854565b34801561022057600080fd5b5061023461022f3660046148ad565b610520565b604051901515815260200161010f565b6101a36102523660046148ee565b610533565b610234610265366004614959565b6105b1565b6102346102783660046149a2565b610623565b61020661028b366004614a31565b610657565b34801561029c57600080fd5b506101c56102ab366004614ad9565b6106e1565b3480156102bc57600080fd5b506102c56106ff565b60405161010f93929190614af6565b6102346102e2366004614b29565b610717565b3480156102f357600080fd5b506102346103023660046148ad565b610722565b606061031161072e565b905090565b606061032d866103268688614b64565b8585610746565b90505b95945050505050565b6000610311610763565b6040805161016081019091526000906104d490806103646020860186614ad9565b6001600160a01b031681526020018460200160208101906103859190614ad9565b6001600160a01b031681526020016103a06040860186614c98565b808060200260200160405190810160405280939291908181526020016000905b828210156103ec576103dd60a08302860136819003810190614ce0565b815260200190600101906103c0565b50505091835250506020016104046060860186614cfc565b808060200260200160405190810160405280939291908181526020016000905b828210156104505761044160c08302860136819003810190614d44565b81526020019060010190610424565b505050918352505060200161046b60a0860160808701614d60565b600381111561047c5761047c614658565b81526020018460a0013581526020018460c0013581526020018460e001358152602001846101000135815260200184610120013581526020018480606001906104c59190614cfc565b909152506101408401356107c0565b92915050565b60608061050d8c6104eb8c8e614b64565b8b8b8b8b8b6001600160a01b038c1615610505578b610507565b335b8b610906565b915091509a509a98505050505050505050565b600061052c8383610948565b9392505050565b60606105a66105428686610aad565b604080516000808252602082019092529061059e565b61058b6040805160a081019091526000808252602082019081526020016000815260200160008152602001606081525090565b8152602001906001900390816105585790505b508585610746565b90505b949350505050565b600061052c6105bf84610b68565b604080516000808252602082019092529061061b565b6106086040805160a081019091526000808252602082019081526020016000815260200160008152602001606081525090565b8152602001906001900390816105d55790505b508433610c13565b600061032d61063187614d7b565b61063b8688614b64565b856001600160a01b038616156106515785610c13565b33610c13565b6060806106d06106678b8b610aad565b60408051600080825260208201909252906106c3565b6106b06040805160a081019091526000808252602082019081526020016000815260200160008152602001606081525090565b81526020019060019003908161067d5790505b508a8a8a8a8a338b610906565b915091509850989650505050505050565b6001600160a01b0381166000908152600160205260408120546104d4565b606060008061070c610d00565b925092509250909192565b60006104d482610d61565b600061052c8383611021565b6060602080526707536561706f727460475260606020f35b60606107588585600188516000611227565b6105a6858484611566565b600061076d611691565b503360008181526001602081815260409283902080549092019182905591518181529092917f721c20121297512b72821b97f5326877ea8ecf4bb9948fea5bfcb6453074d37f910160405180910390a290565b610140820151604080519084015180516000939284927f000000000000000000000000000000000000000000000000000000000000000092602090910190845b8181101561082d578251601f1901805186825260c082208652905260209384019390920191600101610800565b506020810260405120945050505060007f00000000000000000000000000000000000000000000000000000000000000009150604051602060608901510160005b8681101561089b578151601f1901805186825260e08220855290526020928301929091019060010161086e565b505060408051602087029020601f198a0180517f00000000000000000000000000000000000000000000000000000000000000008252928b01805197815260608c018051938152610140909c019a8b5261018082209390915295909552939097525050925250919050565b6060806109178b8b60008688611227565b6109368b6109258a8c614dd5565b61092f898b614dd5565b88886116b6565b909c909b509950505050505050505050565b6000610952611691565b6000808084815b81811015610a9f573688888381811061097457610974614ea7565b90506020028101906109869190614ebd565b9050366109938280614edd565b90506109a26020820182614ad9565b94506109b56109b082614ef4565b611896565b600081815260026020526040812098509096506109d7908790899060016118d1565b50865460ff16610a9557610a2d85876109f36020860186614f00565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061199692505050565b865460ff19166001178755610a486040820160208301614ad9565b6001600160a01b0316856001600160a01b03167ffde361574a066b44b3b5fe98a87108b7565e327327954c4faeea56a4e6491a0a88604051610a8c91815260200190565b60405180910390a35b5050600101610959565b506001979650505050505050565b606081806001600160401b03811115610ac857610ac861400e565b604051908082528060200260200182016040528015610b0157816020015b610aee613ea1565b815260200190600190039081610ae65790505b50915060005b81811015610b6057610b3b858583818110610b2457610b24614ea7565b9050602002810190610b369190614ebd565b610b68565b838281518110610b4d57610b4d614ea7565b6020908102919091010152600101610b07565b505092915050565b610b70613ea1565b6040805160a0810190915280610b868480614edd565b610b8f90614ef4565b815260200160016001600160781b0316815260200160016001600160781b03168152602001838060200190610bc49190614f00565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201829052509385525050604080516020818101909252928352909201525092915050565b6000610c1d6119eb565b60606000806000610c3189896001876119fa565b604080516001808252818301909252939650919450925060009190816020015b610c59613ea1565b815260200190600190039081610c515790505090508981600081518110610c8257610c82614ea7565b6020026020010181905250610c97818a611cb3565b600081600081518110610cac57610cac614ea7565b6020026020010151600001519050610cc78185858c8c61200c565b610ce585826000015183602001518b856040015186606001516121da565b610cef6001600055565b5060019a9950505050505050505050565b6060600080610d0d61223f565b6040805160038082528183019092529193507f00000000000000000000000000000000000000000000000000000000000000009250602082018180368337505062312e3160e81b6020830152509391925090565b600061012435600281901c90600316600182113415811480610d9d57604051630a61be9f60e41b81523460048201526024015b60405180910390fd5b5060008060008060038711915060a082026024013593506002871460028811600289030201905060018101820260028615028801039250610de2898783888888612335565b506101c46020820201356000856005811115610e0057610e00614658565b03610ea35760208901803590610e16908b614ad9565b6001600160a01b03161715610e3e57604051636ab37ce760e01b815260040160405180910390fd5b610e7383610e5260c08c0160a08d01614ad9565b610e6260808d0160608e01614ad9565b338d60c001358e60e001358761266b565b610e9e60408a0135610e8b60808c0160608d01614ad9565b610e996102008d018d614f46565b61271f565b611008565b6040805160208082528183019092526000916020820181803683370190505090506002886005811115610ed857610ed8614658565b03610f1757610f12610ef060c08c0160a08d01614ad9565b610f0060808d0160608e01614ad9565b338d60c001358e60e0013587876127da565b610fe2565b6003886005811115610f2b57610f2b614658565b03610f6557610f12610f4360c08c0160a08d01614ad9565b610f5360808d0160608e01614ad9565b338d60c001358e60e001358787612827565b6004886005811115610f7957610f79614658565b03610fb057610f12610f8e60208c018c614ad9565b33610f9f60808e0160608f01614ad9565b8d602001358e6040013587876127da565b610fe2610fc060208c018c614ad9565b33610fd160808e0160608f01614ad9565b8d602001358e604001358787612827565b610ffd610ff560808c0160608d01614ad9565b8b858461285d565b6110068161297e565b505b6110126001600055565b50600198975050505050505050565b600061102b611691565b6000808084815b81811015610a9f573688888381811061104d5761104d614ea7565b905060200281019061105f9190614edd565b905061106e6020820182614ad9565b94506110806040820160208301614ad9565b9350336001600160a01b038616148015906110a45750336001600160a01b03851614155b156110c25760405163203b1cdd60e21b815260040160405180910390fd5b60006111b1604051806101600160405280886001600160a01b03168152602001876001600160a01b031681526020018480604001906111019190614c98565b808060200260200160405190810160405280939291908181526020016000905b8282101561114d5761113e60a08302860136819003810190614ce0565b81526020019060010190611121565b50505091835250506020016111656060860186614cfc565b808060200260200160405190810160405280939291908181526020016000905b82821015610450576111a260c08302860136819003810190614d44565b81526020019060010190611185565b60008181526002602052604090819020805461ffff191661010017815590519098509091506001600160a01b0380871691908816907f6bacc01dbe442496068f7d234edd811f1a5f833243e0aec824f86ab861f3c90d906112159085815260200190565b60405180910390a35050600101611032565b61122f6119eb565b84516000816001600160401b0381111561124b5761124b61400e565b604051908082528060200260200182016040528015611274578160200160208202803683370190505b506000808252909150601d6045823560e01c061160011b905b8381101561149d5760008982815181106112a9576112a9614ea7565b60200260200101519050866000036112ce576000602090910152600181018352611495565b60008060006112df848d8d8a6119fa565b92509250925060018501875281600003611306575050600060209092019190915250611495565b8287868151811061131957611319614ea7565b6020908102919091010152835160a081015160c08201516040909201518051600019909d019c91929160005b818110156113e157600083828151811061136157611361614ea7565b602002602001015190508051158c179b506000611383898984608001516129a7565b905081608001518260600151036113a057606082018190526113b5565b6113af898984606001516129a7565b60608301525b6080820181905260608201516113cf9082898960006129e9565b60609092019190915250600101611345565b50875160600151805160005b8181101561148957600083828151811061140957611409614ea7565b6020026020010151905060006114248b8b84608001516129a7565b905081608001518260600151036114415760608201819052611456565b6114508b8b84606001516129a7565b60608301525b60808201819052606082015161147090828b8b60016129e9565b60608301525060a08101516080909101526001016113ed565b50505050505050505050505b60010161128d565b50806003036114bf576040516312d3f5a360e01b815260040160405180910390fd5b6114c98888611cb3565b60005b8381101561155b576000801b8382815181106114ea576114ea614ea7565b6020026020010151031561155357600089828151811061150c5761150c614ea7565b602002602001015160000151905061155184838151811061152f5761152f614ea7565b60200260200101518260000151836020015189856040015186606001516121da565b505b6001016114cc565b505050505050505050565b606081806001600160401b038111156115815761158161400e565b6040519080825280602002602001820160405280156115ba57816020015b6115a7613ed5565b81526020019060019003908161159f5790505b5091506000805b8281101561166f57368686838181106115dc576115dc614ea7565b90506020028101906115ee9190614ebd565b90506000611612896116008480614f46565b61160d6020870187614f46565b612a3e565b905080602001516001600160a01b03168160000151608001516001600160a01b03160361164457836001019350611665565b80868585038151811061165957611659614ea7565b60200260200101819052505b50506001016115c1565b50801561167d578083510383525b506116888583612d23565b50509392505050565b6001600054146116b457604051637fa8a98760e01b815260040160405180910390fd5b565b8351835160609182916116c98183614fa5565b6001600160401b038111156116e0576116e061400e565b60405190808252806020026020018201604052801561171957816020015b611706613ed5565b8152602001906001900390816116fe5790505b5092506000805b838110156117b35760008a828151811061173c5761173c614ea7565b6020026020010151905060006117568d6000848d8d612f3d565b905080602001516001600160a01b03168160000151608001516001600160a01b031603611788578360010193506117a9565b80878585038151811061179d5761179d614ea7565b60200260200101819052505b5050600101611720565b5060005b8281101561184d5760008982815181106117d3576117d3614ea7565b6020026020010151905060006117ee8d6001848d6000612f3d565b905080602001516001600160a01b03168160000151608001516001600160a01b03160361182057836001019350611843565b808785888601038151811061183757611837614ea7565b60200260200101819052505b50506001016117b7565b50801561185b578084510384525b50825160000361187e5760405163d5da9a1b60e01b815260040160405180910390fd5b6118888984612d23565b935050509550959350505050565b60006118ac826060015151836101400151612fe2565b81516001600160a01b03166000908152600160205260409020546104d49083906107c0565b8254600090610100900460ff161561190d57811561190557604051630694555d60e21b815260048101869052602401610d94565b5060006105a9565b83546201000090046001600160781b0316801561198a5783156119465760405163ee9e0e6360e01b815260048101879052602401610d94565b8454600160881b90046001600160781b0316811061198a578215611980576040516310fda3e160e01b815260048101879052602401610d94565b60009150506105a9565b50600195945050505050565b336001600160a01b038416036119ab57505050565b60006119d86119b861223f565b61190160f01b600090815260029190915260228581526042822091905290565b90506119e5848284613003565b50505050565b6119f3611691565b6002600055565b60008060008087600001519050611a1a8160a001518260c0015188613154565b611a2e575060009250829150819050611ca9565b602088015160408901516001600160781b03918216911680821180611a51575081155b15611a6f57604051632d02959960e11b815260040160405180910390fd5b8082108015611a8357506080830151600116155b15611aa15760405163a11b63ff60e01b815260040160405180910390fd5b611aaa83611896565b9550611acc8a8a89898760e00151886080015189600001518a6020015161319a565b600086815260026020526040812090611ae990889083908c6118d1565b611afe575060009450849350611ca992505050565b805460ff16611b1a57611b1a8460000151888d60600151611996565b80546001600160781b03620100008204811691600160881b9004168015611c635783600103611b4e57809450809350611b7a565b838114611b7a57611b5f8483614fbd565b9150611b6b8186614fbd565b9450611b778185614fbd565b93505b83611b858684614fa5565b1115611b915781840394505b611b9b8583614fa5565b91506001600160781b0384116001600160781b0383111715611c2457611bd6565b60005b8215611bd057908290069190611bbf565b50919050565b611be9611be38584611bbc565b86611bbc565b80150194859004949384900493909104906001600160781b038083119085111715611c2457634e487b7160e01b600052601160045260246000fd5b82546001600160781b03858116600160881b026001600160881b0391851662010000026001600160881b03199093169290921760011716178355611c9e565b82546001600160781b03858116600160881b026001600160881b0391881662010000026001600160881b031990931692909217600117161783555b509295509093505050505b9450945094915050565b8051825160005b82811015611efa576000848281518110611cd657611cd6614ea7565b60200260200101519050600081600001519050838110611d09576040516321a561b160e21b815260040160405180910390fd5b868181518110611d1b57611d1b614ea7565b6020026020010151602001516001600160781b0316600003611d3e575050611ef2565b6000878281518110611d5257611d52614ea7565b60209081029190910101515160408401519091506000808086602001516001811115611d8057611d80614658565b03611e1a57604084015180518410611dab57604051635fd9fc6760e11b815260040160405180910390fd5b6000818581518110611dbf57611dbf614ea7565b602090810291909101015180516040820151909550935090506004841460030381816005811115611df257611df2614658565b90816005811115611e0557611e05614658565b90525050606088015160409091015250611eab565b606084015180518410611e40576040516330446bef60e11b815260040160405180910390fd5b6000818581518110611e5457611e54614ea7565b602090810291909101015180516040820151909550935090506004841460030381816005811115611e8757611e87614658565b90816005811115611e9a57611e9a614658565b905250506060880151604090910152505b611eb58260031090565b611ed257604051634a75b57b60e11b815260040160405180910390fd5b8015611eeb57611eeb866060015182886080015161327a565b5050505050505b600101611cba565b5060005b81811015612005576000858281518110611f1a57611f1a614ea7565b6020026020010151905080602001516001600160781b0316600003611f3f5750611ffd565b805160608101515160005b81811015611fa657611f7d83606001518281518110611f6b57611f6b614ea7565b60200260200101516000015160031090565b15611f9e5760405160016202297360e61b0319815260040160405180910390fd5b600101611f4a565b505060408101515160005b81811015611ff857611fd283604001518281518110611f6b57611f6b614ea7565b15611ff05760405163a6cfc67360e01b815260040160405180910390fd5b600101611fb1565b505050505b600101611efe565b5050505050565b60a085015160c08601516040805160208082528183019092526000916020820181803683375050506040890151519091506132dd9060005b818110156120fa5760008b60400151828151811061206457612064614ea7565b602002602001015190506000600581111561208157612081614658565b8151600581111561209457612094614658565b036120b2576040516312d3f5a360e01b815260040160405180910390fd5b60006120cc826060015183608001518e8e8c8c60006133ef565b606083015250608081018890528b516101208d01516120f19183918863ffffffff8916565b50600101612044565b50505060608801515134906132dd9060005b818110156121be5760008c60600151828151811061212c5761212c614ea7565b602002602001015190506000612150826060015183608001518f8f8d8d60016133ef565b6060830181905260a08301516080840152905060008251600581111561217857612178614658565b036121a4578581111561219e57604051631a783b8d60e01b815260040160405180910390fd5b80860395505b6121b482338d8a8963ffffffff16565b505060010161210c565b5050506121ca8261297e565b801561155b5761155b3382613439565b60608290506060829050856001600160a01b0316876001600160a01b03167f9d9af8e38d66c62e2c12f0225249fd9d721c54b83f48d9352c97c6cacdcb6f318a88868660405161222d9493929190615016565b60405180910390a35050505050505050565b60007f0000000000000000000000000000000000000000000000000000000000000000461461231057610311604080517f000000000000000000000000000000000000000000000000000000000000000060208201527f0000000000000000000000000000000000000000000000000000000000000000918101919091527f000000000000000000000000000000000000000000000000000000000000000060608201524660808201523060a082015260009060c00160405160208183030381529060405280519060200120905090565b507f000000000000000000000000000000000000000000000000000000000000000090565b61233d6119eb565b6123538661012001358761014001356001613154565b5061235c61348d565b61237a61236d610200880188614f46565b9050876101e00135612fe2565b6000807f00000000000000000000000000000000000000000000000000000000000000009050806080528560a0526060602460c037604060646101203760e06080206101605261026435602081026102a0016001610264350181526020810190508781526080602460208301376101608760a0528660c052600060e05261020435925060005b8381101561244b578060400261028401602081610100376040816101203760208301925060e0608020835260a084019350898452886020850152604081606086013750600101612400565b60206001850102610160206060526102643593505b83811015612491578060400261028401915060a0830192508883528760208401526040826060850137600101612460565b505050505060007f00000000000000000000000000000000000000000000000000000000000000009050806080528260a052606060c460c03760206101046101203760c0608020600052602060002060e052602061026435026102000160018152836020820152606060c4604083013750506084356001600160a01b0381166000908152600160205260408120547f000000000000000000000000000000000000000000000000000000000000000060808190529091506040608460a03760605161010052886101205260a061014461014037816101e0526101806080209350505050602061026435026101800181815233602082015260806040820152610120606082015260a061026435026101e00160a4356084357f9d9af8e38d66c62e2c12f0225249fd9d721c54b83f48d9352c97c6cacdcb6f318385a35050600060605261260681886101600135888a60600160208101906125f19190614ad9565b61260160a08d0160808e01614ad9565b6134d6565b6126628161261a60808a0160608b01614ad9565b6126286102208b018b614f00565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061352692505050565b50505050505050565b80156126c75760006040519050632671a55160e11b815260206004820152600160248201528760448201528660648201528560848201528460a48201528360c48201528260e48201526126c18282610104613570565b50612662565b60028760058111156126db576126db614658565b0361271257816001146127015760405163efcc00b160e01b815260040160405180910390fd5b61270d86868686613669565b612662565b612662868686868661372d565b348160005b81811015612792573685858381811061273f5761273f614ea7565b6040029190910191505080358481111561276c57604051631a783b8d60e01b815260040160405180910390fd5b61278561277f6040840160208501614ad9565b82613439565b9093039250600101612724565b50818611156127b457604051631a783b8d60e01b815260040160405180910390fd5b6127be8587613439565b858211156127d2576127d233878403613439565b505050505050565b6127e48183613814565b81612816578260011461280a5760405163efcc00b160e01b815260040160405180910390fd5b61270d87878787613669565b612662828260028a8a8a8a8a613833565b612830836138b3565b61283a8183613814565b8161284c5761270d878787878761372d565b612662828260038a8a8a8a8a613833565b600080600080600086156128945788945033935061288160c0890160a08a01614ad9565b9250505060e086013560c08701356128b6565b3394508893506128a76020890189614ad9565b92505050604086013560208701355b80156128d557604051636ab37ce760e01b815260040160405180910390fd5b50602086026101e4033560006128ef6102008a018a614f46565b9050905060005b81811015612963573661290d6102008c018c614f46565b8381811061291d5761291d614ea7565b6040029190910191505080358a1561293c5761293981876150b0565b95505b612959878a6129516040860160208701614ad9565b84898f6138d4565b50506001016128f6565b5061297284878786868c6138d4565b50505050505050505050565b604081511461298a5750565b6000612997826020015190565b90506129a3818361390f565b5050565b60008284036129b757508061052c565b82848309156129d15763c63cf08960e01b60005260046000fd5b60006129dd8584614fbd565b93909304949350505050565b6000848614612a3457838303428590038082036000612a08838a614fbd565b612a12838c614fbd565b612a1c9190614fa5565b90508584878303040181151502945050505050610330565b5092949350505050565b612a46613ed5565b831580612a51575081155b15612a6f57604051634c74edb760e11b815260040160405180910390fd5b612a77613ed5565b612ad4878585808060200260200160405190810160405280939291908181526020016000905b82821015612ac957612aba604083028601368190038101906150c7565b81526020019060010190612a9d565b505050505083613933565b805160408051602080890282018101909252878152612b33918a91908a908a90819060009085015b82821015612b2857612b19604083028601368190038101906150c7565b81526020019060010190612afc565b505050505085613ad6565b80516005811115612b4657612b46614658565b8351516005811115612b5a57612b5a614658565b141580612b85575080602001516001600160a01b03168360000151602001516001600160a01b031614155b80612b9c5750806040015183600001516040015114155b15612bba576040516309cfb45560e01b815260040160405180910390fd5b82600001516060015181606001511115612c6857600085856000818110612be357612be3614ea7565b905060400201803603810190612bf991906150c7565b905083600001516060015182606001510389826000015181518110612c2057612c20614ea7565b60200260200101516000015160600151826020015181518110612c4557612c45614ea7565b602090810291909101015160609081019190915284518101519083015250612d03565b600087876000818110612c7d57612c7d614ea7565b905060400201803603810190612c9391906150c7565b905081606001518460000151606001510389826000015181518110612cba57612cba614ea7565b60200260200101516000015160400151826020015181518110612cdf57612cdf614ea7565b60200260200101516060018181525050816060015184600001516060018181525050505b60809081015183516001600160a01b039091169101525095945050505050565b8151606090806001600160401b03811115612d4057612d4061400e565b604051908082528060200260200182016040528015612d69578160200160208202803683370190505b50915060005b81811015612e51576000858281518110612d8b57612d8b614ea7565b6020026020010151905080602001516001600160781b0316600003612db05750612e49565b6001848381518110612dc457612dc4614ea7565b91151560209283029190910190910152805160600151805160005b81811015612e44576000838281518110612dfb57612dfb614ea7565b602002602001015160600151905080600014612e3b576040516314bea84160e31b8152600481018790526024810183905260448101829052606401610d94565b50600101612ddf565b505050505b600101612d6f565b5060408051602080825281830190925234916000919060208201818036833701905050855190915060005b81811015612f0f576000878281518110612e9857612e98614ea7565b60209081029190910101518051909150600081516005811115612ebd57612ebd614658565b03612ef1578581606001511115612ee757604051631a783b8d60e01b815260040160405180910390fd5b8060600151860395505b612f058183602001518460400151886132dd565b5050600101612e7c565b50612f198261297e565b8215612f2957612f293384613439565b612f336001600055565b5050505092915050565b612f45613ed5565b8351600003612f69578460405163375c24c160e01b8152600401610d9491906150f3565b6000856001811115612f7d57612f7d614658565b03612fa45780516001600160a01b038316608090910152612f9f868583613ad6565b612fbd565b612faf868583613933565b336020820152604081018390525b8051606001516000036103305760006020820181905281516080015295945050505050565b808210156129a357604051632335530b60e11b815260040160405180910390fd5b6000806000526000825160208403805182604103600060018211613071576040880151606089015160001a9650821561304f57601b8160ff1c0196506001600160ff1b03811660408a01525b8689528985526020600060808760015afa508385528589526040890152506000515b89148915151695508590506131325760408252604486038051604088038051630b135d3f60e11b84528a82526020600060648901868f5afa9850881561312857630b135d3f60e11b60005114613128578b3b156130d957634f7fb80d60e01b60005260046000fd5b60018760410311156130f657638baa579f60e01b60005260046000fd5b640101000000881a61311757630f801e8560e11b6000528760045260246000fd5b632057875960e21b60005260046000fd5b8486529190925290525b50505050806119e557613143613c67565b634f7fb80d60e01b60005260046000fd5b6000428411806131645750428311155b15613190578115613188576040516337bf561360e11b815260040160405180910390fd5b50600061052c565b5060019392505050565b60018360038111156131ae576131ae614658565b1180156131c45750336001600160a01b03821614155b80156131d95750336001600160a01b03831614155b15613270576080880151511580156131f057508651155b156132065761320181868487613caf565b613270565b600061326482633313157060e01b88338d8c8e60405160240161322d9594939291906152b3565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152613cfb565b905061155b8187613d10565b5050505050505050565b600083600052602060002060208301835160051b81015b808210156132b957815180841160051b93845260209384185260406000209290910190613291565b505083149050806119e5576040516309bde33960e01b815260040160405180910390fd5b6000845160058111156132f2576132f2614658565b0361334057604084015160208501516001600160a01b0316171561332957604051636ab37ce760e01b815260040160405180910390fd5b61333b84608001518560600151613439565b6119e5565b60018451600581111561335557613355614658565b036133975760408401511561337d57604051636ab37ce760e01b815260040160405180910390fd5b61333b8460200151848660800151876060015186866138d4565b6002845160058111156133ac576133ac614658565b036133d05761333b84602001518486608001518760400151886060015187876127da565b6119e58460200151848660800151876040015188606001518787612827565b600086880361340a576134038686896129a7565b905061342e565b61342b61341887878b6129a7565b61342388888b6129a7565b8686866129e9565b90505b979650505050505050565b613442816138b3565b600080600080600085875af19050806134885761345d613c67565b60405163470c7c1d60e01b81526001600160a01b038416600482015260248101839052604401610d94565b505050565b60186101243510610244356102606102643560400201146004356020146102243561024014161616806134d3576040516339f3e3fd60e01b815260040160405180910390fd5b50565b60018360038111156134ea576134ea614658565b1180156135005750336001600160a01b03821614155b80156135155750336001600160a01b03831614155b156120055761200581868487613caf565b600083815260026020526040902061354184826001806118d1565b50805460ff1661355657613556838584611996565b710100000000000000000000000000000100019055505050565b604080517f000000000000000000000000000000000000000000000000000000000000000060ff60a01b17600090815260208690527f000000000000000000000000000000000000000000000000000000000000000083526055600b20919092526001600160a01b03169050600080600080526020600085876000875af1915060005190508161362657613602613c67565b60405163344f54f560e21b81526001600160a01b0384166004820152602401610d94565b6001600160e01b03198116632671a55160e11b146127d257604051630e7ccd9360e11b8152600481018790526001600160a01b0384166024820152604401610d94565b833b61368457632f8aeb3960e11b6000528360045260246000fd5b6040516323b872dd60e01b6000528360045282602452816044526000806064600080895af18061371e573d156136f8576020601f3d01046020830481600302818311156136df57818303600302610200838002858002030401015b5a6020820110156136f4573d6000803e3d6000fd5b5050505b63f486bc8760e01b60005285600452846024528360445282606452600160845260a46000fd5b50604052505060006060525050565b843b61374857632f8aeb3960e11b6000528460045260246000fd5b60405160805160a05160c051637921219560e11b6000528760045286602452856044528460645260a0608452600060a45260008060c46000808d5af1806137f8573d156137d3576020601f3d01046020860481600302818311156137ba57818303600302610200838002858002030401015b5a6020820110156137cf573d6000803e3d6000fd5b5050505b63f486bc8760e01b600052896004528860245287604452866064528560845260a46000fd5b5060809290925260a05260c05260405250506000606052505050565b6000613821836020015190565b9050818114613488576134888361297e565b6000602088510361386e5750604080885260208089018a9052632671a55160e11b91890191909152604488015260016064880181905261387d565b50606487018051600101908190525b603c60c082028901038781528660208201528560408201528460608201528360808201528260a082015250505050505050505050565b806000036134d35760405163246cf94560e21b815260040160405180910390fd5b6138dd836138b3565b6138e78183613814565b816138fd576138f886868686613d6a565b6127d2565b6127d28282600189898960008a613833565b6064810151604082019060c00260440161392a848383613570565b50506020905250565b61395f565b637fda727960e01b60005260046000fd5b634e487b7160e01b600052601160045260246000fd5b602082018051518451811061397657613976613938565b602081026020860101516060815101516020845101518151811061399c5761399c613938565b602081026020830101516000806020860151156139c3575050606081018051600090915280155b885183518152602084015160208201526040840151604082015260a084015160808201526060812060208c51028c015b808b1015613a9a5760208b019a508a515199508d518a10613a1657613a16613938565b60208a0260208f01015198506020890151156139f357606089510151975060208b510151965087518710613a4c57613a4c613938565b602087026020890101519550606086018051860181511587821060011b1786179550809650506000815250606086208214608084015160a08801511416613a9557613a95613938565b6139f3565b50506060018290528015613ac95760018103613ac15763246cf94560e21b60005260046000fd5b613ac9613949565b5050505050505050505050565b6020820180515184518110613aed57613aed613938565b602081026020860101518051604081015160208551015181518110613b1457613b14613938565b60208102602083010151600080602087015115613b3b575050606081018051600090915280155b8951835181526020840151602082015260408401516040820152865160208c015261012087015160408c015260608120905060208c51028c015b808b1015613c295760208b019a508a515199508d518a10613b9857613b98613938565b60208a0260208f0101519850602089015115613b7557885197506040880151965060208b510151955086518610613bd157613bd1613938565b602086026020880101519450606085018051850181511586821060011b178517945080955050600081525060608520821460408d01516101208a01511460208e01518a51141616613c2457613c24613938565b613b75565b50508160608b5101528015613c595760018103613c515763246cf94560e21b60005260046000fd5b613c59613949565b505050505050505050505050565b3d156116b4576020601f3d01046020604051048160030281831115613c9a57818303600302610200838002858002030401015b5a602082011015613488573d6000803e3d6000fd5b604051602481018490523360448201526001600160a01b038316606482015260848101829052600090613cef9086906303874c7760e21b9060a40161322d565b90506120058185613d10565b6000806000835160208501865afa9392505050565b81613d3957613d1d613c67565b604051633ed4053f60e21b815260048101829052602401610d94565b613d496303874c7760e21b613e73565b156129a357604051633ed4053f60e21b815260048101829052602401610d94565b6040516323b872dd60e01b600052836004528260245281604452602060006064600080895af1803d15601f3d116001600051141617163d15158116613e635780873b151516613e635780613e4e5781613e2d573d15613e07576020601f3d0104602084048160030281831115613dee57818303600302610200838002858002030401015b5a602082011015613e03573d6000803e3d6000fd5b5050505b63f486bc8760e01b60005286600452856024528460445260006064528360845260a46000fd5b639889192360e01b6000528660045285602452846044528360645260846000fd5b632f8aeb3960e11b6000528660045260246000fd5b5050604052505060006060525050565b60008060203d03613e895760206000803e506000515b6001600160e01b031990811692169190911415919050565b6040518060a00160405280613eb4613f18565b81526000602082018190526040820152606080820181905260809091015290565b60408051610100810182526000606082018181526080830182905260a0830182905260c0830182905260e083018290528252602082018190529181019190915290565b60405180610160016040528060006001600160a01b0316815260200160006001600160a01b03168152602001606081526020016060815260200160006003811115613f6557613f65614658565b815260006020820181905260408201819052606082018190526080820181905260a0820181905260c09091015290565b6000815180845260005b81811015613fbb57602081850181015186830182015201613f9f565b81811115613fcd576000602083870101525b50601f01601f19169290920160200192915050565b60208152600061052c6020830184613f95565b60006020828403121561400757600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b60405160a081016001600160401b03811182821017156140465761404661400e565b60405290565b60405161016081016001600160401b03811182821017156140465761404661400e565b604051601f8201601f191681016001600160401b03811182821017156140975761409761400e565b604052919050565b60006001600160401b038211156140b8576140b861400e565b5060051b60200190565b6001600160a01b03811681146134d357600080fd5b80356140e2816140c2565b919050565b8035600681106140e257600080fd5b600060a0828403121561410857600080fd5b614110614024565b905061411b826140e7565b8152602082013561412b816140c2565b8060208301525060408201356040820152606082013560608201526080820135608082015292915050565b600082601f83011261416757600080fd5b8135602061417c6141778361409f565b61406f565b82815260a0928302850182019282820191908785111561419b57600080fd5b8387015b858110156141be576141b189826140f6565b845292840192810161419f565b5090979650505050505050565b600060c082840312156141dd57600080fd5b60405160c081018181106001600160401b03821117156141ff576141ff61400e565b60405290508061420e836140e7565b8152602083013561421e816140c2565b8060208301525060408301356040820152606083013560608201526080830135608082015260a0830135614251816140c2565b60a0919091015292915050565b600082601f83011261426f57600080fd5b8135602061427f6141778361409f565b82815260c0928302850182019282820191908785111561429e57600080fd5b8387015b858110156141be576142b489826141cb565b84529284019281016142a2565b8035600481106140e257600080fd5b600061016082840312156142e357600080fd5b6142eb61404c565b90506142f6826140d7565b8152614304602083016140d7565b602082015260408201356001600160401b038082111561432357600080fd5b61432f85838601614156565b6040840152606084013591508082111561434857600080fd5b506143558482850161425e565b606083015250614367608083016142c1565b608082015260a082013560a082015260c082013560c082015260e082013560e082015261010080830135818301525061012080830135818301525061014080830135818301525092915050565b80356001600160781b03811681146140e257600080fd5b600082601f8301126143dc57600080fd5b81356001600160401b038111156143f5576143f561400e565b614408601f8201601f191660200161406f565b81815284602083860101111561441d57600080fd5b816020850160208301376000918101602001919091529392505050565b600060a0828403121561444c57600080fd5b614454614024565b905081356001600160401b038082111561446d57600080fd5b614479858386016142d0565b8352614487602085016143b4565b6020840152614498604085016143b4565b604084015260608401359150808211156144b157600080fd5b6144bd858386016143cb565b606084015260808401359150808211156144d657600080fd5b506144e3848285016143cb565b60808301525092915050565b600082601f83011261450057600080fd5b813560206145106141778361409f565b82815260059290921b8401810191818101908684111561452f57600080fd5b8286015b8481101561456e5780356001600160401b038111156145525760008081fd5b6145608986838b010161443a565b845250918301918301614533565b509695505050505050565b60008083601f84011261458b57600080fd5b5081356001600160401b038111156145a257600080fd5b6020830191508360208260051b85010111156145bd57600080fd5b9250929050565b6000806000806000606086880312156145dc57600080fd5b85356001600160401b03808211156145f357600080fd5b6145ff89838a016144ef565b9650602088013591508082111561461557600080fd5b61462189838a01614579565b9096509450604088013591508082111561463a57600080fd5b5061464788828901614579565b969995985093965092949392505050565b634e487b7160e01b600052602160045260246000fd5b6006811061467e5761467e614658565b9052565b61468d82825161466e565b6020818101516001600160a01b0390811691840191909152604080830151908401526060808301519084015260809182015116910152565b600081518084526020808501945080840160005b8381101561471b5781516146ee888251614682565b808401516001600160a01b031660a08901526040015160c088015260e090960195908201906001016146d9565b509495945050505050565b60208152600061052c60208301846146c5565b60006020828403121561474b57600080fd5b81356001600160401b0381111561476157600080fd5b8201610160818503121561052c57600080fd5b60008060008060008060008060008060e08b8d03121561479357600080fd5b8a356001600160401b03808211156147aa57600080fd5b6147b68e838f016144ef565b9b5060208d01359150808211156147cc57600080fd5b6147d88e838f01614579565b909b50995060408d01359150808211156147f157600080fd5b6147fd8e838f01614579565b909950975060608d013591508082111561481657600080fd5b506148238d828e01614579565b90965094505060808b0135925061483c60a08c016140d7565b915060c08b013590509295989b9194979a5092959850565b604080825283519082018190526000906020906060840190828701845b8281101561488f578151151584529284019290840190600101614871565b505050838103828501526148a381866146c5565b9695505050505050565b600080602083850312156148c057600080fd5b82356001600160401b038111156148d657600080fd5b6148e285828601614579565b90969095509350505050565b6000806000806040858703121561490457600080fd5b84356001600160401b038082111561491b57600080fd5b61492788838901614579565b9096509450602087013591508082111561494057600080fd5b5061494d87828801614579565b95989497509550505050565b6000806040838503121561496c57600080fd5b82356001600160401b0381111561498257600080fd5b83016040818603121561499457600080fd5b946020939093013593505050565b6000806000806000608086880312156149ba57600080fd5b85356001600160401b03808211156149d157600080fd5b9087019060a0828a0312156149e557600080fd5b909550602087013590808211156149fb57600080fd5b50614a0888828901614579565b909550935050604086013591506060860135614a23816140c2565b809150509295509295909350565b60008060008060008060008060a0898b031215614a4d57600080fd5b88356001600160401b0380821115614a6457600080fd5b614a708c838d01614579565b909a50985060208b0135915080821115614a8957600080fd5b614a958c838d01614579565b909850965060408b0135915080821115614aae57600080fd5b50614abb8b828c01614579565b999c989b509699959896976060870135966080013595509350505050565b600060208284031215614aeb57600080fd5b813561052c816140c2565b606081526000614b096060830186613f95565b6020830194909452506001600160a01b0391909116604090910152919050565b600060208284031215614b3b57600080fd5b81356001600160401b03811115614b5157600080fd5b8201610240818503121561052c57600080fd5b6000614b726141778461409f565b83815260208082019190600586811b860136811115614b9057600080fd5b865b81811015614c8b5780356001600160401b0380821115614bb25760008081fd5b818a01915060a08236031215614bc85760008081fd5b614bd0614024565b823581528683013560028110614be65760008081fd5b81880152604083810135908201526060808401359082015260808084013583811115614c125760008081fd5b939093019236601f850112614c2957600092508283fd5b83359250614c396141778461409f565b83815292871b84018801928881019036851115614c565760008081fd5b948901945b84861015614c7457853582529489019490890190614c5b565b918301919091525088525050948301948301614b92565b5092979650505050505050565b6000808335601e19843603018112614caf57600080fd5b8301803591506001600160401b03821115614cc957600080fd5b602001915060a0810236038213156145bd57600080fd5b600060a08284031215614cf257600080fd5b61052c83836140f6565b6000808335601e19843603018112614d1357600080fd5b8301803591506001600160401b03821115614d2d57600080fd5b602001915060c0810236038213156145bd57600080fd5b600060c08284031215614d5657600080fd5b61052c83836141cb565b600060208284031215614d7257600080fd5b61052c826142c1565b60006104d4368361443a565b600060408284031215614d9957600080fd5b604051604081018181106001600160401b0382111715614dbb57614dbb61400e565b604052823581526020928301359281019290925250919050565b6000614de36141778461409f565b80848252602080830192508560051b850136811115614e0157600080fd5b855b81811015614e9b5780356001600160401b03811115614e225760008081fd5b870136601f820112614e345760008081fd5b8035614e426141778261409f565b81815260069190911b82018501908581019036831115614e625760008081fd5b928601925b82841015614e8b57614e793685614d87565b82528682019150604084019350614e67565b8852505050938201938201614e03565b50919695505050505050565b634e487b7160e01b600052603260045260246000fd5b60008235603e19833603018112614ed357600080fd5b9190910192915050565b6000823561015e19833603018112614ed357600080fd5b60006104d436836142d0565b6000808335601e19843603018112614f1757600080fd5b8301803591506001600160401b03821115614f3157600080fd5b6020019150368190038213156145bd57600080fd5b6000808335601e19843603018112614f5d57600080fd5b8301803591506001600160401b03821115614f7757600080fd5b6020019150600681901b36038213156145bd57600080fd5b634e487b7160e01b600052601160045260246000fd5b60008219821115614fb857614fb8614f8f565b500190565b6000816000190483118215151615614fd757614fd7614f8f565b500290565b600081518084526020808501945080840160005b8381101561471b57615003878351614682565b60a0969096019590820190600101614ff0565b60006080808301878452602060018060a01b03808916828701526040848188015283895180865260a089019150848b01955060005b8181101561508c57865161506084825161466e565b80870151861684880152848101518585015260609081015190840152958501959187019160010161504b565b505087810360608901526150a0818a614fdc565b9c9b505050505050505050505050565b6000828210156150c2576150c2614f8f565b500390565b6000604082840312156150d957600080fd5b61052c8383614d87565b6002811061467e5761467e614658565b602081016104d482846150e3565b600081518084526020808501945080840160005b8381101561471b57815161512a88825161466e565b838101516001600160a01b03168885015260408082015190890152606080820151908901526080908101519088015260a09096019590820190600101615115565b600081518084526020808501945080840160005b8381101561471b57815161519488825161466e565b808401516001600160a01b0390811689860152604080830151908a0152606080830151908a0152608080830151908a015260a091820151169088015260c0909601959082019060010161517f565b6004811061467e5761467e614658565b600081518084526020808501945080840160005b8381101561471b57815187529582019590820190600101615206565b600081518084526020808501808196508360051b8101915082860160005b858110156152a6578284038952815160a08151865286820151615265888801826150e3565b506040828101519087015260608083015190870152608091820151918601819052615292818701836151f2565b9a87019a9550505090840190600101615240565b5091979650505050505050565b85815260018060a01b038516602082015260a060408201526000610140855160a0808501526152ed82850182516001600160a01b03169052565b6020810151610160615309818701836001600160a01b03169052565b6040830151915080610180870152506153266102a0860182615101565b9050606082015161013f19868303016101a0870152615345828261516b565b915050608082015161535b6101c08701826151e2565b5060a08201516101e086015260c082015161020086015260e082015161022086015261010080830151610240870152610120808401516102608801528484015161028088015260208a015194506153bd60c08801866001600160781b03169052565b60408a01516001600160781b031660e088015260608a0151878403609f19908101848a015290955093506153f18386613f95565b945060808a01519250838786030181880152505061540f8382613f95565b92505050828103606084015261542581866151f2565b905082810360808401526154398185615222565b9897505050505050505056fea2646970667358221220d9ec6bf53c7c4dd207e9b7af873aae1b86f9ebf0a16709b20f4f94de3560378664736f6c634300080e0033000000000000000000000000c8ddac143e4da8337ffdea513ba27bf1d0657518
Deployed Bytecode
0x6080604052600436106100e85760003560e01c8063a81744041161008a578063f07ec37311610059578063f07ec37314610290578063f47b7740146102b0578063fb0f3ee1146102d4578063fd9f1e10146102e757600080fd5b8063a817440414610244578063b3a34c4c14610257578063e7acab241461026a578063ed98a5741461027d57600080fd5b80635b34b966116100c65780635b34b966146101b057806379df72bd146101d357806387201b41146101f3578063881477321461021457600080fd5b806306fdde03146100ed57806346423aa71461011857806355944a4214610190575b600080fd5b3480156100f957600080fd5b50610102610307565b60405161010f9190613fe2565b60405180910390f35b34801561012457600080fd5b5061016e610133366004613ff5565b60009081526002602052604090205460ff808216926101008304909116916001600160781b03620100008204811692600160881b9092041690565b604080519415158552921515602085015291830152606082015260800161010f565b6101a361019e3660046145c4565b610316565b60405161010f9190614726565b3480156101bc57600080fd5b506101c5610339565b60405190815260200161010f565b3480156101df57600080fd5b506101c56101ee366004614739565b610343565b610206610201366004614774565b6104da565b60405161010f929190614854565b34801561022057600080fd5b5061023461022f3660046148ad565b610520565b604051901515815260200161010f565b6101a36102523660046148ee565b610533565b610234610265366004614959565b6105b1565b6102346102783660046149a2565b610623565b61020661028b366004614a31565b610657565b34801561029c57600080fd5b506101c56102ab366004614ad9565b6106e1565b3480156102bc57600080fd5b506102c56106ff565b60405161010f93929190614af6565b6102346102e2366004614b29565b610717565b3480156102f357600080fd5b506102346103023660046148ad565b610722565b606061031161072e565b905090565b606061032d866103268688614b64565b8585610746565b90505b95945050505050565b6000610311610763565b6040805161016081019091526000906104d490806103646020860186614ad9565b6001600160a01b031681526020018460200160208101906103859190614ad9565b6001600160a01b031681526020016103a06040860186614c98565b808060200260200160405190810160405280939291908181526020016000905b828210156103ec576103dd60a08302860136819003810190614ce0565b815260200190600101906103c0565b50505091835250506020016104046060860186614cfc565b808060200260200160405190810160405280939291908181526020016000905b828210156104505761044160c08302860136819003810190614d44565b81526020019060010190610424565b505050918352505060200161046b60a0860160808701614d60565b600381111561047c5761047c614658565b81526020018460a0013581526020018460c0013581526020018460e001358152602001846101000135815260200184610120013581526020018480606001906104c59190614cfc565b909152506101408401356107c0565b92915050565b60608061050d8c6104eb8c8e614b64565b8b8b8b8b8b6001600160a01b038c1615610505578b610507565b335b8b610906565b915091509a509a98505050505050505050565b600061052c8383610948565b9392505050565b60606105a66105428686610aad565b604080516000808252602082019092529061059e565b61058b6040805160a081019091526000808252602082019081526020016000815260200160008152602001606081525090565b8152602001906001900390816105585790505b508585610746565b90505b949350505050565b600061052c6105bf84610b68565b604080516000808252602082019092529061061b565b6106086040805160a081019091526000808252602082019081526020016000815260200160008152602001606081525090565b8152602001906001900390816105d55790505b508433610c13565b600061032d61063187614d7b565b61063b8688614b64565b856001600160a01b038616156106515785610c13565b33610c13565b6060806106d06106678b8b610aad565b60408051600080825260208201909252906106c3565b6106b06040805160a081019091526000808252602082019081526020016000815260200160008152602001606081525090565b81526020019060019003908161067d5790505b508a8a8a8a8a338b610906565b915091509850989650505050505050565b6001600160a01b0381166000908152600160205260408120546104d4565b606060008061070c610d00565b925092509250909192565b60006104d482610d61565b600061052c8383611021565b6060602080526707536561706f727460475260606020f35b60606107588585600188516000611227565b6105a6858484611566565b600061076d611691565b503360008181526001602081815260409283902080549092019182905591518181529092917f721c20121297512b72821b97f5326877ea8ecf4bb9948fea5bfcb6453074d37f910160405180910390a290565b610140820151604080519084015180516000939284927fa66999307ad1bb4fde44d13a5d710bd7718e0c87c1eef68a571629fbf5b93d0292602090910190845b8181101561082d578251601f1901805186825260c082208652905260209384019390920191600101610800565b506020810260405120945050505060007f42d81c6929ffdc4eb27a0808e40e82516ad42296c166065de7f812492304ff6e9150604051602060608901510160005b8681101561089b578151601f1901805186825260e08220855290526020928301929091019060010161086e565b505060408051602087029020601f198a0180517ffa445660b7e21515a59617fcd68910b487aa5808b8abda3d78bc85df364b2c2f8252928b01805197815260608c018051938152610140909c019a8b5261018082209390915295909552939097525050925250919050565b6060806109178b8b60008688611227565b6109368b6109258a8c614dd5565b61092f898b614dd5565b88886116b6565b909c909b509950505050505050505050565b6000610952611691565b6000808084815b81811015610a9f573688888381811061097457610974614ea7565b90506020028101906109869190614ebd565b9050366109938280614edd565b90506109a26020820182614ad9565b94506109b56109b082614ef4565b611896565b600081815260026020526040812098509096506109d7908790899060016118d1565b50865460ff16610a9557610a2d85876109f36020860186614f00565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061199692505050565b865460ff19166001178755610a486040820160208301614ad9565b6001600160a01b0316856001600160a01b03167ffde361574a066b44b3b5fe98a87108b7565e327327954c4faeea56a4e6491a0a88604051610a8c91815260200190565b60405180910390a35b5050600101610959565b506001979650505050505050565b606081806001600160401b03811115610ac857610ac861400e565b604051908082528060200260200182016040528015610b0157816020015b610aee613ea1565b815260200190600190039081610ae65790505b50915060005b81811015610b6057610b3b858583818110610b2457610b24614ea7565b9050602002810190610b369190614ebd565b610b68565b838281518110610b4d57610b4d614ea7565b6020908102919091010152600101610b07565b505092915050565b610b70613ea1565b6040805160a0810190915280610b868480614edd565b610b8f90614ef4565b815260200160016001600160781b0316815260200160016001600160781b03168152602001838060200190610bc49190614f00565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201829052509385525050604080516020818101909252928352909201525092915050565b6000610c1d6119eb565b60606000806000610c3189896001876119fa565b604080516001808252818301909252939650919450925060009190816020015b610c59613ea1565b815260200190600190039081610c515790505090508981600081518110610c8257610c82614ea7565b6020026020010181905250610c97818a611cb3565b600081600081518110610cac57610cac614ea7565b6020026020010151600001519050610cc78185858c8c61200c565b610ce585826000015183602001518b856040015186606001516121da565b610cef6001600055565b5060019a9950505050505050505050565b6060600080610d0d61223f565b6040805160038082528183019092529193507f000000000000000000000000c8ddac143e4da8337ffdea513ba27bf1d06575189250602082018180368337505062312e3160e81b6020830152509391925090565b600061012435600281901c90600316600182113415811480610d9d57604051630a61be9f60e41b81523460048201526024015b60405180910390fd5b5060008060008060038711915060a082026024013593506002871460028811600289030201905060018101820260028615028801039250610de2898783888888612335565b506101c46020820201356000856005811115610e0057610e00614658565b03610ea35760208901803590610e16908b614ad9565b6001600160a01b03161715610e3e57604051636ab37ce760e01b815260040160405180910390fd5b610e7383610e5260c08c0160a08d01614ad9565b610e6260808d0160608e01614ad9565b338d60c001358e60e001358761266b565b610e9e60408a0135610e8b60808c0160608d01614ad9565b610e996102008d018d614f46565b61271f565b611008565b6040805160208082528183019092526000916020820181803683370190505090506002886005811115610ed857610ed8614658565b03610f1757610f12610ef060c08c0160a08d01614ad9565b610f0060808d0160608e01614ad9565b338d60c001358e60e0013587876127da565b610fe2565b6003886005811115610f2b57610f2b614658565b03610f6557610f12610f4360c08c0160a08d01614ad9565b610f5360808d0160608e01614ad9565b338d60c001358e60e001358787612827565b6004886005811115610f7957610f79614658565b03610fb057610f12610f8e60208c018c614ad9565b33610f9f60808e0160608f01614ad9565b8d602001358e6040013587876127da565b610fe2610fc060208c018c614ad9565b33610fd160808e0160608f01614ad9565b8d602001358e604001358787612827565b610ffd610ff560808c0160608d01614ad9565b8b858461285d565b6110068161297e565b505b6110126001600055565b50600198975050505050505050565b600061102b611691565b6000808084815b81811015610a9f573688888381811061104d5761104d614ea7565b905060200281019061105f9190614edd565b905061106e6020820182614ad9565b94506110806040820160208301614ad9565b9350336001600160a01b038616148015906110a45750336001600160a01b03851614155b156110c25760405163203b1cdd60e21b815260040160405180910390fd5b60006111b1604051806101600160405280886001600160a01b03168152602001876001600160a01b031681526020018480604001906111019190614c98565b808060200260200160405190810160405280939291908181526020016000905b8282101561114d5761113e60a08302860136819003810190614ce0565b81526020019060010190611121565b50505091835250506020016111656060860186614cfc565b808060200260200160405190810160405280939291908181526020016000905b82821015610450576111a260c08302860136819003810190614d44565b81526020019060010190611185565b60008181526002602052604090819020805461ffff191661010017815590519098509091506001600160a01b0380871691908816907f6bacc01dbe442496068f7d234edd811f1a5f833243e0aec824f86ab861f3c90d906112159085815260200190565b60405180910390a35050600101611032565b61122f6119eb565b84516000816001600160401b0381111561124b5761124b61400e565b604051908082528060200260200182016040528015611274578160200160208202803683370190505b506000808252909150601d6045823560e01c061160011b905b8381101561149d5760008982815181106112a9576112a9614ea7565b60200260200101519050866000036112ce576000602090910152600181018352611495565b60008060006112df848d8d8a6119fa565b92509250925060018501875281600003611306575050600060209092019190915250611495565b8287868151811061131957611319614ea7565b6020908102919091010152835160a081015160c08201516040909201518051600019909d019c91929160005b818110156113e157600083828151811061136157611361614ea7565b602002602001015190508051158c179b506000611383898984608001516129a7565b905081608001518260600151036113a057606082018190526113b5565b6113af898984606001516129a7565b60608301525b6080820181905260608201516113cf9082898960006129e9565b60609092019190915250600101611345565b50875160600151805160005b8181101561148957600083828151811061140957611409614ea7565b6020026020010151905060006114248b8b84608001516129a7565b905081608001518260600151036114415760608201819052611456565b6114508b8b84606001516129a7565b60608301525b60808201819052606082015161147090828b8b60016129e9565b60608301525060a08101516080909101526001016113ed565b50505050505050505050505b60010161128d565b50806003036114bf576040516312d3f5a360e01b815260040160405180910390fd5b6114c98888611cb3565b60005b8381101561155b576000801b8382815181106114ea576114ea614ea7565b6020026020010151031561155357600089828151811061150c5761150c614ea7565b602002602001015160000151905061155184838151811061152f5761152f614ea7565b60200260200101518260000151836020015189856040015186606001516121da565b505b6001016114cc565b505050505050505050565b606081806001600160401b038111156115815761158161400e565b6040519080825280602002602001820160405280156115ba57816020015b6115a7613ed5565b81526020019060019003908161159f5790505b5091506000805b8281101561166f57368686838181106115dc576115dc614ea7565b90506020028101906115ee9190614ebd565b90506000611612896116008480614f46565b61160d6020870187614f46565b612a3e565b905080602001516001600160a01b03168160000151608001516001600160a01b03160361164457836001019350611665565b80868585038151811061165957611659614ea7565b60200260200101819052505b50506001016115c1565b50801561167d578083510383525b506116888583612d23565b50509392505050565b6001600054146116b457604051637fa8a98760e01b815260040160405180910390fd5b565b8351835160609182916116c98183614fa5565b6001600160401b038111156116e0576116e061400e565b60405190808252806020026020018201604052801561171957816020015b611706613ed5565b8152602001906001900390816116fe5790505b5092506000805b838110156117b35760008a828151811061173c5761173c614ea7565b6020026020010151905060006117568d6000848d8d612f3d565b905080602001516001600160a01b03168160000151608001516001600160a01b031603611788578360010193506117a9565b80878585038151811061179d5761179d614ea7565b60200260200101819052505b5050600101611720565b5060005b8281101561184d5760008982815181106117d3576117d3614ea7565b6020026020010151905060006117ee8d6001848d6000612f3d565b905080602001516001600160a01b03168160000151608001516001600160a01b03160361182057836001019350611843565b808785888601038151811061183757611837614ea7565b60200260200101819052505b50506001016117b7565b50801561185b578084510384525b50825160000361187e5760405163d5da9a1b60e01b815260040160405180910390fd5b6118888984612d23565b935050509550959350505050565b60006118ac826060015151836101400151612fe2565b81516001600160a01b03166000908152600160205260409020546104d49083906107c0565b8254600090610100900460ff161561190d57811561190557604051630694555d60e21b815260048101869052602401610d94565b5060006105a9565b83546201000090046001600160781b0316801561198a5783156119465760405163ee9e0e6360e01b815260048101879052602401610d94565b8454600160881b90046001600160781b0316811061198a578215611980576040516310fda3e160e01b815260048101879052602401610d94565b60009150506105a9565b50600195945050505050565b336001600160a01b038416036119ab57505050565b60006119d86119b861223f565b61190160f01b600090815260029190915260228581526042822091905290565b90506119e5848284613003565b50505050565b6119f3611691565b6002600055565b60008060008087600001519050611a1a8160a001518260c0015188613154565b611a2e575060009250829150819050611ca9565b602088015160408901516001600160781b03918216911680821180611a51575081155b15611a6f57604051632d02959960e11b815260040160405180910390fd5b8082108015611a8357506080830151600116155b15611aa15760405163a11b63ff60e01b815260040160405180910390fd5b611aaa83611896565b9550611acc8a8a89898760e00151886080015189600001518a6020015161319a565b600086815260026020526040812090611ae990889083908c6118d1565b611afe575060009450849350611ca992505050565b805460ff16611b1a57611b1a8460000151888d60600151611996565b80546001600160781b03620100008204811691600160881b9004168015611c635783600103611b4e57809450809350611b7a565b838114611b7a57611b5f8483614fbd565b9150611b6b8186614fbd565b9450611b778185614fbd565b93505b83611b858684614fa5565b1115611b915781840394505b611b9b8583614fa5565b91506001600160781b0384116001600160781b0383111715611c2457611bd6565b60005b8215611bd057908290069190611bbf565b50919050565b611be9611be38584611bbc565b86611bbc565b80150194859004949384900493909104906001600160781b038083119085111715611c2457634e487b7160e01b600052601160045260246000fd5b82546001600160781b03858116600160881b026001600160881b0391851662010000026001600160881b03199093169290921760011716178355611c9e565b82546001600160781b03858116600160881b026001600160881b0391881662010000026001600160881b031990931692909217600117161783555b509295509093505050505b9450945094915050565b8051825160005b82811015611efa576000848281518110611cd657611cd6614ea7565b60200260200101519050600081600001519050838110611d09576040516321a561b160e21b815260040160405180910390fd5b868181518110611d1b57611d1b614ea7565b6020026020010151602001516001600160781b0316600003611d3e575050611ef2565b6000878281518110611d5257611d52614ea7565b60209081029190910101515160408401519091506000808086602001516001811115611d8057611d80614658565b03611e1a57604084015180518410611dab57604051635fd9fc6760e11b815260040160405180910390fd5b6000818581518110611dbf57611dbf614ea7565b602090810291909101015180516040820151909550935090506004841460030381816005811115611df257611df2614658565b90816005811115611e0557611e05614658565b90525050606088015160409091015250611eab565b606084015180518410611e40576040516330446bef60e11b815260040160405180910390fd5b6000818581518110611e5457611e54614ea7565b602090810291909101015180516040820151909550935090506004841460030381816005811115611e8757611e87614658565b90816005811115611e9a57611e9a614658565b905250506060880151604090910152505b611eb58260031090565b611ed257604051634a75b57b60e11b815260040160405180910390fd5b8015611eeb57611eeb866060015182886080015161327a565b5050505050505b600101611cba565b5060005b81811015612005576000858281518110611f1a57611f1a614ea7565b6020026020010151905080602001516001600160781b0316600003611f3f5750611ffd565b805160608101515160005b81811015611fa657611f7d83606001518281518110611f6b57611f6b614ea7565b60200260200101516000015160031090565b15611f9e5760405160016202297360e61b0319815260040160405180910390fd5b600101611f4a565b505060408101515160005b81811015611ff857611fd283604001518281518110611f6b57611f6b614ea7565b15611ff05760405163a6cfc67360e01b815260040160405180910390fd5b600101611fb1565b505050505b600101611efe565b5050505050565b60a085015160c08601516040805160208082528183019092526000916020820181803683375050506040890151519091506132dd9060005b818110156120fa5760008b60400151828151811061206457612064614ea7565b602002602001015190506000600581111561208157612081614658565b8151600581111561209457612094614658565b036120b2576040516312d3f5a360e01b815260040160405180910390fd5b60006120cc826060015183608001518e8e8c8c60006133ef565b606083015250608081018890528b516101208d01516120f19183918863ffffffff8916565b50600101612044565b50505060608801515134906132dd9060005b818110156121be5760008c60600151828151811061212c5761212c614ea7565b602002602001015190506000612150826060015183608001518f8f8d8d60016133ef565b6060830181905260a08301516080840152905060008251600581111561217857612178614658565b036121a4578581111561219e57604051631a783b8d60e01b815260040160405180910390fd5b80860395505b6121b482338d8a8963ffffffff16565b505060010161210c565b5050506121ca8261297e565b801561155b5761155b3382613439565b60608290506060829050856001600160a01b0316876001600160a01b03167f9d9af8e38d66c62e2c12f0225249fd9d721c54b83f48d9352c97c6cacdcb6f318a88868660405161222d9493929190615016565b60405180910390a35050505050505050565b60007f000000000000000000000000000000000000000000000000000000000000a4ba461461231057610311604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f60208201527f32b5c112df393a49218d7552f96b2eeb829dfb4272f4f24eef510a586b85feef918101919091527f722c0e0c80487266e8c6a45e3a1a803aab23378a9c32e6ebe029d4fad7bfc96560608201524660808201523060a082015260009060c00160405160208183030381529060405280519060200120905090565b507f1272de176ba30276e3297320d24a6075a4a6a0e56d4cb1ad8a6e509cd821929490565b61233d6119eb565b6123538661012001358761014001356001613154565b5061235c61348d565b61237a61236d610200880188614f46565b9050876101e00135612fe2565b6000807f42d81c6929ffdc4eb27a0808e40e82516ad42296c166065de7f812492304ff6e9050806080528560a0526060602460c037604060646101203760e06080206101605261026435602081026102a0016001610264350181526020810190508781526080602460208301376101608760a0528660c052600060e05261020435925060005b8381101561244b578060400261028401602081610100376040816101203760208301925060e0608020835260a084019350898452886020850152604081606086013750600101612400565b60206001850102610160206060526102643593505b83811015612491578060400261028401915060a0830192508883528760208401526040826060850137600101612460565b505050505060007fa66999307ad1bb4fde44d13a5d710bd7718e0c87c1eef68a571629fbf5b93d029050806080528260a052606060c460c03760206101046101203760c0608020600052602060002060e052602061026435026102000160018152836020820152606060c4604083013750506084356001600160a01b0381166000908152600160205260408120547ffa445660b7e21515a59617fcd68910b487aa5808b8abda3d78bc85df364b2c2f60808190529091506040608460a03760605161010052886101205260a061014461014037816101e0526101806080209350505050602061026435026101800181815233602082015260806040820152610120606082015260a061026435026101e00160a4356084357f9d9af8e38d66c62e2c12f0225249fd9d721c54b83f48d9352c97c6cacdcb6f318385a35050600060605261260681886101600135888a60600160208101906125f19190614ad9565b61260160a08d0160808e01614ad9565b6134d6565b6126628161261a60808a0160608b01614ad9565b6126286102208b018b614f00565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061352692505050565b50505050505050565b80156126c75760006040519050632671a55160e11b815260206004820152600160248201528760448201528660648201528560848201528460a48201528360c48201528260e48201526126c18282610104613570565b50612662565b60028760058111156126db576126db614658565b0361271257816001146127015760405163efcc00b160e01b815260040160405180910390fd5b61270d86868686613669565b612662565b612662868686868661372d565b348160005b81811015612792573685858381811061273f5761273f614ea7565b6040029190910191505080358481111561276c57604051631a783b8d60e01b815260040160405180910390fd5b61278561277f6040840160208501614ad9565b82613439565b9093039250600101612724565b50818611156127b457604051631a783b8d60e01b815260040160405180910390fd5b6127be8587613439565b858211156127d2576127d233878403613439565b505050505050565b6127e48183613814565b81612816578260011461280a5760405163efcc00b160e01b815260040160405180910390fd5b61270d87878787613669565b612662828260028a8a8a8a8a613833565b612830836138b3565b61283a8183613814565b8161284c5761270d878787878761372d565b612662828260038a8a8a8a8a613833565b600080600080600086156128945788945033935061288160c0890160a08a01614ad9565b9250505060e086013560c08701356128b6565b3394508893506128a76020890189614ad9565b92505050604086013560208701355b80156128d557604051636ab37ce760e01b815260040160405180910390fd5b50602086026101e4033560006128ef6102008a018a614f46565b9050905060005b81811015612963573661290d6102008c018c614f46565b8381811061291d5761291d614ea7565b6040029190910191505080358a1561293c5761293981876150b0565b95505b612959878a6129516040860160208701614ad9565b84898f6138d4565b50506001016128f6565b5061297284878786868c6138d4565b50505050505050505050565b604081511461298a5750565b6000612997826020015190565b90506129a3818361390f565b5050565b60008284036129b757508061052c565b82848309156129d15763c63cf08960e01b60005260046000fd5b60006129dd8584614fbd565b93909304949350505050565b6000848614612a3457838303428590038082036000612a08838a614fbd565b612a12838c614fbd565b612a1c9190614fa5565b90508584878303040181151502945050505050610330565b5092949350505050565b612a46613ed5565b831580612a51575081155b15612a6f57604051634c74edb760e11b815260040160405180910390fd5b612a77613ed5565b612ad4878585808060200260200160405190810160405280939291908181526020016000905b82821015612ac957612aba604083028601368190038101906150c7565b81526020019060010190612a9d565b505050505083613933565b805160408051602080890282018101909252878152612b33918a91908a908a90819060009085015b82821015612b2857612b19604083028601368190038101906150c7565b81526020019060010190612afc565b505050505085613ad6565b80516005811115612b4657612b46614658565b8351516005811115612b5a57612b5a614658565b141580612b85575080602001516001600160a01b03168360000151602001516001600160a01b031614155b80612b9c5750806040015183600001516040015114155b15612bba576040516309cfb45560e01b815260040160405180910390fd5b82600001516060015181606001511115612c6857600085856000818110612be357612be3614ea7565b905060400201803603810190612bf991906150c7565b905083600001516060015182606001510389826000015181518110612c2057612c20614ea7565b60200260200101516000015160600151826020015181518110612c4557612c45614ea7565b602090810291909101015160609081019190915284518101519083015250612d03565b600087876000818110612c7d57612c7d614ea7565b905060400201803603810190612c9391906150c7565b905081606001518460000151606001510389826000015181518110612cba57612cba614ea7565b60200260200101516000015160400151826020015181518110612cdf57612cdf614ea7565b60200260200101516060018181525050816060015184600001516060018181525050505b60809081015183516001600160a01b039091169101525095945050505050565b8151606090806001600160401b03811115612d4057612d4061400e565b604051908082528060200260200182016040528015612d69578160200160208202803683370190505b50915060005b81811015612e51576000858281518110612d8b57612d8b614ea7565b6020026020010151905080602001516001600160781b0316600003612db05750612e49565b6001848381518110612dc457612dc4614ea7565b91151560209283029190910190910152805160600151805160005b81811015612e44576000838281518110612dfb57612dfb614ea7565b602002602001015160600151905080600014612e3b576040516314bea84160e31b8152600481018790526024810183905260448101829052606401610d94565b50600101612ddf565b505050505b600101612d6f565b5060408051602080825281830190925234916000919060208201818036833701905050855190915060005b81811015612f0f576000878281518110612e9857612e98614ea7565b60209081029190910101518051909150600081516005811115612ebd57612ebd614658565b03612ef1578581606001511115612ee757604051631a783b8d60e01b815260040160405180910390fd5b8060600151860395505b612f058183602001518460400151886132dd565b5050600101612e7c565b50612f198261297e565b8215612f2957612f293384613439565b612f336001600055565b5050505092915050565b612f45613ed5565b8351600003612f69578460405163375c24c160e01b8152600401610d9491906150f3565b6000856001811115612f7d57612f7d614658565b03612fa45780516001600160a01b038316608090910152612f9f868583613ad6565b612fbd565b612faf868583613933565b336020820152604081018390525b8051606001516000036103305760006020820181905281516080015295945050505050565b808210156129a357604051632335530b60e11b815260040160405180910390fd5b6000806000526000825160208403805182604103600060018211613071576040880151606089015160001a9650821561304f57601b8160ff1c0196506001600160ff1b03811660408a01525b8689528985526020600060808760015afa508385528589526040890152506000515b89148915151695508590506131325760408252604486038051604088038051630b135d3f60e11b84528a82526020600060648901868f5afa9850881561312857630b135d3f60e11b60005114613128578b3b156130d957634f7fb80d60e01b60005260046000fd5b60018760410311156130f657638baa579f60e01b60005260046000fd5b640101000000881a61311757630f801e8560e11b6000528760045260246000fd5b632057875960e21b60005260046000fd5b8486529190925290525b50505050806119e557613143613c67565b634f7fb80d60e01b60005260046000fd5b6000428411806131645750428311155b15613190578115613188576040516337bf561360e11b815260040160405180910390fd5b50600061052c565b5060019392505050565b60018360038111156131ae576131ae614658565b1180156131c45750336001600160a01b03821614155b80156131d95750336001600160a01b03831614155b15613270576080880151511580156131f057508651155b156132065761320181868487613caf565b613270565b600061326482633313157060e01b88338d8c8e60405160240161322d9594939291906152b3565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b031990931692909217909152613cfb565b905061155b8187613d10565b5050505050505050565b600083600052602060002060208301835160051b81015b808210156132b957815180841160051b93845260209384185260406000209290910190613291565b505083149050806119e5576040516309bde33960e01b815260040160405180910390fd5b6000845160058111156132f2576132f2614658565b0361334057604084015160208501516001600160a01b0316171561332957604051636ab37ce760e01b815260040160405180910390fd5b61333b84608001518560600151613439565b6119e5565b60018451600581111561335557613355614658565b036133975760408401511561337d57604051636ab37ce760e01b815260040160405180910390fd5b61333b8460200151848660800151876060015186866138d4565b6002845160058111156133ac576133ac614658565b036133d05761333b84602001518486608001518760400151886060015187876127da565b6119e58460200151848660800151876040015188606001518787612827565b600086880361340a576134038686896129a7565b905061342e565b61342b61341887878b6129a7565b61342388888b6129a7565b8686866129e9565b90505b979650505050505050565b613442816138b3565b600080600080600085875af19050806134885761345d613c67565b60405163470c7c1d60e01b81526001600160a01b038416600482015260248101839052604401610d94565b505050565b60186101243510610244356102606102643560400201146004356020146102243561024014161616806134d3576040516339f3e3fd60e01b815260040160405180910390fd5b50565b60018360038111156134ea576134ea614658565b1180156135005750336001600160a01b03821614155b80156135155750336001600160a01b03831614155b156120055761200581868487613caf565b600083815260026020526040902061354184826001806118d1565b50805460ff1661355657613556838584611996565b710100000000000000000000000000000100019055505050565b604080517f000000000000000000000000c8ddac143e4da8337ffdea513ba27bf1d065751860ff60a01b17600090815260208690527f6b68d96d7ecc2eeecd3f60a3b682f13661a0ea7d1c90b397ba07dd3b4d114c1883526055600b20919092526001600160a01b03169050600080600080526020600085876000875af1915060005190508161362657613602613c67565b60405163344f54f560e21b81526001600160a01b0384166004820152602401610d94565b6001600160e01b03198116632671a55160e11b146127d257604051630e7ccd9360e11b8152600481018790526001600160a01b0384166024820152604401610d94565b833b61368457632f8aeb3960e11b6000528360045260246000fd5b6040516323b872dd60e01b6000528360045282602452816044526000806064600080895af18061371e573d156136f8576020601f3d01046020830481600302818311156136df57818303600302610200838002858002030401015b5a6020820110156136f4573d6000803e3d6000fd5b5050505b63f486bc8760e01b60005285600452846024528360445282606452600160845260a46000fd5b50604052505060006060525050565b843b61374857632f8aeb3960e11b6000528460045260246000fd5b60405160805160a05160c051637921219560e11b6000528760045286602452856044528460645260a0608452600060a45260008060c46000808d5af1806137f8573d156137d3576020601f3d01046020860481600302818311156137ba57818303600302610200838002858002030401015b5a6020820110156137cf573d6000803e3d6000fd5b5050505b63f486bc8760e01b600052896004528860245287604452866064528560845260a46000fd5b5060809290925260a05260c05260405250506000606052505050565b6000613821836020015190565b9050818114613488576134888361297e565b6000602088510361386e5750604080885260208089018a9052632671a55160e11b91890191909152604488015260016064880181905261387d565b50606487018051600101908190525b603c60c082028901038781528660208201528560408201528460608201528360808201528260a082015250505050505050505050565b806000036134d35760405163246cf94560e21b815260040160405180910390fd5b6138dd836138b3565b6138e78183613814565b816138fd576138f886868686613d6a565b6127d2565b6127d28282600189898960008a613833565b6064810151604082019060c00260440161392a848383613570565b50506020905250565b61395f565b637fda727960e01b60005260046000fd5b634e487b7160e01b600052601160045260246000fd5b602082018051518451811061397657613976613938565b602081026020860101516060815101516020845101518151811061399c5761399c613938565b602081026020830101516000806020860151156139c3575050606081018051600090915280155b885183518152602084015160208201526040840151604082015260a084015160808201526060812060208c51028c015b808b1015613a9a5760208b019a508a515199508d518a10613a1657613a16613938565b60208a0260208f01015198506020890151156139f357606089510151975060208b510151965087518710613a4c57613a4c613938565b602087026020890101519550606086018051860181511587821060011b1786179550809650506000815250606086208214608084015160a08801511416613a9557613a95613938565b6139f3565b50506060018290528015613ac95760018103613ac15763246cf94560e21b60005260046000fd5b613ac9613949565b5050505050505050505050565b6020820180515184518110613aed57613aed613938565b602081026020860101518051604081015160208551015181518110613b1457613b14613938565b60208102602083010151600080602087015115613b3b575050606081018051600090915280155b8951835181526020840151602082015260408401516040820152865160208c015261012087015160408c015260608120905060208c51028c015b808b1015613c295760208b019a508a515199508d518a10613b9857613b98613938565b60208a0260208f0101519850602089015115613b7557885197506040880151965060208b510151955086518610613bd157613bd1613938565b602086026020880101519450606085018051850181511586821060011b178517945080955050600081525060608520821460408d01516101208a01511460208e01518a51141616613c2457613c24613938565b613b75565b50508160608b5101528015613c595760018103613c515763246cf94560e21b60005260046000fd5b613c59613949565b505050505050505050505050565b3d156116b4576020601f3d01046020604051048160030281831115613c9a57818303600302610200838002858002030401015b5a602082011015613488573d6000803e3d6000fd5b604051602481018490523360448201526001600160a01b038316606482015260848101829052600090613cef9086906303874c7760e21b9060a40161322d565b90506120058185613d10565b6000806000835160208501865afa9392505050565b81613d3957613d1d613c67565b604051633ed4053f60e21b815260048101829052602401610d94565b613d496303874c7760e21b613e73565b156129a357604051633ed4053f60e21b815260048101829052602401610d94565b6040516323b872dd60e01b600052836004528260245281604452602060006064600080895af1803d15601f3d116001600051141617163d15158116613e635780873b151516613e635780613e4e5781613e2d573d15613e07576020601f3d0104602084048160030281831115613dee57818303600302610200838002858002030401015b5a602082011015613e03573d6000803e3d6000fd5b5050505b63f486bc8760e01b60005286600452856024528460445260006064528360845260a46000fd5b639889192360e01b6000528660045285602452846044528360645260846000fd5b632f8aeb3960e11b6000528660045260246000fd5b5050604052505060006060525050565b60008060203d03613e895760206000803e506000515b6001600160e01b031990811692169190911415919050565b6040518060a00160405280613eb4613f18565b81526000602082018190526040820152606080820181905260809091015290565b60408051610100810182526000606082018181526080830182905260a0830182905260c0830182905260e083018290528252602082018190529181019190915290565b60405180610160016040528060006001600160a01b0316815260200160006001600160a01b03168152602001606081526020016060815260200160006003811115613f6557613f65614658565b815260006020820181905260408201819052606082018190526080820181905260a0820181905260c09091015290565b6000815180845260005b81811015613fbb57602081850181015186830182015201613f9f565b81811115613fcd576000602083870101525b50601f01601f19169290920160200192915050565b60208152600061052c6020830184613f95565b60006020828403121561400757600080fd5b5035919050565b634e487b7160e01b600052604160045260246000fd5b60405160a081016001600160401b03811182821017156140465761404661400e565b60405290565b60405161016081016001600160401b03811182821017156140465761404661400e565b604051601f8201601f191681016001600160401b03811182821017156140975761409761400e565b604052919050565b60006001600160401b038211156140b8576140b861400e565b5060051b60200190565b6001600160a01b03811681146134d357600080fd5b80356140e2816140c2565b919050565b8035600681106140e257600080fd5b600060a0828403121561410857600080fd5b614110614024565b905061411b826140e7565b8152602082013561412b816140c2565b8060208301525060408201356040820152606082013560608201526080820135608082015292915050565b600082601f83011261416757600080fd5b8135602061417c6141778361409f565b61406f565b82815260a0928302850182019282820191908785111561419b57600080fd5b8387015b858110156141be576141b189826140f6565b845292840192810161419f565b5090979650505050505050565b600060c082840312156141dd57600080fd5b60405160c081018181106001600160401b03821117156141ff576141ff61400e565b60405290508061420e836140e7565b8152602083013561421e816140c2565b8060208301525060408301356040820152606083013560608201526080830135608082015260a0830135614251816140c2565b60a0919091015292915050565b600082601f83011261426f57600080fd5b8135602061427f6141778361409f565b82815260c0928302850182019282820191908785111561429e57600080fd5b8387015b858110156141be576142b489826141cb565b84529284019281016142a2565b8035600481106140e257600080fd5b600061016082840312156142e357600080fd5b6142eb61404c565b90506142f6826140d7565b8152614304602083016140d7565b602082015260408201356001600160401b038082111561432357600080fd5b61432f85838601614156565b6040840152606084013591508082111561434857600080fd5b506143558482850161425e565b606083015250614367608083016142c1565b608082015260a082013560a082015260c082013560c082015260e082013560e082015261010080830135818301525061012080830135818301525061014080830135818301525092915050565b80356001600160781b03811681146140e257600080fd5b600082601f8301126143dc57600080fd5b81356001600160401b038111156143f5576143f561400e565b614408601f8201601f191660200161406f565b81815284602083860101111561441d57600080fd5b816020850160208301376000918101602001919091529392505050565b600060a0828403121561444c57600080fd5b614454614024565b905081356001600160401b038082111561446d57600080fd5b614479858386016142d0565b8352614487602085016143b4565b6020840152614498604085016143b4565b604084015260608401359150808211156144b157600080fd5b6144bd858386016143cb565b606084015260808401359150808211156144d657600080fd5b506144e3848285016143cb565b60808301525092915050565b600082601f83011261450057600080fd5b813560206145106141778361409f565b82815260059290921b8401810191818101908684111561452f57600080fd5b8286015b8481101561456e5780356001600160401b038111156145525760008081fd5b6145608986838b010161443a565b845250918301918301614533565b509695505050505050565b60008083601f84011261458b57600080fd5b5081356001600160401b038111156145a257600080fd5b6020830191508360208260051b85010111156145bd57600080fd5b9250929050565b6000806000806000606086880312156145dc57600080fd5b85356001600160401b03808211156145f357600080fd5b6145ff89838a016144ef565b9650602088013591508082111561461557600080fd5b61462189838a01614579565b9096509450604088013591508082111561463a57600080fd5b5061464788828901614579565b969995985093965092949392505050565b634e487b7160e01b600052602160045260246000fd5b6006811061467e5761467e614658565b9052565b61468d82825161466e565b6020818101516001600160a01b0390811691840191909152604080830151908401526060808301519084015260809182015116910152565b600081518084526020808501945080840160005b8381101561471b5781516146ee888251614682565b808401516001600160a01b031660a08901526040015160c088015260e090960195908201906001016146d9565b509495945050505050565b60208152600061052c60208301846146c5565b60006020828403121561474b57600080fd5b81356001600160401b0381111561476157600080fd5b8201610160818503121561052c57600080fd5b60008060008060008060008060008060e08b8d03121561479357600080fd5b8a356001600160401b03808211156147aa57600080fd5b6147b68e838f016144ef565b9b5060208d01359150808211156147cc57600080fd5b6147d88e838f01614579565b909b50995060408d01359150808211156147f157600080fd5b6147fd8e838f01614579565b909950975060608d013591508082111561481657600080fd5b506148238d828e01614579565b90965094505060808b0135925061483c60a08c016140d7565b915060c08b013590509295989b9194979a5092959850565b604080825283519082018190526000906020906060840190828701845b8281101561488f578151151584529284019290840190600101614871565b505050838103828501526148a381866146c5565b9695505050505050565b600080602083850312156148c057600080fd5b82356001600160401b038111156148d657600080fd5b6148e285828601614579565b90969095509350505050565b6000806000806040858703121561490457600080fd5b84356001600160401b038082111561491b57600080fd5b61492788838901614579565b9096509450602087013591508082111561494057600080fd5b5061494d87828801614579565b95989497509550505050565b6000806040838503121561496c57600080fd5b82356001600160401b0381111561498257600080fd5b83016040818603121561499457600080fd5b946020939093013593505050565b6000806000806000608086880312156149ba57600080fd5b85356001600160401b03808211156149d157600080fd5b9087019060a0828a0312156149e557600080fd5b909550602087013590808211156149fb57600080fd5b50614a0888828901614579565b909550935050604086013591506060860135614a23816140c2565b809150509295509295909350565b60008060008060008060008060a0898b031215614a4d57600080fd5b88356001600160401b0380821115614a6457600080fd5b614a708c838d01614579565b909a50985060208b0135915080821115614a8957600080fd5b614a958c838d01614579565b909850965060408b0135915080821115614aae57600080fd5b50614abb8b828c01614579565b999c989b509699959896976060870135966080013595509350505050565b600060208284031215614aeb57600080fd5b813561052c816140c2565b606081526000614b096060830186613f95565b6020830194909452506001600160a01b0391909116604090910152919050565b600060208284031215614b3b57600080fd5b81356001600160401b03811115614b5157600080fd5b8201610240818503121561052c57600080fd5b6000614b726141778461409f565b83815260208082019190600586811b860136811115614b9057600080fd5b865b81811015614c8b5780356001600160401b0380821115614bb25760008081fd5b818a01915060a08236031215614bc85760008081fd5b614bd0614024565b823581528683013560028110614be65760008081fd5b81880152604083810135908201526060808401359082015260808084013583811115614c125760008081fd5b939093019236601f850112614c2957600092508283fd5b83359250614c396141778461409f565b83815292871b84018801928881019036851115614c565760008081fd5b948901945b84861015614c7457853582529489019490890190614c5b565b918301919091525088525050948301948301614b92565b5092979650505050505050565b6000808335601e19843603018112614caf57600080fd5b8301803591506001600160401b03821115614cc957600080fd5b602001915060a0810236038213156145bd57600080fd5b600060a08284031215614cf257600080fd5b61052c83836140f6565b6000808335601e19843603018112614d1357600080fd5b8301803591506001600160401b03821115614d2d57600080fd5b602001915060c0810236038213156145bd57600080fd5b600060c08284031215614d5657600080fd5b61052c83836141cb565b600060208284031215614d7257600080fd5b61052c826142c1565b60006104d4368361443a565b600060408284031215614d9957600080fd5b604051604081018181106001600160401b0382111715614dbb57614dbb61400e565b604052823581526020928301359281019290925250919050565b6000614de36141778461409f565b80848252602080830192508560051b850136811115614e0157600080fd5b855b81811015614e9b5780356001600160401b03811115614e225760008081fd5b870136601f820112614e345760008081fd5b8035614e426141778261409f565b81815260069190911b82018501908581019036831115614e625760008081fd5b928601925b82841015614e8b57614e793685614d87565b82528682019150604084019350614e67565b8852505050938201938201614e03565b50919695505050505050565b634e487b7160e01b600052603260045260246000fd5b60008235603e19833603018112614ed357600080fd5b9190910192915050565b6000823561015e19833603018112614ed357600080fd5b60006104d436836142d0565b6000808335601e19843603018112614f1757600080fd5b8301803591506001600160401b03821115614f3157600080fd5b6020019150368190038213156145bd57600080fd5b6000808335601e19843603018112614f5d57600080fd5b8301803591506001600160401b03821115614f7757600080fd5b6020019150600681901b36038213156145bd57600080fd5b634e487b7160e01b600052601160045260246000fd5b60008219821115614fb857614fb8614f8f565b500190565b6000816000190483118215151615614fd757614fd7614f8f565b500290565b600081518084526020808501945080840160005b8381101561471b57615003878351614682565b60a0969096019590820190600101614ff0565b60006080808301878452602060018060a01b03808916828701526040848188015283895180865260a089019150848b01955060005b8181101561508c57865161506084825161466e565b80870151861684880152848101518585015260609081015190840152958501959187019160010161504b565b505087810360608901526150a0818a614fdc565b9c9b505050505050505050505050565b6000828210156150c2576150c2614f8f565b500390565b6000604082840312156150d957600080fd5b61052c8383614d87565b6002811061467e5761467e614658565b602081016104d482846150e3565b600081518084526020808501945080840160005b8381101561471b57815161512a88825161466e565b838101516001600160a01b03168885015260408082015190890152606080820151908901526080908101519088015260a09096019590820190600101615115565b600081518084526020808501945080840160005b8381101561471b57815161519488825161466e565b808401516001600160a01b0390811689860152604080830151908a0152606080830151908a0152608080830151908a015260a091820151169088015260c0909601959082019060010161517f565b6004811061467e5761467e614658565b600081518084526020808501945080840160005b8381101561471b57815187529582019590820190600101615206565b600081518084526020808501808196508360051b8101915082860160005b858110156152a6578284038952815160a08151865286820151615265888801826150e3565b506040828101519087015260608083015190870152608091820151918601819052615292818701836151f2565b9a87019a9550505090840190600101615240565b5091979650505050505050565b85815260018060a01b038516602082015260a060408201526000610140855160a0808501526152ed82850182516001600160a01b03169052565b6020810151610160615309818701836001600160a01b03169052565b6040830151915080610180870152506153266102a0860182615101565b9050606082015161013f19868303016101a0870152615345828261516b565b915050608082015161535b6101c08701826151e2565b5060a08201516101e086015260c082015161020086015260e082015161022086015261010080830151610240870152610120808401516102608801528484015161028088015260208a015194506153bd60c08801866001600160781b03169052565b60408a01516001600160781b031660e088015260608a0151878403609f19908101848a015290955093506153f18386613f95565b945060808a01519250838786030181880152505061540f8382613f95565b92505050828103606084015261542581866151f2565b905082810360808401526154398185615222565b9897505050505050505056fea2646970667358221220d9ec6bf53c7c4dd207e9b7af873aae1b86f9ebf0a16709b20f4f94de3560378664736f6c634300080e0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000c8ddac143e4da8337ffdea513ba27bf1d0657518
-----Decoded View---------------
Arg [0] : conduitController (address): 0xc8ddac143E4da8337FFDeA513Ba27bF1d0657518
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 000000000000000000000000c8ddac143e4da8337ffdea513ba27bf1d0657518
Deployed Bytecode Sourcemap
3793:1319:29:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;29062:203:8;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;27490:367;;;;;;;;;;-1:-1:-1;27490:367:8;;;;;:::i;:::-;27615:16;19905:23:26;;;:12;:23;;;;;20014;;;;;;;20052;;;;;;-1:-1:-1;;;;;20090:21:26;;;;;;-1:-1:-1;;;20126:23:26;;;;;27490:367:8;;;;;1145:14:39;;1138:22;1120:41;;1204:14;;1197:22;1192:2;1177:18;;1170:50;1236:18;;;1229:34;1294:2;1279:18;;1272:34;1107:3;1092:19;27490:367:8;901:411:39;22904:506:8;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;25473:190::-;;;;;;;;;;;;;:::i;:::-;;;13363:25:39;;;13351:2;13336:18;25473:190:8;13217:177:39;25856:728:8;;;;;;;;;;-1:-1:-1;25856:728:8;;;;;:::i;:::-;;:::i;17479:938::-;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;:::i;25002:199::-;;;;;;;;;;-1:-1:-1;25002:199:8;;;;;:::i;:::-;;:::i;:::-;;;17344:14:39;;17337:22;17319:41;;17307:2;17292:18;25002:199:8;17179:187:39;19944:489:8;;;;;;:::i;:::-;;:::i;5074:495::-;;;;;;:::i;:::-;;:::i;8311:532::-;;;;;;:::i;:::-;;:::i;11883:926::-;;;;;;:::i;:::-;;:::i;28058:233::-;;;;;;;;;;-1:-1:-1;28058:233:8;;;;;:::i;:::-;;:::i;28605:315::-;;;;;;;;;;;;;:::i;:::-;;;;;;;;;:::i;3409:283::-;;;;;;:::i;:::-;;:::i;23942:203::-;;;;;;;;;;-1:-1:-1;23942:203:8;;;;;:::i;:::-;;:::i;29062:::-;29146:26;29250:7;:5;:7::i;:::-;29235:22;;29062:203;:::o;22904:506::-;23125:29;23267:135;23306:14;23267:135;23339:17;;23267:135;:::i;:::-;23375:12;;23267:20;:135::i;:::-;23247:155;;22904:506;;;;;;;;:::o;25473:190::-;25528:18;25636:19;:17;:19::i;25856:728::-;26136:401;;;;;;;;;25978:17;;26105:471;;26136:401;26170:13;;;;:5;:13;:::i;:::-;-1:-1:-1;;;;;26136:401:8;;;;;26202:5;:10;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;26136:401:8;;;;;26231:11;;;;:5;:11;:::i;:::-;26136:401;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;-1:-1:-1;;;26136:401:8;;;-1:-1:-1;;26136:401:8;;26261:19;;;;:5;:19;:::i;:::-;26136:401;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;-1:-1:-1;;;26136:401:8;;;-1:-1:-1;;26136:401:8;;26299:15;;;;;;;;:::i;:::-;26136:401;;;;;;;;:::i;:::-;;;;;26333:5;:15;;;26136:401;;;;26367:5;:13;;;26136:401;;;;26399:5;:14;;;26136:401;;;;26432:5;:10;;;26136:401;;;;26461:5;:16;;;26136:401;;;;26496:5;:19;;;;;;;;:::i;:::-;26136:401;;;-1:-1:-1;26552:13:8;;;;26105:16;:471::i;:::-;26093:483;25856:728;-1:-1:-1;;25856:728:8:o;17479:938::-;17934:29;;18074:335;18124:14;18074:335;18157:17;;18074:335;:::i;:::-;18193:17;;18229:25;;18273:19;-1:-1:-1;;;;;18311:23:8;;;:48;;18350:9;18311:48;;;18337:10;18311:48;18378:16;18074:31;:335::i;:::-;18054:355;;;;17479:938;;;;;;;;;;;;;:::o;25002:199::-;25099:14;25176:17;25186:6;;25176:9;:17::i;:::-;25164:29;25002:199;-1:-1:-1;;;25002:199:8:o;19944:489::-;20087:29;20229:196;20268:32;20293:6;;20268:24;:32::i;:::-;20319:25;;;20342:1;20319:25;;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;20319:25:8;;;;;;;;;;;;;;;;;20398:12;;20229:20;:196::i;:::-;20209:216;;19944:489;;;;;;;:::o;5074:495::-;5218:14;5339:222;5386:30;5410:5;5386:23;:30::i;:::-;5431:25;;;5454:1;5431:25;;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;5431:25:8;;;;;;;;;;;;;;;;;5506:19;5540:10;5339:32;:222::i;8311:532::-;8552:14;8635:200;;8682:13;8635:200;:::i;:::-;;8710:17;;8635:200;:::i;:::-;8742:19;-1:-1:-1;;;;;8776:23:8;;;:48;;8815:9;8635:32;:200::i;8776:48::-;8802:10;8635:32;:200::i;11883:926::-;12232:29;12263;12412:389;12462:32;12487:6;;12462:24;:32::i;:::-;12544:25;;;12567:1;12544:25;;;;;;;;;;;;;;-1:-1:-1;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;12544:25:8;;;;;;;;;;;;;;;;;12623:17;;12659:25;;12703:19;12741:10;12770:16;12412:31;:389::i;:::-;12392:409;;;;11883:926;;;;;;;;;;;:::o;28058:233::-;-1:-1:-1;;;;;1885:18:15;;28163:15:8;1885:18:15;;;:9;:18;;;;;;28263:20:8;1683:228:15;28605:315:8;28710:21;28746:23;28784:25;28898:14;:12;:14::i;:::-;28891:21;;;;;;28605:315;;;:::o;3409:283::-;3549:14;3643:41;3673:10;3643:29;:41::i;23942:203::-;24047:14;24122:15;24130:6;;24122:7;:15::i;4451:258:29:-;4500:13;4608:4;;4595:18;4640;4634:4;4627:32;4686:4;4608;4673:18;36263:757:24;36466:29;36586:290;36635:14;36664:17;36696:4;36763:14;:21;36807:1;36586:34;:290::i;:::-;36960:52;36983:14;36999:12;;36960:22;:52::i;923:516:15:-;970:18;1068:21;:19;:21::i;:::-;-1:-1:-1;1295:10:15;1285:21;;;;:9;:21;;;;;;;;;1283:23;;;;;;;;;1389:42;;13363:25:39;;;1283:23:15;;1295:10;1389:42;;13336:18:39;1389:42:15;;;;;;;923:516;:::o;1411:7606:22:-;1707:47;;;;2532:21;2526:28;;2666:55;;;2642:94;2804:18;;1542:17;;1707:47;1542:17;;2297:20;;2929:7;2912:25;;;;1542:17;3031:911;3056:11;3053:1;3050:18;3031:911;;;3274:18;;-1:-1:-1;;3270:32:22;3401:10;;3493:21;;;3641;3626:37;;3607:57;;3731:18;;-1:-1:-1;3903:24:22;;;;3846:25;;;;3100:1;3093:9;3031:911;;;3035:14;4132:7;4119:11;4115:25;4074:21;4068:28;4040:115;4027:128;;;;;4258:25;4388:28;4377:39;;4631:21;4625:28;4980:7;4878:41;4836:15;4806:136;4778:183;4756:246;5140:1;5125:1036;5150:27;5147:1;5144:34;5125:1036;;;5392:26;;-1:-1:-1;;5388:40:22;5535:10;;5627:21;;;5818:29;5803:45;;5741:126;;5934:18;;-1:-1:-1;6122:24:22;;;;6057:33;;;;5210:1;5203:9;5125:1036;;;-1:-1:-1;;6309:21:22;6303:28;;6383:7;6350:41;;6275:131;;-1:-1:-1;;6753:29:22;;6894:18;;6521:15;7008:29;;7136:104;;;7348:19;;7454:31;;;7656:41;7600:112;;7836:27;;7958:47;;;8149:30;8093:101;;;8278:27;;;8437:17;8414:41;;8551:34;;;;8680;;;;8812:50;;;;-1:-1:-1;;8952:47:22;;-1:-1:-1;8414:41:22;1411:7606;-1:-1:-1;1411:7606:22:o;5886:1254:24:-;6305:29;6336;6465:233;6514:14;6543:17;6575:5;6647:16;6678:9;6465:34;:233::i;:::-;6823:199;6867:14;6823:199;6896:17;;6823:199;:::i;:::-;;6928:25;;6823:199;:::i;:::-;6968:19;7002:9;6823:29;:199::i;:::-;6791:231;;;;-1:-1:-1;5886:1254:24;-1:-1:-1;;;;;;;;;;5886:1254:24:o;16021:2618:26:-;16101:14;16200:21;:19;:21::i;:::-;16285:31;;;16583:6;16285:31;16654:1857;16678:11;16674:1;:15;16654:1857;;;16752:20;16775:6;;16782:1;16775:9;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;16752:32;-1:-1:-1;16856:40:26;16899:16;16752:32;;16899:16;:::i;:::-;16856:59;-1:-1:-1;17005:23:26;;;;16856:59;17005:23;:::i;:::-;16995:33;-1:-1:-1;17142:98:26;;17206:15;17142:98;:::i;:::-;:41;:98::i;:::-;17351:23;;;;:12;:23;;;;;;-1:-1:-1;17130:110:26;;-1:-1:-1;17472:259:26;;17130:110;;17351:23;;17660:4;17472:18;:259::i;:::-;-1:-1:-1;17824:23:26;;;;17819:571;;17927:53;17944:7;17953:9;17964:15;;;;:5;:15;:::i;:::-;17927:53;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;17927:16:26;;-1:-1:-1;;;17927:53:26:i;:::-;18077:30;;-1:-1:-1;;18077:30:26;18103:4;18077:30;;;18327:20;;;;;;;;:::i;:::-;-1:-1:-1;;;;;18216:154:26;18293:7;-1:-1:-1;;;;;18216:154:26;;18257:9;18216:154;;;;13363:25:39;;13351:2;13336:18;;13217:177;18216:154:26;;;;;;;;17819:571;-1:-1:-1;;18492:3:26;;16654:1857;;;-1:-1:-1;18627:4:26;;16021:2618;-1:-1:-1;;;;;;;16021:2618:26:o;18565:881:25:-;18674:37;18827:6;;-1:-1:-1;;;;;18941:32:25;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;18924:49;;19137:9;19132:213;19156:11;19152:1;:15;19132:213;;;19295:34;19319:6;;19326:1;19319:9;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;19295:23;:34::i;:::-;19275:14;19290:1;19275:17;;;;;;;;:::i;:::-;;;;;;;;;;:54;19169:3;;19132:213;;;;19417:21;18565:881;;;;:::o;17874:393::-;17979:34;;:::i;:::-;18125:134;;;;;;;;;;18153:16;:5;;:16;:::i;:::-;18125:134;;;:::i;:::-;;;;;18184:1;-1:-1:-1;;;;;18125:134:25;;;;;18200:1;-1:-1:-1;;;;;18125:134:25;;;;;18216:5;:15;;;;;;;;:::i;:::-;18125:134;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;18125:134:25;;;-1:-1:-1;;18125:134:25;;;;;;;;;;;;;;;;;-1:-1:-1;18109:150:25;17874:393;-1:-1:-1;;17874:393:25:o;3092:2123::-;3324:4;3419:21;:19;:21::i;:::-;3522:33;3658:17;3690:21;3726:23;3763:170;3811:13;3843:17;3879:4;3902:16;3763:29;:170::i;:::-;4050:22;;;4070:1;4050:22;;;;;;;;;3643:290;;-1:-1:-1;3643:290:25;;-1:-1:-1;3643:290:25;-1:-1:-1;4010:37:25;;4050:22;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;4010:62;;4184:13;4164:14;4179:1;4164:17;;;;;;;;:::i;:::-;;;;;;:33;;;;4290:58;4314:14;4330:17;4290:23;:58::i;:::-;4438:38;4479:14;4494:1;4479:17;;;;;;;;:::i;:::-;;;;;;;:28;;;4438:69;;4599:187;4644:15;4674:13;4702:15;4732:19;4766:9;4599:30;:187::i;:::-;4871:236;4910:9;4934:15;:23;;;4972:15;:20;;;5007:9;5031:15;:21;;;5067:15;:29;;;4871:24;:236::i;:::-;5160:23;2393:1:10;1355:16:28;:31;1262:132;5160:23:25;-1:-1:-1;5203:4:25;;3092:2123;-1:-1:-1;;;;;;;;;;3092:2123:25:o;12363:717:22:-;12451:21;12487:23;12525:25;12637:18;:16;:18::i;:::-;12874:26;;;2315:1:10;12874:26:22;;;;;;;;;12619:36;;-1:-1:-1;12775:19:22;;-1:-1:-1;12874:26:22;;;;;;;;-1:-1:-1;;;;;13024:7:22;13011:21;;13004:58;-1:-1:-1;13011:21:22;12363:717;;-1:-1:-1;12363:717:22;:::o;2941:8691:3:-;3056:4;3546:31;3533:45;3805:1;3801:22;;;;3707:1;3687:22;3963:1;3953:12;;4404:11;4397:19;4321:114;;;4618:95;;4671:26;;-1:-1:-1;;;4671:26:3;;4687:9;4671:26;;;13363:25:39;13336:18;;4671:26:3;;;;;;;;4618:95;3988:736;4817:33;4861:24;4896:40;5039:25;5320:1;5313:5;5310:12;5271:51;;5679:29;5613:35;5579:156;5517:35;5487:271;5452:325;5423:354;;6069:1;6062:5;6059:12;6033:1;6026:5;6023:12;6019:1;6012:5;6008:13;6004:32;5978:112;5958:132;;6508:1;6490:16;6486:24;6424:35;6394:139;6368:1;6337:28;6330:36;6326:44;6319:5;6315:56;6289:263;6270:282;;6665:268;6720:10;6749:9;6777:16;6812:28;6859:25;6903:15;6665:36;:268::i;:::-;-1:-1:-1;7309:31:3;7404:7;7363:49;;7283:148;7252:194;7025:18;7521:28;:47;;;;;;;;:::i;:::-;;7517:4008;;7750:34;;;;;;7696:29;;7750:10;7696:29;:::i;:::-;-1:-1:-1;;;;;7688:96:3;;7687:103;7665:205;;7832:22;;-1:-1:-1;;;7832:22:3;;;;;;;;;;;7665:205;7966:302;8017:15;8051:21;;;;;;;;:::i;:::-;8091:18;;;;;;;;:::i;:::-;8128:10;8157;:26;;;8202:10;:22;;;8243:10;7966:32;:302::i;:::-;8367:174;8409:30;;;;8458:18;;;;;;;;:::i;:::-;8495:31;;;;:10;:31;:::i;:::-;8367:23;:174::i;:::-;7517:4008;;;8976:30;;;14743:4:10;8976:30:3;;;;;;;;;8949:24;;8976:30;;;;;;;;;;-1:-1:-1;;8949:57:3;-1:-1:-1;9118:35:3;9109:5;:44;;;;;;;;:::i;:::-;;9105:2007;;9256:313;9294:21;;;;;;;;:::i;:::-;9338:18;;;;;;;;:::i;:::-;9379:10;9412;:26;;;9461:10;:22;;;9506:10;9539:11;9256:15;:313::i;:::-;9105:2007;;;9604:36;9595:5;:45;;;;;;;;:::i;:::-;;9591:1521;;9743:314;9782:21;;;;;;;;:::i;:::-;9826:18;;;;;;;;:::i;:::-;9867:10;9900;:26;;;9949:10;:22;;;9994:10;10027:11;9743:16;:314::i;9591:1521::-;10092:35;10083:5;:44;;;;;;;;:::i;:::-;;10079:1033;;10230:337;10268:29;;;;:10;:29;:::i;:::-;10320:10;10353:18;;;;;;;;:::i;:::-;10394:10;:34;;;10451:10;:30;;;10504:10;10537:11;10230:15;:337::i;10079:1033::-;10758:338;10797:29;;;;:10;:29;:::i;:::-;10849:10;10882:18;;;;;;;;:::i;:::-;10923:10;:34;;;10980:10;:30;;;11033:10;11066:11;10758:16;:338::i;:::-;11197:190;11241:18;;;;;;;;:::i;:::-;11278:10;11307:35;11361:11;11197:25;:190::i;:::-;11485:28;11501:11;11485:15;:28::i;:::-;8559:2966;7517:4008;11577:23;2393:1:10;1355:16:28;:31;1262:132;11577:23:3;-1:-1:-1;11620:4:3;;2941:8691;-1:-1:-1;;;;;;;;2941:8691:3:o;12704:2468:26:-;12792:14;12891:21;:19;:21::i;:::-;12976:31;;;13269:6;12976:31;13340:1704;13364:11;13360:1;:15;13340:1704;;;13438:30;13471:6;;13478:1;13471:9;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;13438:42;-1:-1:-1;13511:13:26;;;;13438:42;13511:13;:::i;:::-;13501:23;-1:-1:-1;13550:10:26;;;;;;;;:::i;:::-;13543:17;-1:-1:-1;13659:10:26;-1:-1:-1;;;;;13659:21:26;;;;;;:43;;-1:-1:-1;13684:10:26;-1:-1:-1;;;;;13684:18:26;;;;13659:43;13655:117;;;13734:18;;-1:-1:-1;;;13734:18:26;;;;;;;;;;;13655:117;13874:17;13894:579;13933:485;;;;;;;;13975:7;-1:-1:-1;;;;;13933:485:26;;;;;14009:4;-1:-1:-1;;;;;13933:485:26;;;;;14040:5;:11;;;;;;;;:::i;:::-;13933:485;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;-1:-1:-1;;;13933:485:26;;;-1:-1:-1;;13933:485:26;;14078:19;;;;:5;:19;:::i;:::-;13933:485;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;13894:579;14584:23;;;;:12;:23;;;;;;;14700:31;;-1:-1:-1;;14750:30:26;14700:31;14750:30;;;14886:40;;14584:23;;-1:-1:-1;13874:599:26;;-1:-1:-1;;;;;;14886:40:26;;;;;;;;;;;;13874:599;13363:25:39;;13351:2;13336:18;;13217:177;14886:40:26;;;;;;;;-1:-1:-1;;15025:3:26;;13340:1704;;8547:11933:24;8892:21;:19;:21::i;:::-;9012;;8990:19;9012:21;-1:-1:-1;;;;;9142:26:24;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;9142:26:24;-1:-1:-1;9306:1:24;9286:22;;;9111:57;;-1:-1:-1;10558:31:24;10327:29;10284:15;;10262:20;10258:42;10228:151;10122:486;10102:1;10080:543;;10792:8052;10816:11;10812:1;:15;10792:8052;;;10901:34;10938:14;10953:1;10938:17;;;;;;;;:::i;:::-;;;;;;;10901:54;;11060:16;11080:1;11060:21;11056:466;;11214:1;11188:23;;;;:27;11371:1;11364:9;;11344:30;;11494:8;;11056:466;11645:17;11685;11725:19;11766:216;11822:13;11862:17;11906:15;11948:11;11766:29;:216::i;:::-;11622:360;;;;;;12126:1;12123;12119:9;12106:11;12099:30;12254:9;12267:1;12254:14;12250:278;;-1:-1:-1;;12401:1:24;12375:23;;;;:27;;;;-1:-1:-1;12500:8:24;;12250:278;12630:9;12613:11;12625:1;12613:14;;;;;;;;:::i;:::-;;;;;;;;;;:26;12970:24;;:34;;;;13110:32;;;;13267:30;;;;;13415:12;;-1:-1:-1;;12842:18:24;;;;12970:34;;13110:32;12950:17;13511:2033;13535:15;13531:1;:19;13511:2033;;;13629:26;13658:5;13664:1;13658:8;;;;;;;;:::i;:::-;;;;;;;13629:37;;14020:9;14014:16;14007:24;13943:33;13910:148;13873:185;;14181:17;14201:155;14240:9;14276:11;14314:9;:19;;;14201:12;:155::i;:::-;14181:175;;14490:9;:19;;;14465:9;:21;;;:44;14461:549;;14617:21;;;:33;;;14461:549;;;14813:173;14856:9;14896:11;14938:9;:21;;;14813:12;:173::i;:::-;14789:21;;;:197;14461:549;15115:19;;;:31;;;15318:21;;;;15271:253;;15137:9;15412;15448:7;15482:5;15271:20;:253::i;:::-;15247:21;;;;:277;;;;-1:-1:-1;13552:3:24;;13511:2033;;;-1:-1:-1;15711:24:24;;:38;;;15902:20;;15645:40;16014:2815;16038:23;16034:1;:27;16014:2815;;;16148:42;16220:13;16234:1;16220:16;;;;;;;;:::i;:::-;;;;;;;16148:111;;16357:17;16377:163;16416:9;16452:11;16490:17;:27;;;16377:12;:163::i;:::-;16357:183;;16733:17;:27;;;16675:17;:29;;;:85;16645:659;;16890:29;;;:41;;;16645:659;;;17099:181;17142:9;17182:11;17224:17;:29;;;17099:12;:181::i;:::-;17067:29;;;:213;16645:659;17409:27;;;:39;;;17665:29;;;;17614:290;;17439:9;17783;17823:7;17861:4;17614:20;:290::i;:::-;17555:29;;;:372;-1:-1:-1;18660:34:24;18562:167;;18522:238;18414:29;18324:167;;;18287:500;16063:3;;16014:2815;;;;10834:8010;;;;;;;;;;10792:8052;10829:3;;10792:8052;;;;19191:33;19228:1;19191:38;19187:102;;19253:24;;-1:-1:-1;;;19253:24:24;;;;;;;;;;;19187:102;19367:58;19391:14;19407:17;19367:23;:58::i;:::-;19669:9;19664:798;19688:11;19684:1;:15;19664:798;;;19825:1;19817:10;;19799:11;19811:1;19799:14;;;;;;;;:::i;:::-;;;;;;;:28;19795:85;19852:8;19795:85;19967:38;20031:14;20046:1;20031:17;;;;;;;;:::i;:::-;;;;;;;:28;;;19967:111;;20149:297;20196:11;20208:1;20196:14;;;;;;;;:::i;:::-;;;;;;;20233:15;:23;;;20279:15;:20;;;20322:9;20354:15;:21;;;20398:15;:29;;;20149:24;:297::i;:::-;19706:756;19664:798;19701:3;;19664:798;;;;8803:11677;;;8547:11933;;;;;:::o;37953:2312::-;38104:29;38245:12;;-1:-1:-1;;;;;38371:34:24;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;38358:47;;38576:31;38680:9;38675:959;38699:17;38695:1;:21;38675:959;;;38801:32;38836:12;;38849:1;38836:15;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;38801:50;-1:-1:-1;38949:26:24;38978:181;39018:14;39055:27;38801:50;;39055:27;:::i;:::-;39105:35;;;;:11;:35;:::i;:::-;38978:17;:181::i;:::-;38949:210;;39290:9;:17;;;-1:-1:-1;;;;;39262:45:24;:9;:14;;;:24;;;-1:-1:-1;;;;;39262:45:24;;39258:361;;39393:25;;;;;39258:361;;;39590:9;39548:10;39563:23;39559:1;:27;39548:39;;;;;;;;:::i;:::-;;;;;;:51;;;;39258:361;-1:-1:-1;;38718:3:24;;38675:959;;;-1:-1:-1;39721:28:24;;39717:328;;39964:23;39951:10;39945:17;39941:47;39904:10;39871:140;39717:328;38498:1558;40121:63;40157:14;40173:10;40121:35;:63::i;:::-;;40238:19;37953:2312;;;;;:::o;1550:220:28:-;2393:1:10;1677:16:28;;:32;1673:90;;1733:18;;-1:-1:-1;;;1733:18:28;;;;;;;;;;;1673:90;1550:220::o;24017:4349:24:-;24532:24;;24707:32;;24341:29;;;;24886:55;24707:32;24532:24;24886:55;:::i;:::-;-1:-1:-1;;;;;24856:96:24;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;24843:109;;25123:31;25233:9;25228:1073;25252:22;25248:1;:26;25228:1073;;;25376:40;25442:17;25460:1;25442:20;;;;;;;;:::i;:::-;;;;;;;25376:105;;25582:26;25611:215;25653:14;25690:10;25723;25756:19;25798:9;25611:19;:215::i;:::-;25582:244;;25957:9;:17;;;-1:-1:-1;;;;;25929:45:24;:9;:14;;;:24;;;-1:-1:-1;;;;;25929:45:24;;25925:361;;26060:25;;;;;25925:361;;;26257:9;26215:10;26230:23;26226:1;:27;26215:39;;;;;;;;:::i;:::-;;;;;;:51;;;;25925:361;-1:-1:-1;;25276:3:24;;25228:1073;;;;26383:9;26378:1185;26402:30;26398:1;:34;26378:1185;;;26538:40;26604:25;26630:1;26604:28;;;;;;;;:::i;:::-;;;;;;;26538:113;;26752:26;26781:234;26823:14;26860:18;26901:10;26934:19;26984:1;26781:19;:234::i;:::-;26752:263;;27146:9;:17;;;-1:-1:-1;;;;;27118:45:24;:9;:14;;;:24;;;-1:-1:-1;;;;;27118:45:24;;27114:434;;27249:25;;;;;27114:434;;;27519:9;27404:10;27470:23;27445:22;27441:1;:26;:52;27404:112;;;;;;;;:::i;:::-;;;;;;:124;;;;27114:434;-1:-1:-1;;26434:3:24;;26378:1185;;;-1:-1:-1;27650:28:24;;27646:328;;27893:23;27880:10;27874:17;27870:47;27833:10;27800:140;27646:328;25045:2940;28048:10;:17;28069:1;28048:22;28044:90;;28094:28;;-1:-1:-1;;;28094:28:24;;;;;;;;;;;28044:90;28209:100;28259:14;28288:10;28209:35;:100::i;:::-;28191:118;;28322:36;;24017:4349;;;;;;;;:::o;1635:663:2:-;1765:7;1867:190;1948:15;:29;;;:36;1999:15;:47;;;1867:66;:190::i;:::-;2251:23;;-1:-1:-1;;;;;1885:18:15;2251:23:2;1885:18:15;;;:9;:18;;;;;;2170:120:2;;2205:15;;2170:16;:120::i;4095:1637:35:-;4370:23;;4285:10;;4370:23;;;;;4366:309;;;4488:15;4484:90;;;4531:27;;-1:-1:-1;;;4531:27:35;;;;;13363:25:39;;;13336:18;;4531:27:35;13217:177:39;4484:90:35;-1:-1:-1;4658:5:35;4651:12;;4366:309;4791:21;;;;;-1:-1:-1;;;;;4791:21:35;4880:25;;4876:770;;5007:15;5003:632;;;5131:31;;-1:-1:-1;;;5131:31:35;;;;;13363:25:39;;;13336:18;;5131:31:35;13217:177:39;5003:632:35;5300:23;;-1:-1:-1;;;5300:23:35;;-1:-1:-1;;;;;5300:23:35;5276:47;;5272:363;;5426:15;5422:100;;;5473:29;;-1:-1:-1;;;5473:29:35;;;;;13363:25:39;;;13336:18;;5473:29:35;13217:177:39;5422:100:35;5614:5;5607:12;;;;;5272:363;-1:-1:-1;5720:4:35;;4095:1637;-1:-1:-1;;;;;4095:1637:35:o;2710:584::-;2940:10;-1:-1:-1;;;;;2929:21:35;;;2925:60;;2710:584;;;:::o;2925:60::-;3078:14;3095:50;3115:18;:16;:18::i;:::-;-1:-1:-1;;;13507:13:22;13699:25;;;13827:29;13820:54;;;;14185:23;14178:42;;;14311:25;14298:39;;14419:34;;;14298:39;13384:1087;3095:50:35;3078:67;;3237:49;3259:7;3268:6;3276:9;3237:21;:49::i;:::-;2844:450;2710:584;;;:::o;936:223:28:-;1052:21;:19;:21::i;:::-;2425:1:10;1124:16:28;:27;936:223::o;4449:7719:26:-;4719:17;4751:20;4786:22;4887:38;4928:13;:24;;;4887:65;;5066:146;5096:15;:25;;;5140:15;:23;;;5182:15;5066:11;:146::i;:::-;5047:311;;-1:-1:-1;5337:1:26;;-1:-1:-1;5337:1:26;;-1:-1:-1;5337:1:26;;-1:-1:-1;5321:25:26;;5047:311;5477:23;;;;5542:25;;;;-1:-1:-1;;;;;5469:32:26;;;;5534:34;5659:23;;;;:41;;-1:-1:-1;5686:14:26;;5659:41;5655:94;;;5724:13;;-1:-1:-1;;;5724:13:26;;;;;;;;;;;5655:94;5873:11;5861:9;:23;:94;;;;-1:-1:-1;5929:25:26;;;;21022:1;21007:17;21000:25;5901:54;5843:268;;;6067:32;;-1:-1:-1;;;6067:32:26;;;;;;;;;;;5843:268;6217:58;6259:15;6217:41;:58::i;:::-;6205:70;;6370:316;6423:13;6451:17;6483:16;6514:9;6538:15;:24;;;6577:15;:25;;;6617:15;:23;;;6655:15;:20;;;6370:38;:316::i;:::-;6767:31;6801:23;;;:12;:23;;;;;;6915:194;;6814:9;;6801:23;;7079:15;6915:18;:194::i;:::-;6896:358;;-1:-1:-1;7237:1:26;;-1:-1:-1;7237:1:26;;-1:-1:-1;7218:24:26;;-1:-1:-1;;;7218:24:26;6896:358;7353:23;;;;7348:200;;7393:143;7428:15;:23;;;7470:9;7498:13;:23;;;7393:16;:143::i;:::-;7668:21;;-1:-1:-1;;;;;7668:21:26;;;;;;-1:-1:-1;;;7728:23:26;;;7876:22;;7872:4153;;8001:11;8016:1;8001:16;7997:681;;8130:17;8118:29;;8180:17;8166:31;;7997:681;;;8336:11;8315:17;:32;8311:367;;8449:30;8468:11;8449:30;;:::i;:::-;;-1:-1:-1;8581:30:26;8594:17;8581:30;;:::i;:::-;;-1:-1:-1;8630:32:26;8645:17;8630:32;;:::i;:::-;;;8311:367;8810:11;8780:27;8798:9;8780:15;:27;:::i;:::-;:41;8776:335;;;9061:15;9047:11;:29;9035:41;;8776:335;9196:28;9215:9;9196:28;;:::i;:::-;;;-1:-1:-1;;;;;9515:11:26;9512:27;-1:-1:-1;;;;;9461:15:26;9458:31;9433:125;9430:1835;;;9664:337;;;9688:3;9719:224;9754:2;9719:224;;;9867:11;;;;;9829:2;9719:224;;;-1:-1:-1;9976:2:26;9664:337;-1:-1:-1;9664:337:26:o;:::-;10040:122;10106:33;10127:11;10110:15;10106:33;:::i;:::-;10070:9;10040:122;:::i;:::-;10287:17;;10272:33;10407:29;;;;;10549:31;;;;;10477:35;;;;-1:-1:-1;;;;;10702:31:26;;;10760:27;;;10673:137;10670:576;;;-1:-1:-1;;;10906:1:26;10899:32;11068:16;11048:18;11041:44;11204:18;11201:1;11194:29;10670:576;11483:30;;-1:-1:-1;;;;;11649:46:26;;;-1:-1:-1;;;11649:46:26;-1:-1:-1;;;;;11582:48:26;;;;;-1:-1:-1;;;;;;11582:48:26;;;;;;;11509:4;11582:48;11649:46;;;;7872:4153;;;11819:30;;-1:-1:-1;;;;;11967:46:26;;;-1:-1:-1;;;11967:46:26;-1:-1:-1;;;;;11910:42:26;;;;;-1:-1:-1;;;;;;11910:42:26;;;;;;;11845:4;11910:42;11967:46;;;;7872:4153;-1:-1:-1;12137:9:26;;-1:-1:-1;12148:11:26;;-1:-1:-1;;;;4449:7719:26;;;;;;;;;:::o;1566:7616:16:-;1951:24;;2090:21;;1918:30;2181:5128;2205:22;2201:1;:26;2181:5128;;;2305:40;2371:17;2389:1;2371:20;;;;;;;;:::i;:::-;;;;;;;2305:105;;2511:18;2532:16;:27;;;2511:48;;2659:19;2645:10;:33;2641:122;;2710:33;;-1:-1:-1;;;2710:33:16;;;;;;;;;;;2641:122;2860:14;2875:10;2860:26;;;;;;;;:::i;:::-;;;;;;;:36;;;-1:-1:-1;;;;;2860:41:16;2900:1;2860:41;2856:98;;2926:8;;;;2856:98;3033:38;3097:14;3112:10;3097:26;;;;;;;;:::i;:::-;;;;;;;;;;;:37;3279:22;;;;3097:37;;-1:-1:-1;3097:37:16;;;3548:16;:21;;;:35;;;;;;;;:::i;:::-;;3544:3087;;3679:21;;;;3816:12;;3798:30;;3794:127;;3864:33;;-1:-1:-1;;;3864:33:16;;;;;;;;;;;3794:127;4019:26;4048:5;4054:14;4048:21;;;;;;;;:::i;:::-;;;;;;;;;;;4187:18;;4251:30;;;;4187:18;;-1:-1:-1;4251:30:16;-1:-1:-1;4048:21:16;-1:-1:-1;4657:1:16;4644:15;;4641:1;4637:23;4048:21;4637:23;4705:32;;;;;;;;:::i;:::-;;;;;;;;;;;:::i;:::-;;;-1:-1:-1;;4876:53:16;;;;4843:30;;;;:86;-1:-1:-1;3544:3087:16;;;5128:29;;;;5296:20;;5278:38;;5274:143;;5352:41;;-1:-1:-1;;;5352:41:16;;;;;;;;;;;5274:143;5521:42;5593:13;5607:14;5593:29;;;;;;;;:::i;:::-;;;;;;;;;;;5763:26;;5862:38;;;;5763:26;;-1:-1:-1;5862:38:16;-1:-1:-1;5593:29:16;-1:-1:-1;6299:1:16;6286:15;;6283:1;6279:23;5593:29;6279:23;6347:40;;;;;;;;:::i;:::-;;;;;;;;;;;:::i;:::-;;;-1:-1:-1;;6561:27:16;;;;6493:38;;;;:118;-1:-1:-1;3544:3087:16;6733:29;6753:8;9961:1;-1:-1:-1;9948:15:16;9694:287;6733:29;6728:113;;6794:27;;-1:-1:-1;;;6794:27:16;;;;;;;;;;;6728:113;6940:34;;6936:358;;7081:193;7120:16;:27;;;7174:20;7221:16;:30;;;7081:12;:193::i;:::-;2234:5075;;;;;;2181:5128;2229:3;;2181:5128;;;;7380:9;7375:1789;7399:19;7395:1;:23;7375:1789;;;7493:34;7530:14;7545:1;7530:17;;;;;;;;:::i;:::-;;;;;;;7493:54;;7645:13;:23;;;-1:-1:-1;;;;;7645:28:16;7672:1;7645:28;7641:85;;7698:8;;;7641:85;7869:24;;8032:29;;;;:36;7805:38;8160:423;8184:10;8180:1;:14;8160:423;;;8331:118;8381:15;:29;;;8411:1;8381:32;;;;;;;;:::i;:::-;;;;;;;:41;;;9961:1;-1:-1:-1;9948:15:16;9694:287;8331:118;8301:263;;;8507:33;;-1:-1:-1;;;;;;8507:33:16;;;;;;;;;;;8301:263;8196:3;;8160:423;;;-1:-1:-1;;8686:21:16;;;;:28;8803:9;8798:351;8822:10;8818:1;:14;8798:351;;;8969:54;8989:15;:21;;;9011:1;8989:24;;;;;;;;:::i;8969:54::-;8939:191;;;9081:25;;-1:-1:-1;;;9081:25:16;;;;;;;;;;;8939:191;8834:3;;8798:351;;;;7425:1739;;;7375:1789;7420:3;;7375:1789;;;;1813:7362;;1566:7616;;:::o;6186:9859:25:-;6527:25;;;;6581:23;;;;6999:30;;;14743:4:10;6999:30:25;;;;;;;;;6507:17;;6999:30;;;;;;;;-1:-1:-1;;;9170:21:25;;;;:28;6972:57;;-1:-1:-1;8761:9:25;;9144:23;9346:1908;9370:15;9366:1;:19;9346:1908;;;9456:26;9485:15;:21;;;9507:1;9485:24;;;;;;;;:::i;:::-;;;;;;;9456:53;;9684:15;9662:37;;;;;;;;:::i;:::-;:18;;:37;;;;;;;;:::i;:::-;;9658:117;;9731:24;;-1:-1:-1;;;9731:24:25;;;;;;;;;;;9658:117;9980:14;9997:307;10038:9;:21;;;10086:9;:19;;;10132:9;10168:11;10206:9;10242:7;10276:5;9997:14;:307::i;:::-;10579:26;10564:42;;10527:143;-1:-1:-1;10808:29:25;10793:45;;10756:149;;;11113:23;;11159:26;;;;11040:198;;10568:9;;11208:11;11040:198;;;:::i;:::-;-1:-1:-1;9387:3:25;;9346:1908;;;-1:-1:-1;;;13149:47:25;;;;:72;11367:9;;12719;;11342:22;13382:2314;13406:23;13402:1;:27;13382:2314;;;13508:42;13576:15;:29;;;13606:1;13576:32;;;;;;;;:::i;:::-;;;;;;;13508:119;;13730:14;13747:290;13784:17;:29;;;13836:17;:27;;;13886:9;13918:11;13952:9;13984:7;14014:4;13747:14;:290::i;:::-;14308:26;14285:50;;14252:139;;;14730:34;14640:155;;14604:218;14547:29;14524:53;;14491:354;13730:307;-1:-1:-1;;14969:26:25;;:45;;;;;;;;:::i;:::-;;14965:419;;15134:14;15125:6;:23;15121:114;;;15184:27;;-1:-1:-1;;;15184:27:25;;;;;;;;;;;15121:114;15358:6;15340:24;;;;14965:419;15486:194;15535:17;15575:10;15608:19;15650:11;15486:26;:194;;:::i;:::-;-1:-1:-1;;13431:3:25;;13382:2314;;;;12198:3509;;15800:28;15816:11;15800:15;:28::i;:::-;15900:19;;15896:142;;15977:49;15998:10;16011:14;15977:12;:49::i;16704:884::-;17026:29;17104:5;17090:19;;17213:35;17300:13;17283:30;;17488:4;-1:-1:-1;;;;;17413:167:25;17466:7;-1:-1:-1;;;;;17413:167:25;;17442:9;17507;17531:10;17556:13;17413:167;;;;;;;;;:::i;:::-;;;;;;;;16945:643;;16704:884;;;;;;:::o;11800:213:22:-;11851:7;11923:9;11906:13;:26;:99;;11981:24;2816:193:9;;;2845:24;2816:193;;;43935:25:39;2888:10:9;43976:18:39;;;43969:34;;;;2917:13:9;44019:18:39;;;44012:34;2949:13:9;44062:18:39;;;44055:34;2989:4:9;44105:19:39;;;44098:61;2737:7:9;;43907:19:39;;2816:193:9;;;;;;;;;;;;2792:228;;;;;;2785:235;;2680:348;;11906:99:22;-1:-1:-1;11948:17:22;;11800:213::o;13520:25582:3:-;13915:21;:19;:21::i;:::-;14031:59;14043:10;:20;;;14065:10;:18;;;14085:4;14031:11;:59::i;:::-;;14448:34;:32;:34::i;:::-;14577:189;14658:31;;;;:10;:31;:::i;:::-;:38;;14711:10;:44;;;14577:66;:189::i;:::-;14833:17;15989:16;16008:28;15989:47;;16519:8;16476:41;16469:59;16639:16;16575:41;16546:128;17139:10;17081:35;17020:38;16985:183;17540:8;17481:36;17416:42;17381:186;17920:29;17852:41;17816:156;17754:39;17725:266;18345:44;18310:98;18693:7;18666:25;18662:39;18593:46;18567:153;19174:1;19076:44;19033:114;19003:195;18956:24;18927:290;19466:7;19419:24;19393:99;19365:127;;19622:16;19596:24;19589:50;19976:9;19918:35;19875:19;19849:24;19845:50;19810:194;20830:39;21207:28;21143:41;21114:140;21362:25;21301:38;21272:134;21476:1;21431:43;21424:54;21675:50;21640:104;21611:133;;21771:1;21826:3444;21839:25;21836:1;21833:32;21826:3444;;;22314:1;22287:25;22283:33;22214:42;22184:155;22636:7;22585:24;22514:44;22475:191;22973:25;22922:24;22853:42;22814:207;23309:7;23260:22;23230:109;23204:135;;23696:29;23624:41;23584:168;23535:22;23502:273;24339:17;24288:24;24258:121;24230:149;;24554:28;24503:24;24470:135;24808:25;24773:7;24747:24;24743:38;24710:146;25220:8;25169:24;25089:26;25034:24;25000:142;24961:290;-1:-1:-1;21901:1:3;21894:9;21826:3444;;;25936:7;25932:1;25905:25;25901:33;25897:47;25831:39;25795:172;25751:21;25722:264;26479:44;26444:98;26415:127;;26596:1760;26609:25;26606:1;26603:32;26596:1760;;;26954:1;26927:25;26923:33;26854:42;26824:155;26792:187;;27425:17;27374:24;27344:121;27316:149;;27640:28;27589:24;27556:135;27894:25;27859:7;27833:24;27829:38;27796:146;28306:8;28255:24;28175:26;28120:24;28086:142;28047:290;26671:1;26664:9;26596:1760;;;26600:2;;;;16186:12185;28881:16;28900:20;28881:39;;29247:8;29212:33;29205:51;29379:15;29344:33;29337:58;29901:10;29851:27;29798:30;29763:167;30198:7;30147:28;30090:34;30055:169;30534:21;30474:33;30438:140;30414:1;30385:212;30925:7;30922:1;30912:21;30878:32;30871:63;31364:7;31266:44;31223:114;31193:201;31132:38;31106:307;31525:1;31499:24;31492:35;31654:15;31644:7;31618:24;31614:38;31607:63;32056:10;32006:27;31957:25;31931:24;31927:56;31892:193;-1:-1:-1;;33241:24:3;33228:38;-1:-1:-1;;;;;1885:18:15;;33159:15:3;1885:18:15;;;:9;:18;;;;;;33525:15:3;33650:29;33643:47;;;33377:38;;-1:-1:-1;33959:8:3;33912:24;33861:28;33826:160;34183:21;34177:28;34114:40;34085:139;34353:9;34321:30;34314:49;34645:9;34596:26;34543:30;34508:165;34810:7;34780:28;34773:45;34986:17;34934:29;34902:120;34889:133;;33566:1471;;;36495:7;36427:44;36414:58;36388:133;36344:25;36322:214;36650:9;36636:12;36629:31;36817:8;36783:31;36769:12;36765:50;36758:68;37060:32;37008;36994:12;36990:51;36922:185;37270:40;37210;37196:12;37192:59;37121:204;37753:17;37685:44;37672:58;37646:143;37604:23;37582:222;38476:21;38463:35;38363:24;38350:38;38250:23;38160:8;38068:12;37980:533;;;38585:1;38575:8;38568:19;38690:191;38740:9;38764:10;:19;;;38798:9;38822:10;:18;;;;;;;;;;:::i;:::-;38855:15;;;;;;;;:::i;:::-;38690:35;:191::i;:::-;38957:137;39006:9;39030:18;;;;;;;;:::i;:::-;39063:20;;;;:10;:20;:::i;:::-;38957:137;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;38957:34:3;;-1:-1:-1;;;38957:137:3:i;:::-;13826:25276;13520:25582;;;;;;:::o;4890:3612:19:-;5214:24;;5210:3285;;5336:22;5578:21;5572:28;5554:46;;-1:-1:-1;;;5698:14:19;5691:49;6025:35;5937:42;5896:14;5866:136;5837:242;6364:38;6276:42;6235:14;6205:136;6176:245;6601:8;6541:36;6525:14;6521:57;6492:136;6801:5;6744:33;6728:14;6724:54;6695:130;7007:4;6951:32;6935:14;6931:53;6902:128;7170:2;7137:30;7121:14;7117:51;7110:63;7362:10;7300:38;7284:14;7280:59;7251:140;7575:6;7517:34;7501:14;7497:55;7468:132;7680:142;7723:10;7752:14;14620:5:10;7680:24:19;:142::i;:::-;5240:2594;5210:3285;;;7949:15;7937:8;:27;;;;;;;;:::i;:::-;;7933:551;;8064:6;8074:1;8064:11;8060:96;;8107:29;;-1:-1:-1;;;8107:29:19;;;;;;;;;;;8060:96;8246:51;8269:5;8276:4;8282:2;8286:10;8246:22;:51::i;:::-;7933:551;;;8408:60;8432:5;8439:4;8445:2;8449:10;8461:6;8408:23;:60::i;39633:2296:3:-;39899:9;40036:20;39874:22;40230:1068;40254:25;40250:1;:29;40230:1068;;;40360:48;40434:20;;40455:1;40434:23;;;;;;;:::i;:::-;;;;;;;;-1:-1:-1;;40614:26:3;;40728:42;;;40724:125;;;40802:27;;-1:-1:-1;;;40802:27:3;;;;;;;;;;;40724:125;40933:131;40968:29;;;;;;;;:::i;:::-;41020:25;40933:12;:131::i;:::-;41239:43;;;;-1:-1:-1;40281:3:3;;40230:1068;;;;41395:14;41386:6;:23;41382:90;;;41433:27;;-1:-1:-1;;;41433:27:3;;;;;;;;;;;41382:90;41527:24;41540:2;41544:6;41527:12;:24::i;:::-;41660:6;41643:14;:23;41639:283;;;41837:58;41858:10;41888:6;41871:14;:23;41837:12;:58::i;:::-;39798:2131;;39633:2296;;;;:::o;12478:1126:19:-;12782:59;12817:11;12830:10;12782:34;:59::i;:::-;12906:10;12902:695;;13022:6;13032:1;13022:11;13018:88;;13061:29;;-1:-1:-1;;;13061:29:19;;;;;;;;;;;13018:88;13188:51;13211:5;13218:4;13224:2;13228:10;13188:22;:51::i;12902:695::-;13341:244;13367:10;13396:11;13426:22;13467:5;13491:4;13514:2;13535:10;13564:6;13341:7;:244::i;14590:1060::-;14886:28;14907:6;14886:20;:28::i;:::-;14993:59;15028:11;15041:10;14993:34;:59::i;:::-;15117:10;15113:530;;15224:60;15248:5;15255:4;15261:2;15265:10;15277:6;15224:23;:60::i;15113:530::-;15386:245;15412:10;15441:11;15471:23;15513:5;15537:4;15560:2;15581:10;15610:6;15386:7;:245::i;42486:3610:3:-;42762:12;42785:10;42888:13;42912:14;43107:18;43227:11;43223:833;;;43340:7;;-1:-1:-1;43371:10:3;;-1:-1:-1;43491:21:3;;;;;;;;:::i;:::-;43483:29;-1:-1:-1;;;43598:22:3;;;;43544:26;;;;43223:833;;;43742:10;;-1:-1:-1;43776:7:3;;-1:-1:-1;43887:29:3;;;;:10;:29;:::i;:::-;43879:37;-1:-1:-1;;;44010:30:3;;;;43948:34;;;;43223:833;44131:15;;44127:85;;44174:22;;-1:-1:-1;;;44174:22:3;;;;;;;;;;;44127:85;-1:-1:-1;44650:7:3;44633:25;;44577:33;44551:126;44520:172;44293:18;44845:31;;;;:10;:31;:::i;:::-;:38;;44794:100;;44964:9;44959:971;44983:25;44979:1;:29;44959:971;;;45078:48;45148:31;;;;:10;:31;:::i;:::-;45180:1;45148:34;;;;;;;:::i;:::-;;;;;;;;-1:-1:-1;;45250:26:3;;45369:87;;;;45405:35;45415:25;45405:35;;:::i;:::-;;;45369:87;45550:227;45583:5;45607:4;45630:29;;;;;;;;:::i;:::-;45678:25;45722:10;45751:11;45550:14;:227::i;:::-;-1:-1:-1;;45900:3:3;;44959:971;;;;46024:64;46039:5;46046:4;46052:2;46056:6;46064:10;46076:11;46024:14;:64::i;:::-;42676:3420;;;;;;42486:3610;;;;:::o;17259:448:19:-;14786:4:10;17386:11:19;:18;:38;17382:77;;17259:448;:::o;17382:77::-;17538:29;17570:38;17596:11;22395:26;22378:44;22354:83;;22080:375;17570:38;17538:70;;17655:44;17664:21;17687:11;17655:8;:44::i;:::-;17319:388;17259:448;:::o;4789:1187:1:-;4923:16;5043:11;5030:9;:24;5026:69;;-1:-1:-1;5078:5:1;5071:12;;5026:69;5445:11;5434:9;5427:5;5420:37;5417:171;;;-1:-1:-1;;;5484:1:1;5477:42;5547:25;5544:1;5537:36;5417:171;5690:27;5720:17;5728:9;5720:5;:17;:::i;:::-;5921:37;;;;;4789:1187;-1:-1:-1;;;;4789:1187:1:o;1638:2326::-;1833:14;1956:9;1941:11;:24;1937:1923;;2358:19;;;2490:15;:27;;;2632:18;;;2061:16;2836:19;2490:27;2836:9;:19;:::i;:::-;2791:23;2805:9;2791:11;:23;:::i;:::-;2790:66;;;;:::i;:::-;2759:98;;3712:7;3676:8;3666:7;3645:19;3641:33;3637:48;3607:135;3256:19;3249:27;3242:35;3216:545;3206:555;;3835:13;;;;;;1937:1923;-1:-1:-1;3947:9:1;;1638:2326;-1:-1:-1;;;;1638:2326:1:o;1726:3902:21:-;1955:26;;:::i;:::-;2091:27;;;:66;;-1:-1:-1;2122:35:21;;2091:66;2073:174;;;2191:44;;-1:-1:-1;;;2191:44:21;;;;;;;;;;;2073:174;2303:39;;:::i;:::-;2433:159;2492:14;2521:23;;2433:159;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;2559:22;2433:44;:159::i;:::-;2716:27;;2946:130;;;;;;;;;;;;;;;;;;;2997:14;;2946:130;3026:15;;;;;;2676:37;;2946:130;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;3056:9;2946:36;:130::i;:::-;3214:26;;3187:53;;;;;;;;:::i;:::-;:14;;:23;:53;;;;;;;;:::i;:::-;;;:117;;;;3281:17;:23;;;-1:-1:-1;;;;;3257:47:21;:9;:14;;;:20;;;-1:-1:-1;;;;;3257:47:21;;;3187:117;:191;;;;3350:17;:28;;;3321:9;:14;;;:25;;;:57;;3187:191;3169:309;;;3412:54;;-1:-1:-1;;;3412:54:21;;;;;;;;;;;3169:309;3591:9;:14;;;:21;;;3564:17;:24;;;:48;3560:1786;;;3710:43;3775:23;;3799:1;3775:26;;;;;;;:::i;:::-;;;;;;3710:106;;;;;;;;;;:::i;:::-;;;4314:9;:14;;;:21;;;4266:17;:24;;;:69;4090:14;4105:15;:26;;;4090:42;;;;;;;;:::i;:::-;;;;;;;:75;;;:111;;;4202:15;:25;;;4090:138;;;;;;;;:::i;:::-;;;;;;;;;;;:172;;;;:246;;;;4472:14;;:21;;;4445:24;;;:48;-1:-1:-1;3560:1786:21;;;4599:43;4645:15;;4661:1;4645:18;;;;;;;:::i;:::-;;;;;;4599:64;;;;;;;;;;:::i;:::-;;;5152:17;:24;;;5107:9;:14;;;:21;;;:69;4939:14;4954:15;:26;;;4939:42;;;;;;;;:::i;:::-;;;;;;;:75;;;:103;;;5043:15;:25;;;4939:130;;;;;;;;:::i;:::-;;;;;;;:164;;:238;;;;;5310:17;:24;;;5286:9;:14;;;:21;;:48;;;;;4511:835;3560:1786;5428:27;;;;;5401:14;;-1:-1:-1;;;;;5401:54:21;;;:24;;:54;-1:-1:-1;1726:3902:21;;;;;;;:::o;29167:4619:24:-;29470:21;;29325:29;;29470:21;-1:-1:-1;;;;;29582:23:24;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;29582:23:24;;29564:41;;29802:9;29797:1614;29821:11;29817:1;:15;29797:1614;;;29910:34;29947:14;29962:1;29947:17;;;;;;;;:::i;:::-;;;;;;;29910:54;;30068:13;:23;;;-1:-1:-1;;;;;30068:28:24;30095:1;30068:28;30064:328;;30364:8;;;30064:328;30482:4;30461:15;30477:1;30461:18;;;;;;;;:::i;:::-;:25;;;:18;;;;;;;;;;;:25;30652:24;;:38;;;30843:20;;30586:40;30962:434;30986:23;30982:1;:27;30962:434;;;31116:19;31138:13;31152:1;31138:16;;;;;;;;:::i;:::-;;;;;;;:28;;;31116:50;;31263:11;31278:1;31263:16;31259:118;;31315:38;;-1:-1:-1;;;31315:38:24;;;;;36440:25:39;;;36481:18;;;36474:34;;;36524:18;;;36517:34;;;36413:18;;31315:38:24;36238:319:39;31259:118:24;-1:-1:-1;31011:3:24;;30962:434;;;;29839:1572;;;29797:1614;29834:3;;29797:1614;;;-1:-1:-1;31928:30:24;;;14743:4:10;31928:30:24;;;;;;;;;31524:9;;31499:22;;31928:30;;;;;;;;;;;-1:-1:-1;;32073:17:24;;31901:57;;-1:-1:-1;32047:23:24;32144:1151;32168:15;32164:1;:19;32144:1151;;;32275:26;32304:10;32315:1;32304:13;;;;;;;;:::i;:::-;;;;;;;;;;;32359:14;;32304:13;;-1:-1:-1;32332:24:24;32472:13;;:32;;;;;;;;:::i;:::-;;32468:444;;32621:14;32607:4;:11;;;:28;32603:111;;;32667:27;;-1:-1:-1;;;32667:27:24;;;;;;;;;;;32603:111;32866:4;:11;;;32848:29;;;;32468:444;32990:152;33018:4;33041:9;:17;;;33077:9;:20;;;33116:11;32990:9;:152::i;:::-;-1:-1:-1;;33265:3:24;;32144:1151;;;;33388:28;33404:11;33388:15;:28::i;:::-;33511:19;;33507:101;;33547:49;33568:10;33581:14;33547:12;:49::i;:::-;33660:23;2393:1:10;1355:16:28;:31;1262:132;33660:23:24;33754:24;;;;29167:4619;;;;:::o;6854:2224:21:-;7109:26;;:::i;:::-;7416:21;:28;7448:1;7416:33;7412:127;;7518:4;7477:46;;-1:-1:-1;;;7477:46:21;;;;;;;;:::i;7412:127::-;7637:10;7629:4;:18;;;;;;;;:::i;:::-;;7625:1109;;7738:14;;-1:-1:-1;;;;;7738:45:21;;:24;;;;:45;7883:168;7942:14;7979:21;7738:9;7883:36;:168::i;:::-;7625:1109;;;8281:176;8348:14;8385:21;8429:9;8281:44;:176::i;:::-;8566:10;8546:17;;;:30;8676:20;;;:42;;;7625:1109;8911:14;;:21;;;:14;:26;8907:153;;8986:1;8958:17;;;:30;;;9007:14;;:24;;:37;6854:2224;;;;;;;:::o;2875:433:2:-;3200:30;3167;:63;3163:138;;;3254:35;;-1:-1:-1;;;3254:35:2;;;;;;;;;;;1093:10140:30;1317:12;1522:1;1519;1512:12;1597:5;1696:9;1690:16;2003:7;1992:9;1988:23;2148:22;2142:29;2623:15;2606;2602:37;2718:19;2891:1;2882:7;2879:14;2869:3454;;3045:24;3034:9;3030:40;2998:95;3486:24;3475:9;3471:40;3465:47;3437:1;3406:129;3401:134;;3637:7;3634:838;;;3891:17;3841:18;3831:8;3827:33;3793:142;3788:147;;-1:-1:-1;;;;;4310:18:30;4272:150;4216:24;4205:9;4201:40;4164:285;3634:838;4660:1;4649:9;4642:20;4876:6;4852:22;4845:38;5550:7;5484:1;5402:19;5320:22;5239:20;5203:5;5162:458;-1:-1:-1;5729:57:30;;;5867:34;;;6033:24;6018:40;;5985:141;-1:-1:-1;;6296:8:30;2869:3454;6597:27;;6626:13;;;6593:47;;-1:-1:-1;6593:47:30;;-1:-1:-1;6750:4030:30;;7075:46;7030:22;7001:139;7316:48;7284:9;7258:125;7526:11;7520:18;7714:46;7682:9;7656:123;7918:9;7912:16;-1:-1:-1;;;8031:11:30;8024:54;8160:6;8149:9;8142:25;8587:7;8563:1;8473:44;8431:15;8401:139;8367:11;8338:6;8310:5;8277:336;8266:347;;8713:7;8710:1724;;;-1:-1:-1;;;8896:1:30;8890:8;8887:47;8877:1538;;9057:6;9045:19;9042:258;;;-1:-1:-1;;;9159:1:30;9152:47;9239:33;9236:1;9229:44;9042:258;9440:1;9422:15;9405;9401:37;9398:44;9395:296;;;-1:-1:-1;;;9558:1:30;9551:43;9634:29;9631:1;9624:40;9395:296;9819:42;9816:1;9811:51;9771:412;;-1:-1:-1;;;9989:1:30;9982:40;10087:1;10059:26;10052:37;10129:26;10126:1;10119:37;9771:412;-1:-1:-1;;;10296:1:30;10289:40;10365:26;10362:1;10355:37;8877:1538;10572:57;;;10647:52;;;;10717:48;;6750:4030;;;;;10842:7;10837:389;;10932:34;:32;:34::i;:::-;-1:-1:-1;;;11098:1:30;11091:47;11166:33;11163:1;11156:44;1375:645:35;1511:10;1630:15;1618:9;:27;:57;;;;1660:15;1649:7;:26;;1618:57;1614:322;;;1770:15;1766:76;;;1813:13;;-1:-1:-1;;;1813:13:35;;;;;;;;;;;1766:76;-1:-1:-1;1919:5:35;1912:12;;1614:322;-1:-1:-1;2008:4:35;1375:645;;;;;:::o;4238:1717:36:-;4715:1;4702:9;4694:18;;;;;;;;:::i;:::-;:22;:57;;;;-1:-1:-1;4733:10:36;-1:-1:-1;;;;;4733:18:36;;;;4694:57;:95;;;;-1:-1:-1;4768:10:36;-1:-1:-1;;;;;4768:21:36;;;;4694:95;4676:1272;;;4908:23;;;;:30;:35;:85;;;;-1:-1:-1;4964:24:36;;:29;4908:85;4886:1051;;;5088:53;5106:4;5112:9;5123:7;5132:8;5088:17;:53::i;:::-;4886:1051;;;5343:12;5358:405;5392:4;5468:53;;;5548:9;5584:10;5621:13;5661:16;5704:17;5419:325;;;;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;5419:325:36;;;;;;;;;;;;;;-1:-1:-1;;;;;5419:325:36;-1:-1:-1;;;;;;5419:325:36;;;;;;;;;;5358:11;:405::i;:::-;5343:420;;5865:56;5902:7;5911:9;5865:36;:56::i;4886:1051::-;4238:1717;;;;;;;;:::o;10325:2180:16:-;10536:12;10740:4;10737:1;10730:15;10875:7;10872:1;10862:21;11101:7;11094:5;11090:19;11330:5;11324:12;11321:1;11317:20;11311:4;11307:31;11199:1038;11363:3;11357:4;11354:13;11199:1038;;;11562:11;;11818:28;;;11815:1;11811:36;12031:29;;;12098:7;12085:21;;;12078:41;12213:8;12210:1;12200:22;;11448:18;;;;11199:1038;;;-1:-1:-1;;12325:22:16;;;-1:-1:-1;12325:22:16;12436:62;;12472:14;;-1:-1:-1;;;12472:14:16;;;;;;;;;;;1908:1850:19;2163:15;2146:13;;:32;;;;;;;;:::i;:::-;;2142:1609;;2302:15;;;;2288:10;;;;-1:-1:-1;;;;;2280:37:19;;2279:44;2275:114;;2351:22;;-1:-1:-1;;;2351:22:19;;;;;;;;;;;2275:114;2466:41;2479:4;:14;;;2495:4;:11;;;2466:12;:41::i;:::-;2142:1609;;;2546:14;2529:13;;:31;;;;;;;;:::i;:::-;;2525:1226;;2636:15;;;;:20;2632:90;;2684:22;;-1:-1:-1;;;2684:22:19;;;;;;;;;;;2632:90;2810:203;2843:4;:10;;;2872:4;2895;:14;;;2928:4;:11;;;2958:10;2987:11;2810:14;:203::i;2525:1226::-;3052:15;3035:13;;:32;;;;;;;;:::i;:::-;;3031:720;;3156:238;3190:4;:10;;;3219:4;3242;:14;;;3275:4;:15;;;3309:4;:11;;;3339:10;3368:11;3156:15;:238::i;3031:720::-;3500:239;3535:4;:10;;;3564:4;3587;:14;;;3620:4;:15;;;3654:4;:11;;;3684:10;3713:11;3500:16;:239::i;6789:889:1:-;7036:14;7159:9;7144:11;:24;7140:531;;7240:47;7253:9;7264:11;7277:9;7240:12;:47::i;:::-;7231:56;;7140:531;;;7410:249;7449:49;7462:9;7473:11;7486;7449:12;:49::i;:::-;7517:47;7530:9;7541:11;7554:9;7517:12;:47::i;:::-;7583:9;7611:7;7637;7410:20;:249::i;:::-;7401:258;;7140:531;6789:889;;;;;;;;;:::o;8742:762:19:-;8877:28;8898:6;8877:20;:28::i;:::-;9000:12;9160:1;9157;9154;9151;9143:6;9139:2;9132:5;9127:35;9116:46;;9223:7;9218:279;;9324:34;:32;:34::i;:::-;9446:39;;-1:-1:-1;;;9446:39:19;;-1:-1:-1;;;;;43589:32:39;;9446:39:19;;;43571:51:39;43638:18;;;43631:34;;;43544:18;;9446:39:19;43389:282:39;9218:279:19;8809:695;8742:762;;:::o;4209:2557:2:-;6503:31;6394;6381:45;6281:272;5527:26;5514:40;5689:24;5901:44;5854:122;6087:25;5740:399;5659:503;5422:759;4964:27;4951:41;5015:25;4926:133;5197:42;5184:56;5263:40;5159:163;4824:513;5369:827;6228:340;;6670:89;;6711:36;;-1:-1:-1;;;6711:36:2;;;;;;;;;;;6670:89;4267:2499;4209:2557::o;1292:560:36:-;1623:1;1610:9;1602:18;;;;;;;;:::i;:::-;:22;:57;;;;-1:-1:-1;1641:10:36;-1:-1:-1;;;;;1641:18:36;;;;1602:57;:95;;;;-1:-1:-1;1676:10:36;-1:-1:-1;;;;;1676:21:36;;;;1602:95;1584:261;;;1780:53;1798:4;1804:9;1815:7;1824:8;1780:17;:53::i;1593:1011:26:-;1815:31;1849:23;;;:12;:23;;;;;1944:223;1862:9;1849:23;2027:4;;1944:18;:223::i;:::-;-1:-1:-1;2267:23:26;;;;2262:104;;2307:47;2324:7;2333:9;2344;2307:16;:47::i;:::-;2569:27;;;-1:-1:-1;;;1593:1011:26:o;20251:1399:19:-;10255:21:22;10249:28;;9865:19;-1:-1:-1;;;10465:41:22;20474:15:19;10455:52:22;;;10605:7;10598:27;;;10013;10723:41;;11160:31;11037:28;10941:269;11406:48;;;;-1:-1:-1;;;;;10873:468:22;20474:44:19;;20531:12;20554:13;20705:1;20702;20695:12;20993:7;20973:1;20942:12;20909:14;20889:1;20863:7;20839:5;20816:199;20805:210;;21120:1;21114:8;21104:18;;21184:7;21179:260;;21284:34;:32;:34::i;:::-;21398:29;;-1:-1:-1;;;21398:29:19;;-1:-1:-1;;;;;44334:32:39;;21398:29:19;;;44316:51:39;44289:18;;21398:29:19;44170:203:39;21179:260:19;-1:-1:-1;;;;;;21529:43:19;;-1:-1:-1;;;21529:43:19;21525:118;;21596:35;;-1:-1:-1;;;21596:35:19;;;;;44552:25:39;;;-1:-1:-1;;;;;44613:32:39;;44593:18;;;44586:60;44525:18;;21596:35:19;44378:274:39;11779:5026:32;12107:5;12095:18;12085:258;;-1:-1:-1;;;12141:24:32;12134:60;12247:5;12219:26;12212:41;12304:23;12278:24;12271:57;12085:258;12545:21;12539:28;-1:-1:-1;;;12665:27:32;12658:66;12775:4;12745:28;12738:42;12829:2;12801:26;12794:38;12881:10;12853:26;12846:46;13181:1;13161;13116:26;13070:27;13050:1;13026:5;13002;12979:218;13265:7;13255:3335;;13419:16;13416:2376;;;13868:7;13827:13;13809:16;13805:36;13775:123;14185:7;14173:10;14169:24;14316:15;14303:11;14299:33;14448:10;14431:15;14428:31;14425:786;;;14644:32;;;14715:11;14602:159;15069:26;14964:27;;;14884:37;;;14838:192;14796:334;14564:597;14495:693;14425:786;15460:5;15443:14;15437:4;15433:25;15430:36;15427:346;;;15597:16;15594:1;15591;15576:38;15733:16;15730:1;15723:27;15427:346;;;;13416:2376;-1:-1:-1;;;15908:41:32;15879:155;16104:5;16059:43;16052:58;16179:4;16135:42;16128:56;16251:2;16209:40;16202:52;16321:10;16279:40;16272:60;16403:1;16357:44;16350:55;16516:40;16452:41;16423:152;13255:3335;-1:-1:-1;16671:21:32;16664:41;-1:-1:-1;;16785:1:32;16775:8;16768:19;-1:-1:-1;;11779:5026:32:o;17468:5749::-;17823:5;17811:18;17801:258;;-1:-1:-1;;;17857:24:32;17850:60;17963:5;17935:26;17928:41;18020:23;17994:24;17987:57;17801:258;18255:21;18249:28;18313:8;18307:15;18358:8;18352:15;18403:8;18397:15;-1:-1:-1;;;18532:32:32;18507:125;18688:4;18653:33;18646:47;18747:2;18714:31;18707:43;18804:10;18771:31;18764:51;18873:6;18836:35;18829:51;18978:43;18919:40;18894:142;19099:1;19057:40;19050:51;19400:1;19380;19330:31;19279:32;19259:1;19235:5;19211;19188:228;19484:7;19474:3340;;19638:16;19635:2376;;;20087:7;20046:13;20028:16;20024:36;19994:123;20404:7;20392:10;20388:24;20535:15;20522:11;20518:33;20667:10;20650:15;20647:31;20644:786;;;20863:32;;;20934:11;20821:159;21288:26;21183:27;;;21103:37;;;21057:192;21015:334;20783:597;20714:693;20644:786;21679:5;21662:14;21656:4;21652:25;21649:36;21646:346;;;21816:16;21813:1;21810;21795:38;21952:16;21949:1;21942:27;21646:346;;;;19635:2376;-1:-1:-1;;;22127:41:32;22098:155;22323:5;22278:43;22271:58;22398:4;22354:42;22347:56;22470:2;22428:40;22421:52;22540:10;22498:40;22491:60;22622:6;22576:44;22569:60;22740:40;22676:41;22647:152;19474:3340;-1:-1:-1;22837:8:32;22830:26;;;;22899:8;22892:26;22961:8;22954:26;23083:21;23076:41;-1:-1:-1;;23197:1:32;-1:-1:-1;23180:19:32;-1:-1:-1;;;17468:5749:32:o;16416:469:19:-;16618:29;16650:38;16676:11;22395:26;22378:44;22354:83;;22080:375;16650:38;16618:70;;16811:10;16786:21;:35;16782:96;;16838:28;16854:11;16838:15;:28::i;23471:2207::-;23741:16;14743:4:10;23918:11:19;:18;:41;23914:1031;;-1:-1:-1;24117:16:19;24097:37;;;24202:26;24185:44;;;24178:64;;;-1:-1:-1;;;24267:42:19;;;24260:60;;;;24384:28;24367:46;;24338:141;23987:1;24521:28;24504:46;;24497:64;;;23914:1031;;;-1:-1:-1;24764:28:19;24747:46;;24741:53;;24817:1;24715:122;24855:64;;;;23914:1031;25128:36;25082:25;25072:8;25068:40;25055:11;25051:58;25029:150;25213:8;25200:11;25193:29;25293:5;25260:30;25247:11;25243:48;25236:63;25369:4;25337:29;25324:11;25320:47;25313:61;25442:2;25412:27;25399:11;25395:45;25388:57;25556:10;25501:35;25488:11;25484:53;25459:122;25653:6;25619:31;25606:11;25602:49;25595:65;;24995:676;23471:2207;;;;;;;;:::o;3482:208:2:-;3617:6;3627:1;3617:11;3613:70;;3652:19;;-1:-1:-1;;;3652:19:2;;;;;;;;;;;10458:1000:19;10723:28;10744:6;10723:20;:28::i;:::-;10830:59;10865:11;10878:10;10830:34;:59::i;:::-;10954:10;10950:501;;11048:46;11070:5;11077:4;11083:2;11087:6;11048:21;:46::i;:::-;10950:501;;;11196:243;11222:10;11251:11;11281:21;11321:5;11345:4;11368:2;11397:1;11418:6;11196:7;:243::i;18426:1141::-;19115:28;19098:46;;19092:53;18923:8;18906:26;;;19168:25;19066:146;19019:28;18997:230;19332:66;19357:10;18906:26;18997:230;19332:24;:66::i;:::-;-1:-1:-1;;19529:19:19;19509:40;;-1:-1:-1;18426:1141:19:o;21592:10887:21:-;21999:372;;;-1:-1:-1;;;22152:1:21;22145:58;22314:41;22311:1;22304:52;22461:412;-1:-1:-1;;;22565:1:21;22558:32;22717:16;22697:18;22690:44;22839:18;22836:1;22829:29;22461:412;23006:7;22981:23;22977:37;23132:18;23126:25;23120:32;23264:14;23258:21;23246:10;23243:37;23233:121;;23301:38;;:::i;:::-;23612:7;23600:10;23596:24;23586:7;23570:14;23566:28;23562:59;23463:173;23897:41;23865:8;23859:15;23753:204;23729:243;24140:28;24119:18;24113:25;24109:60;24085:99;24295:19;24289:26;24278:9;24275:41;24265:125;;24337:38;;:::i;:::-;24766:7;24755:9;24751:23;24649:7;24628:19;24624:33;24532:261;24508:300;24911:1;25020;25177:30;25167:8;25163:45;25157:52;25154:528;;;-1:-1:-1;;25350:20:21;25324:47;;25437:16;;25665:1;25647:20;;;25541:14;;25154:528;25786:9;25780:16;25895:20;25889:27;25875:12;25868:49;26099:19;26077:20;26073:46;26067:53;26028:19;26014:12;26010:38;25985:150;26327:24;26305:20;26301:51;26295:58;26251:24;26237:12;26233:43;26208:160;26637:34;26590:20;26560:134;26532:181;26483:29;26469:12;26465:48;26440:288;26888:30;26857:12;26829:104;27137:7;27111:23;27105:30;27101:44;27059:23;27037:123;27265:4417;27296:6;27275:18;27272:31;27265:4417;;;27444:7;27424:18;27420:32;27398:54;;27569:18;27563:25;27557:32;27543:46;;27696:14;27690:21;27678:10;27675:37;27665:127;;27735:38;;:::i;:::-;28011:7;27999:10;27995:24;27960:7;27944:14;27940:28;27910:132;27882:179;27870:191;;28193:30;28183:8;28179:45;28173:52;28141:152;27265:4417;28141:152;28590:41;28554:8;28548:15;28439:215;28411:262;28388:285;;28813:7;28792:18;28786:25;28782:39;28776:46;28763:59;;28941:19;28935:26;28924:9;28921:41;28911:133;;28987:38;;:::i;:::-;29429:7;29418:9;29414:23;29310:7;29289:19;29285:33;29185:275;29157:322;29133:346;;29667:20;29622;29594:112;29819:9;29813:16;29805:6;29801:29;30092:9;30086:16;30079:24;30048:6;30037:9;30034:21;30031:1;30027:29;30002:122;29970:11;29947:196;29932:211;;30238:9;30228:19;;;30366:1;30355:9;30348:20;;31388:30;31337:20;31297:150;31260:8;31229:245;31008:29;30957:12;30915:157;30875:228;30749:29;30690:20;30648:165;30608:236;30575:555;30489:1008;30457:1210;;31610:38;;:::i;:::-;27265:4417;;;-1:-1:-1;;31770:20:21;31752:39;31745:55;;;31898:563;;;;32023:1;32010:11;32007:18;32004:310;;-1:-1:-1;;;32125:1:21;32118:44;32267:27;32264:1;32257:38;32004:310;32431:15;;:::i;:::-;31898:563;;;;;;;;21592:10887;;;:::o;9711:11114::-;11019:7;11002:15;10998:29;11145:18;11139:25;11133:32;11277:14;11271:21;11259:10;11256:37;11246:121;;11314:38;;:::i;:::-;11625:7;11613:10;11609:24;11599:7;11583:14;11579:28;11575:59;11476:173;11764:8;11758:15;11893:33;11882:9;11878:49;11854:88;12110:28;12089:18;12083:25;12079:60;12055:99;12265:11;12259:18;12248:9;12245:33;12235:117;;12299:38;;:::i;:::-;12712:7;12701:9;12697:23;12595:7;12582:11;12578:25;12486:253;12462:292;12857:1;12966;13088:30;13078:8;13074:45;13068:52;13065:532;;;-1:-1:-1;;13253:20:21;13235:39;;13340:16;;13466:1;13448:20;;;13568:14;;13065:532;13694:9;13688:16;13806:12;13800:19;13783:15;13776:44;13997:19;13983:12;13979:38;13973:45;13934:19;13917:15;13913:41;13888:145;14220:24;14206:12;14202:43;14196:50;14152:24;14135:15;14131:46;14106:155;14407:9;14401:16;14374:24;14363:9;14359:40;14352:66;14621:30;14610:9;14606:46;14600:53;14556:24;14545:9;14541:40;14516:152;14831:30;14797:15;14769:107;14753:123;;15064:7;15046:15;15040:22;15036:36;15002:15;14980:107;15192:4832;15223:6;15202:18;15199:31;15192:4832;;;15378:7;15358:18;15354:32;15332:54;;15503:18;15497:25;15491:32;15477:46;;15630:14;15624:21;15612:10;15609:37;15599:127;;15669:38;;:::i;:::-;15945:7;15933:10;15929:24;15894:7;15878:14;15874:28;15844:132;15816:179;15804:191;;16127:30;16117:8;16113:45;16085:92;16075:152;15192:4832;16075:152;16346:8;16340:15;16327:28;;16530:33;16494:9;16464:122;16436:169;16421:184;;16745:7;16724:18;16718:25;16714:39;16708:46;16695:59;;16895:11;16889:18;16878:9;16875:33;16843:165;;16951:38;;:::i;:::-;17369:7;17358:9;17354:23;17250:7;17237:11;17233:25;17133:267;17105:314;17089:330;;17591:20;17554:12;17526:104;17743:9;17737:16;17729:6;17725:29;18016:9;18010:16;18003:24;17972:6;17961:9;17958:21;17955:1;17951:29;17926:122;17894:11;17871:196;17856:211;;18162:9;18152:19;;;18290:1;18279:9;18272:20;;19728:30;19681:12;19637:152;19598:8;19565:251;19312:24;19262:9;19218:155;19176:230;19043:30;18993:9;18949:161;18907:236;18872:563;18684:24;18673:9;18669:40;18627:115;18584:9;18578:16;18543:228;18443:1019;18413:1426;18381:1628;;19952:38;;:::i;:::-;15192:4832;;;15196:2;;20139:6;20116:20;20104:9;20098:16;20094:43;20087:59;20247:11;20244:563;;;20369:1;20356:11;20353:18;20350:310;;-1:-1:-1;;;20471:1:21;20464:44;20613:27;20610:1;20603:38;20350:310;20777:15;;:::i;:::-;20244:563;;;;;;;;;9711:11114;;;:::o;1393:2286:23:-;1604:16;1601:2060;;;1976:7;1939:13;1921:16;1917:36;1891:111;2291:7;2267:21;2261:28;2257:42;2414:15;2401:11;2397:33;2538:10;2521:15;2518:31;2515:621;;;2680:32;;;2714:11;2676:50;3010:26;2913:27;;;2837:37;;;2795:180;2757:310;2642:452;2581:536;2515:621;3349:5;3332:14;3326:4;3322:25;3319:36;3316:330;;;3478:16;3475:1;3472;3457:38;3610:16;3607:1;3600:27;1860:641:36;2135:201;;;;;44888:25:39;;;2258:10:36;44967:18:39;;;44960:43;-1:-1:-1;;;;;45039:15:39;;45019:18;;;45012:43;45071:18;;;45064:34;;;2075:12:36;;2090:257;;2116:4;;-1:-1:-1;;;2176:35:36;44860:19:39;;2135:201:36;44657:447:39;2090:257:36;2075:272;;2437:56;2474:7;2483:9;2437:36;:56::i;718:422:23:-;828:12;1106:1;1086;1058:8;1052:15;1025:7;1015:8;1011:22;986:6;962:5;933:189;922:200;718:422;-1:-1:-1;;;718:422:23:o;6435:650:36:-;6603:7;6598:262;;6693:34;:32;:34::i;:::-;6815:33;;-1:-1:-1;;;6815:33:36;;;;;13363:25:39;;;13336:18;;6815:33:36;13217:177:39;6598:262:36;6954:55;-1:-1:-1;;;6954:18:36;:55::i;:::-;6950:128;;;7033:33;;-1:-1:-1;;;7033:33:36;;;;;13363:25:39;;;13336:18;;7033:33:36;13217:177:39;1355:9806:32;1791:21;1785:28;-1:-1:-1;;;1914:26:32;1907:64;2021:4;1992:27;1985:41;2074:2;2047:25;2040:37;2129:6;2098:29;2091:45;2838:7;2818:1;2774:25;2729:26;2709:1;2685:5;2661;2638:222;3348:10;3293:16;3286:24;3259:2;3241:16;3238:24;3234:1;3230;3224:8;3221:15;3217:46;3192:137;2972:401;3740:16;3733:24;3726:32;3717:7;3713:46;3703:7243;;4065:7;4055:5;4043:18;4036:26;4029:34;4025:48;4015:6706;;4156:7;4146:6248;;4257:10;4247:4845;;4450:16;4447:3380;;;5025:7;4972:13;4954:16;4950:36;4908:159;5438:7;5426:10;5422:24;5593:15;5580:11;5576:33;5749:10;5732:15;5729:31;5726:1316;;;6005:189;;;6245:11;5951:352;6852:26;6723:27;;;6462:206;;;6404:397;6350:575;5901:1067;5808:1199;5726:1316;7339:5;7322:14;7316:4;7312:25;7309:36;7306:490;;;7540:16;7537:1;7534;7519:38;7744:16;7741:1;7734:27;7306:490;;;;4447:3380;-1:-1:-1;;;7979:41:32;7938:191;8278:5;8200:43;8159:155;8462:4;8385:42;8344:153;8576:2;8534:40;8527:52;8658:1;8616:40;8609:51;8810:6;8731:44;8690:157;8994:40;8918:41;8877:188;4247:4845;-1:-1:-1;;;9309:47:32;9272:191;9606:5;9526:49;9489:149;9780:4;9701:48;9664:147;9951:2;9874:46;9837:143;10124:6;10043:50;10006:151;10298:46;10220:47;10183:188;4146:6248;-1:-1:-1;;;10507:24:32;10500:60;10617:5;10589:26;10582:41;10678:23;10652:24;10645:57;4015:6706;-1:-1:-1;;11027:21:32;11020:41;-1:-1:-1;;11141:1:32;11131:8;11124:19;-1:-1:-1;;1355:9806:32:o;4035:797:23:-;4103:4;4197:13;4427:7;4409:16;4406:29;4403:291;;4556:7;4553:1;4550;4535:29;-1:-1:-1;4677:1:23;4671:8;4403:291;-1:-1:-1;;;;;;4806:18:23;;;;;;;;;;;4035:797;-1:-1:-1;4035:797:23:o;-1:-1:-1:-;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;14:472:39:-;56:3;94:5;88:12;121:6;116:3;109:19;146:1;156:162;170:6;167:1;164:13;156:162;;;232:4;288:13;;;284:22;;278:29;260:11;;;256:20;;249:59;185:12;156:162;;;336:6;333:1;330:13;327:87;;;402:1;395:4;386:6;381:3;377:16;373:27;366:38;327:87;-1:-1:-1;468:2:39;447:15;-1:-1:-1;;443:29:39;434:39;;;;475:4;430:50;;14:472;-1:-1:-1;;14:472:39:o;491:220::-;640:2;629:9;622:21;603:4;660:45;701:2;690:9;686:18;678:6;660:45;:::i;716:180::-;775:6;828:2;816:9;807:7;803:23;799:32;796:52;;;844:1;841;834:12;796:52;-1:-1:-1;867:23:39;;716:180;-1:-1:-1;716:180:39:o;1317:127::-;1378:10;1373:3;1369:20;1366:1;1359:31;1409:4;1406:1;1399:15;1433:4;1430:1;1423:15;1449:253;1521:2;1515:9;1563:4;1551:17;;-1:-1:-1;;;;;1583:34:39;;1619:22;;;1580:62;1577:88;;;1645:18;;:::i;:::-;1681:2;1674:22;1449:253;:::o;1707:255::-;1779:2;1773:9;1821:6;1809:19;;-1:-1:-1;;;;;1843:34:39;;1879:22;;;1840:62;1837:88;;;1905:18;;:::i;1967:275::-;2038:2;2032:9;2103:2;2084:13;;-1:-1:-1;;2080:27:39;2068:40;;-1:-1:-1;;;;;2123:34:39;;2159:22;;;2120:62;2117:88;;;2185:18;;:::i;:::-;2221:2;2214:22;1967:275;;-1:-1:-1;1967:275:39:o;2247:196::-;2320:4;-1:-1:-1;;;;;2345:6:39;2342:30;2339:56;;;2375:18;;:::i;:::-;-1:-1:-1;2420:1:39;2416:14;2432:4;2412:25;;2247:196::o;2448:131::-;-1:-1:-1;;;;;2523:31:39;;2513:42;;2503:70;;2569:1;2566;2559:12;2584:134;2652:20;;2681:31;2652:20;2681:31;:::i;:::-;2584:134;;;:::o;2723:149::-;2797:20;;2846:1;2836:12;;2826:40;;2862:1;2859;2852:12;2877:566;2933:5;2981:4;2969:9;2964:3;2960:19;2956:30;2953:50;;;2999:1;2996;2989:12;2953:50;3021:22;;:::i;:::-;3012:31;;3066:35;3091:9;3066:35;:::i;:::-;3059:5;3052:50;3154:2;3143:9;3139:18;3126:32;3167:33;3192:7;3167:33;:::i;:::-;3232:7;3227:2;3220:5;3216:14;3209:31;;3300:2;3289:9;3285:18;3272:32;3267:2;3260:5;3256:14;3249:56;3365:2;3354:9;3350:18;3337:32;3332:2;3325:5;3321:14;3314:56;3431:3;3420:9;3416:19;3403:33;3397:3;3390:5;3386:15;3379:58;2877:566;;;;:::o;3448:728::-;3511:5;3564:3;3557:4;3549:6;3545:17;3541:27;3531:55;;3582:1;3579;3572:12;3531:55;3618:6;3605:20;3644:4;3668:73;3684:56;3737:2;3684:56;:::i;:::-;3668:73;:::i;:::-;3775:15;;;3837:4;3880:11;;;3868:24;;3864:33;;;3806:12;;;;3763:3;3909:15;;;3906:35;;;3937:1;3934;3927:12;3906:35;3973:2;3965:6;3961:15;3985:162;4001:6;3996:3;3993:15;3985:162;;;4067:37;4100:3;4095;4067:37;:::i;:::-;4055:50;;4125:12;;;;4018;;3985:162;;;-1:-1:-1;4165:5:39;;3448:728;-1:-1:-1;;;;;;;3448:728:39:o;4181:908::-;4245:5;4293:4;4281:9;4276:3;4272:19;4268:30;4265:50;;;4311:1;4308;4301:12;4265:50;4344:2;4338:9;4386:4;4378:6;4374:17;4457:6;4445:10;4442:22;-1:-1:-1;;;;;4409:10:39;4406:34;4403:62;4400:88;;;4468:18;;:::i;:::-;4504:2;4497:22;4537:6;-1:-1:-1;4537:6:39;4567:35;4592:9;4567:35;:::i;:::-;4559:6;4552:51;4655:2;4644:9;4640:18;4627:32;4668:33;4693:7;4668:33;:::i;:::-;4734:7;4729:2;4721:6;4717:15;4710:32;;4803:2;4792:9;4788:18;4775:32;4770:2;4762:6;4758:15;4751:57;4869:2;4858:9;4854:18;4841:32;4836:2;4828:6;4824:15;4817:57;4936:3;4925:9;4921:19;4908:33;4902:3;4894:6;4890:16;4883:59;4994:3;4983:9;4979:19;4966:33;5008;5033:7;5008:33;:::i;:::-;5069:3;5057:16;;;;5050:33;4181:908;;-1:-1:-1;;4181:908:39:o;5094:744::-;5165:5;5218:3;5211:4;5203:6;5199:17;5195:27;5185:55;;5236:1;5233;5226:12;5185:55;5272:6;5259:20;5298:4;5322:73;5338:56;5391:2;5338:56;:::i;5322:73::-;5429:15;;;5491:4;5534:11;;;5522:24;;5518:33;;;5460:12;;;;5417:3;5563:15;;;5560:35;;;5591:1;5588;5581:12;5560:35;5627:2;5619:6;5615:15;5639:170;5655:6;5650:3;5647:15;5639:170;;;5721:45;5762:3;5757;5721:45;:::i;:::-;5709:58;;5787:12;;;;5672;;5639:170;;5843:150;5918:20;;5967:1;5957:12;;5947:40;;5983:1;5980;5973:12;5998:1291;6060:5;6108:6;6096:9;6091:3;6087:19;6083:32;6080:52;;;6128:1;6125;6118:12;6080:52;6150:22;;:::i;:::-;6141:31;;6195:29;6214:9;6195:29;:::i;:::-;6188:5;6181:44;6257:38;6291:2;6280:9;6276:18;6257:38;:::i;:::-;6252:2;6245:5;6241:14;6234:62;6347:2;6336:9;6332:18;6319:32;-1:-1:-1;;;;;6411:2:39;6403:6;6400:14;6397:34;;;6427:1;6424;6417:12;6397:34;6463:66;6525:3;6516:6;6505:9;6501:22;6463:66;:::i;:::-;6458:2;6451:5;6447:14;6440:90;6583:2;6572:9;6568:18;6555:32;6539:48;;6612:2;6602:8;6599:16;6596:36;;;6628:1;6625;6618:12;6596:36;;6664:76;6736:3;6725:8;6714:9;6710:24;6664:76;:::i;:::-;6659:2;6652:5;6648:14;6641:100;;6774:46;6815:3;6804:9;6800:19;6774:46;:::i;:::-;6768:3;6761:5;6757:15;6750:71;6882:3;6871:9;6867:19;6854:33;6848:3;6841:5;6837:15;6830:58;6949:3;6938:9;6934:19;6921:33;6915:3;6908:5;6904:15;6897:58;7016:3;7005:9;7001:19;6988:33;6982:3;6975:5;6971:15;6964:58;7041:3;7104:2;7093:9;7089:18;7076:32;7071:2;7064:5;7060:14;7053:56;;7128:3;7191:2;7180:9;7176:18;7163:32;7158:2;7151:5;7147:14;7140:56;;7215:3;7278:2;7267:9;7263:18;7250:32;7245:2;7238:5;7234:14;7227:56;;5998:1291;;;;:::o;7294:186::-;7362:20;;-1:-1:-1;;;;;7411:44:39;;7401:55;;7391:83;;7470:1;7467;7460:12;7485:530;7527:5;7580:3;7573:4;7565:6;7561:17;7557:27;7547:55;;7598:1;7595;7588:12;7547:55;7634:6;7621:20;-1:-1:-1;;;;;7656:2:39;7653:26;7650:52;;;7682:18;;:::i;:::-;7726:55;7769:2;7750:13;;-1:-1:-1;;7746:27:39;7775:4;7742:38;7726:55;:::i;:::-;7806:2;7797:7;7790:19;7852:3;7845:4;7840:2;7832:6;7828:15;7824:26;7821:35;7818:55;;;7869:1;7866;7859:12;7818:55;7934:2;7927:4;7919:6;7915:17;7908:4;7899:7;7895:18;7882:55;7982:1;7957:16;;;7975:4;7953:27;7946:38;;;;7961:7;7485:530;-1:-1:-1;;;7485:530:39:o;8020:896::-;8080:5;8128:4;8116:9;8111:3;8107:19;8103:30;8100:50;;;8146:1;8143;8136:12;8100:50;8168:22;;:::i;:::-;8159:31;;8226:9;8213:23;-1:-1:-1;;;;;8296:2:39;8288:6;8285:14;8282:34;;;8312:1;8309;8302:12;8282:34;8339:62;8397:3;8388:6;8377:9;8373:22;8339:62;:::i;:::-;8332:5;8325:77;8434:38;8468:2;8457:9;8453:18;8434:38;:::i;:::-;8429:2;8422:5;8418:14;8411:62;8505:38;8539:2;8528:9;8524:18;8505:38;:::i;:::-;8500:2;8493:5;8489:14;8482:62;8597:2;8586:9;8582:18;8569:32;8553:48;;8626:2;8616:8;8613:16;8610:36;;;8642:1;8639;8632:12;8610:36;8678:47;8721:3;8710:8;8699:9;8695:24;8678:47;:::i;:::-;8673:2;8666:5;8662:14;8655:71;8779:3;8768:9;8764:19;8751:33;8735:49;;8809:2;8799:8;8796:16;8793:36;;;8825:1;8822;8815:12;8793:36;;8862:47;8905:3;8894:8;8883:9;8879:24;8862:47;:::i;:::-;8856:3;8849:5;8845:15;8838:72;;8020:896;;;;:::o;8921:929::-;8988:5;9041:3;9034:4;9026:6;9022:17;9018:27;9008:55;;9059:1;9056;9049:12;9008:55;9095:6;9082:20;9121:4;9145:73;9161:56;9214:2;9161:56;:::i;9145:73::-;9252:15;;;9338:1;9334:10;;;;9322:23;;9318:32;;;9283:12;;;;9362:15;;;9359:35;;;9390:1;9387;9380:12;9359:35;9426:2;9418:6;9414:15;9438:383;9454:6;9449:3;9446:15;9438:383;;;9540:3;9527:17;-1:-1:-1;;;;;9563:11:39;9560:35;9557:125;;;9636:1;9665:2;9661;9654:14;9557:125;9707:71;9774:3;9769:2;9755:11;9747:6;9743:24;9739:33;9707:71;:::i;:::-;9695:84;;-1:-1:-1;9799:12:39;;;;9471;;9438:383;;;-1:-1:-1;9839:5:39;8921:929;-1:-1:-1;;;;;;8921:929:39:o;9855:392::-;9943:8;9953:6;10007:3;10000:4;9992:6;9988:17;9984:27;9974:55;;10025:1;10022;10015:12;9974:55;-1:-1:-1;10048:20:39;;-1:-1:-1;;;;;10080:30:39;;10077:50;;;10123:1;10120;10113:12;10077:50;10160:4;10152:6;10148:17;10136:29;;10220:3;10213:4;10203:6;10200:1;10196:14;10188:6;10184:27;10180:38;10177:47;10174:67;;;10237:1;10234;10227:12;10174:67;9855:392;;;;;:::o;10252:1160::-;10506:6;10514;10522;10530;10538;10591:2;10579:9;10570:7;10566:23;10562:32;10559:52;;;10607:1;10604;10597:12;10559:52;10647:9;10634:23;-1:-1:-1;;;;;10717:2:39;10709:6;10706:14;10703:34;;;10733:1;10730;10723:12;10703:34;10756:74;10822:7;10813:6;10802:9;10798:22;10756:74;:::i;:::-;10746:84;;10883:2;10872:9;10868:18;10855:32;10839:48;;10912:2;10902:8;10899:16;10896:36;;;10928:1;10925;10918:12;10896:36;10967:97;11056:7;11045:8;11034:9;11030:24;10967:97;:::i;:::-;11083:8;;-1:-1:-1;10941:123:39;-1:-1:-1;11171:2:39;11156:18;;11143:32;;-1:-1:-1;11187:16:39;;;11184:36;;;11216:1;11213;11206:12;11184:36;;11255:97;11344:7;11333:8;11322:9;11318:24;11255:97;:::i;:::-;10252:1160;;;;-1:-1:-1;10252:1160:39;;-1:-1:-1;11371:8:39;;11229:123;10252:1160;-1:-1:-1;;;10252:1160:39:o;11417:127::-;11478:10;11473:3;11469:20;11466:1;11459:31;11509:4;11506:1;11499:15;11533:4;11530:1;11523:15;11549:139;11629:1;11622:5;11619:12;11609:46;;11635:18;;:::i;:::-;11664;;11549:139::o;11802:436::-;11868:43;11907:3;11899:5;11893:12;11868:43;:::i;:::-;11957:4;11946:16;;;11940:23;-1:-1:-1;;;;;12033:21:39;;;12017:14;;;12010:45;;;;12104:4;12093:16;;;12087:23;12071:14;;;12064:47;12160:4;12149:16;;;12143:23;12127:14;;;12120:47;12220:4;12209:16;;;12203:23;12199:32;12183:14;;12176:56;11802:436::o;12243:640::-;12305:3;12343:5;12337:12;12370:6;12365:3;12358:19;12396:4;12425:2;12420:3;12416:12;12409:19;;12462:2;12455:5;12451:14;12483:1;12493:365;12507:6;12504:1;12501:13;12493:365;;;12572:6;12566:13;12592:46;12634:3;12629:2;12623:9;12592:46;:::i;:::-;12684:11;;;12678:18;-1:-1:-1;;;;;12674:44:39;12706:3;12658:14;;12651:68;12769:4;12761:13;12755:20;12748:4;12739:14;;12732:44;12805:4;12796:14;;;;12833:15;;;;12715:1;12522:9;12493:365;;;-1:-1:-1;12874:3:39;;12243:640;-1:-1:-1;;;;;12243:640:39:o;12888:324::-;13121:2;13110:9;13103:21;13084:4;13141:65;13202:2;13191:9;13187:18;13179:6;13141:65;:::i;13399:395::-;13493:6;13546:2;13534:9;13525:7;13521:23;13517:32;13514:52;;;13562:1;13559;13552:12;13514:52;13602:9;13589:23;-1:-1:-1;;;;;13627:6:39;13624:30;13621:50;;;13667:1;13664;13657:12;13621:50;13690:22;;13746:3;13728:16;;;13724:26;13721:46;;;13763:1;13760;13753:12;13981:1817;14401:6;14409;14417;14425;14433;14441;14449;14457;14465;14473;14526:3;14514:9;14505:7;14501:23;14497:33;14494:53;;;14543:1;14540;14533:12;14494:53;14583:9;14570:23;-1:-1:-1;;;;;14653:2:39;14645:6;14642:14;14639:34;;;14669:1;14666;14659:12;14639:34;14692:74;14758:7;14749:6;14738:9;14734:22;14692:74;:::i;:::-;14682:84;;14819:2;14808:9;14804:18;14791:32;14775:48;;14848:2;14838:8;14835:16;14832:36;;;14864:1;14861;14854:12;14832:36;14903:97;14992:7;14981:8;14970:9;14966:24;14903:97;:::i;:::-;15019:8;;-1:-1:-1;14877:123:39;-1:-1:-1;15107:2:39;15092:18;;15079:32;;-1:-1:-1;15123:16:39;;;15120:36;;;15152:1;15149;15142:12;15120:36;15191:97;15280:7;15269:8;15258:9;15254:24;15191:97;:::i;:::-;15307:8;;-1:-1:-1;15165:123:39;-1:-1:-1;15395:2:39;15380:18;;15367:32;;-1:-1:-1;15411:16:39;;;15408:36;;;15440:1;15437;15430:12;15408:36;;15479:97;15568:7;15557:8;15546:9;15542:24;15479:97;:::i;:::-;15595:8;;-1:-1:-1;15453:123:39;-1:-1:-1;;15677:3:39;15662:19;;15649:33;;-1:-1:-1;15701:39:39;15735:3;15720:19;;15701:39;:::i;:::-;15691:49;;15787:3;15776:9;15772:19;15759:33;15749:43;;13981:1817;;;;;;;;;;;;;:::o;15803:879::-;16119:2;16131:21;;;16201:13;;16104:18;;;16223:22;;;16071:4;;16298;;16276:2;16261:18;;;16325:15;;;16071:4;16368:185;16382:6;16379:1;16376:13;16368:185;;;16457:13;;16450:21;16443:29;16431:42;;16493:12;;;;16528:15;;;;16404:1;16397:9;16368:185;;;16372:3;;;16598:9;16593:3;16589:19;16584:2;16573:9;16569:18;16562:47;16626:50;16672:3;16664:6;16626:50;:::i;:::-;16618:58;15803:879;-1:-1:-1;;;;;;15803:879:39:o;16687:487::-;16798:6;16806;16859:2;16847:9;16838:7;16834:23;16830:32;16827:52;;;16875:1;16872;16865:12;16827:52;16915:9;16902:23;-1:-1:-1;;;;;16940:6:39;16937:30;16934:50;;;16980:1;16977;16970:12;16934:50;17019:95;17106:7;17097:6;17086:9;17082:22;17019:95;:::i;:::-;17133:8;;16993:121;;-1:-1:-1;16687:487:39;-1:-1:-1;;;;16687:487:39:o;17371:879::-;17549:6;17557;17565;17573;17626:2;17614:9;17605:7;17601:23;17597:32;17594:52;;;17642:1;17639;17632:12;17594:52;17682:9;17669:23;-1:-1:-1;;;;;17752:2:39;17744:6;17741:14;17738:34;;;17768:1;17765;17758:12;17738:34;17807:95;17894:7;17885:6;17874:9;17870:22;17807:95;:::i;:::-;17921:8;;-1:-1:-1;17781:121:39;-1:-1:-1;18009:2:39;17994:18;;17981:32;;-1:-1:-1;18025:16:39;;;18022:36;;;18054:1;18051;18044:12;18022:36;;18093:97;18182:7;18171:8;18160:9;18156:24;18093:97;:::i;:::-;17371:879;;;;-1:-1:-1;18209:8:39;-1:-1:-1;;;;17371:879:39:o;18255:452::-;18348:6;18356;18409:2;18397:9;18388:7;18384:23;18380:32;18377:52;;;18425:1;18422;18415:12;18377:52;18465:9;18452:23;-1:-1:-1;;;;;18490:6:39;18487:30;18484:50;;;18530:1;18527;18520:12;18484:50;18553:22;;18609:2;18591:16;;;18587:25;18584:45;;;18625:1;18622;18615:12;18584:45;18648:2;18697;18682:18;;;;18669:32;;-1:-1:-1;;;18255:452:39:o;18712:994::-;18894:6;18902;18910;18918;18926;18979:3;18967:9;18958:7;18954:23;18950:33;18947:53;;;18996:1;18993;18986:12;18947:53;19036:9;19023:23;-1:-1:-1;;;;;19106:2:39;19098:6;19095:14;19092:34;;;19122:1;19119;19112:12;19092:34;19145:22;;;;19201:3;19183:16;;;19179:26;19176:46;;;19218:1;19215;19208:12;19176:46;19241:2;;-1:-1:-1;19296:2:39;19281:18;;19268:32;;19312:16;;;19309:36;;;19341:1;19338;19331:12;19309:36;;19380:97;19469:7;19458:8;19447:9;19443:24;19380:97;:::i;:::-;19496:8;;-1:-1:-1;19354:123:39;-1:-1:-1;;19578:2:39;19563:18;;19550:32;;-1:-1:-1;19632:2:39;19617:18;;19604:32;19645:31;19604:32;19645:31;:::i;:::-;19695:5;19685:15;;;18712:994;;;;;;;;:::o;19711:1460::-;20046:6;20054;20062;20070;20078;20086;20094;20102;20155:3;20143:9;20134:7;20130:23;20126:33;20123:53;;;20172:1;20169;20162:12;20123:53;20212:9;20199:23;-1:-1:-1;;;;;20282:2:39;20274:6;20271:14;20268:34;;;20298:1;20295;20288:12;20268:34;20337:95;20424:7;20415:6;20404:9;20400:22;20337:95;:::i;:::-;20451:8;;-1:-1:-1;20311:121:39;-1:-1:-1;20539:2:39;20524:18;;20511:32;;-1:-1:-1;20555:16:39;;;20552:36;;;20584:1;20581;20574:12;20552:36;20623:97;20712:7;20701:8;20690:9;20686:24;20623:97;:::i;:::-;20739:8;;-1:-1:-1;20597:123:39;-1:-1:-1;20827:2:39;20812:18;;20799:32;;-1:-1:-1;20843:16:39;;;20840:36;;;20872:1;20869;20862:12;20840:36;;20911:97;21000:7;20989:8;20978:9;20974:24;20911:97;:::i;:::-;19711:1460;;;;-1:-1:-1;19711:1460:39;;;;21027:8;;21109:2;21094:18;;21081:32;;21160:3;21145:19;21132:33;;-1:-1:-1;19711:1460:39;-1:-1:-1;;;;19711:1460:39:o;21176:247::-;21235:6;21288:2;21276:9;21267:7;21263:23;21259:32;21256:52;;;21304:1;21301;21294:12;21256:52;21343:9;21330:23;21362:31;21387:5;21362:31;:::i;21428:388::-;21633:2;21622:9;21615:21;21596:4;21653:45;21694:2;21683:9;21679:18;21671:6;21653:45;:::i;:::-;21729:2;21714:18;;21707:34;;;;-1:-1:-1;;;;;;21777:32:39;;;;21772:2;21757:18;;;21750:60;21645:53;21428:388;-1:-1:-1;21428:388:39:o;21821:400::-;21920:6;21973:2;21961:9;21952:7;21948:23;21944:32;21941:52;;;21989:1;21986;21979:12;21941:52;22029:9;22016:23;-1:-1:-1;;;;;22054:6:39;22051:30;22048:50;;;22094:1;22091;22084:12;22048:50;22117:22;;22173:3;22155:16;;;22151:26;22148:46;;;22190:1;22187;22180:12;22728:2710;22914:9;22949:77;22965:60;23018:6;22965:60;:::i;22949:77::-;23060:19;;;23098:4;23118:12;;;;23048:3;23149:1;23184:15;;;23173:27;;23223:14;23212:26;;23209:46;;;23251:1;23248;23241:12;23209:46;23275:5;23289:2116;23305:6;23300:3;23297:15;23289:2116;;;23391:3;23378:17;-1:-1:-1;;;;;23468:2:39;23455:11;23452:19;23449:109;;;23512:1;23541:2;23537;23530:14;23449:109;23592:11;23585:5;23581:23;23571:33;;23649:4;23644:2;23628:14;23624:23;23620:34;23617:124;;;23695:1;23724:2;23720;23713:14;23617:124;23769:22;;:::i;:::-;23833:2;23820:16;23811:7;23804:33;23886:2;23882;23878:11;23865:25;23925:1;23916:7;23913:14;23903:112;;23969:1;23998:2;23994;23987:14;23903:112;24035:16;;;24028:33;24084:2;24137:11;;;24124:25;24106:16;;;24099:51;24173:2;24226:11;;;24213:25;24195:16;;;24188:51;24263:3;24306:12;;;24293:26;24335:14;;;24332:107;;;24391:1;24421:3;24416;24409:16;24332:107;24463:15;;;;;24521:14;24514:4;24505:14;;24501:35;24491:136;;24579:1;24568:12;;24609:3;24604;24597:16;24491:136;24664:3;24651:17;24640:28;;24694:74;24710:57;24763:3;24710:57;:::i;24694:74::-;24812:18;;;24908:12;;;24899:22;;24895:31;;;24852:14;;;;24955;24942:28;;24939:121;;;25012:1;25042:3;25037;25030:16;24939:121;25086:12;;;;25111:174;25129:8;25122:5;25119:19;25111:174;;;25211:19;;25197:34;;25150:14;;;;25257;;;;25111:174;;;25305:17;;;25298:32;;;;-1:-1:-1;25343:20:39;;-1:-1:-1;;25383:12:39;;;;23322;;23289:2116;;;-1:-1:-1;25427:5:39;;22728:2710;-1:-1:-1;;;;;;;22728:2710:39:o;25443:577::-;25565:4;25571:6;25631:11;25618:25;25725:2;25721:7;25710:8;25694:14;25690:29;25686:43;25666:18;25662:68;25652:96;;25744:1;25741;25734:12;25652:96;25771:33;;25823:20;;;-1:-1:-1;;;;;;25855:30:39;;25852:50;;;25898:1;25895;25888:12;25852:50;25931:4;25919:17;;-1:-1:-1;25990:4:39;25978:17;;25962:14;25958:38;25948:49;;25945:69;;;26010:1;26007;26000:12;26025:232;26111:6;26164:3;26152:9;26143:7;26139:23;26135:33;26132:53;;;26181:1;26178;26171:12;26132:53;26204:47;26243:7;26232:9;26204:47;:::i;26262:585::-;26392:4;26398:6;26458:11;26445:25;26552:2;26548:7;26537:8;26521:14;26517:29;26513:43;26493:18;26489:68;26479:96;;26571:1;26568;26561:12;26479:96;26598:33;;26650:20;;;-1:-1:-1;;;;;;26682:30:39;;26679:50;;;26725:1;26722;26715:12;26679:50;26758:4;26746:17;;-1:-1:-1;26817:4:39;26805:17;;26789:14;26785:38;26775:49;;26772:69;;;26837:1;26834;26827:12;26852:248;26946:6;26999:3;26987:9;26978:7;26974:23;26970:33;26967:53;;;27016:1;27013;27006:12;26967:53;27039:55;27086:7;27075:9;27039:55;:::i;27105:207::-;27178:6;27231:2;27219:9;27210:7;27206:23;27202:32;27199:52;;;27247:1;27244;27237:12;27199:52;27270:36;27296:9;27270:36;:::i;27317:211::-;27431:9;27468:54;27507:14;27500:5;27468:54;:::i;27533:489::-;27600:5;27648:4;27636:9;27631:3;27627:19;27623:30;27620:50;;;27666:1;27663;27656:12;27620:50;27699:4;27693:11;27743:4;27735:6;27731:17;27814:6;27802:10;27799:22;-1:-1:-1;;;;;27766:10:39;27763:34;27760:62;27757:88;;;27825:18;;:::i;:::-;27861:4;27854:24;27926:23;;27911:39;;28011:2;27996:18;;;27983:32;27966:15;;;27959:57;;;;-1:-1:-1;27896:6:39;27533:489;-1:-1:-1;27533:489:39:o;28027:1832::-;28273:9;28308:77;28324:60;28377:6;28324:60;:::i;28308:77::-;28407:3;28431:6;28426:3;28419:19;28457:4;28486:2;28481:3;28477:12;28470:19;;28530:6;28527:1;28523:14;28516:5;28512:26;28561:14;28553:6;28550:26;28547:46;;;28589:1;28586;28579:12;28547:46;28613:5;28627:1199;28643:6;28638:3;28635:15;28627:1199;;;28729:3;28716:17;-1:-1:-1;;;;;28752:11:39;28749:35;28746:125;;;28825:1;28854:2;28850;28843:14;28746:125;28894:23;;28959:14;28952:4;28944:13;;28940:34;28930:132;;29016:1;29045:2;29041;29034:14;28930:132;29098:2;29085:16;29127:73;29143:56;29196:2;29143:56;:::i;29127:73::-;29244:17;;;29342:1;29338:10;;;;29330:19;;29326:28;;;29283:14;;;;29383;29370:28;;29367:118;;;29439:1;29468:2;29464;29457:14;29367:118;29511:11;;;;29535:218;29553:8;29546:5;29543:19;29535:218;;;29637:61;29683:14;29676:5;29637:61;:::i;:::-;29630:5;29623:76;29736:2;29729:5;29725:14;29716:23;;29585:4;29578:5;29574:16;29565:25;;29535:218;;;29766:18;;-1:-1:-1;;;29804:12:39;;;;28660;;28627:1199;;;-1:-1:-1;29848:5:39;;28027:1832;-1:-1:-1;;;;;;28027:1832:39:o;29864:127::-;29925:10;29920:3;29916:20;29913:1;29906:31;29956:4;29953:1;29946:15;29980:4;29977:1;29970:15;29996:322;30087:4;30145:11;30132:25;30239:2;30235:7;30224:8;30208:14;30204:29;30200:43;30180:18;30176:68;30166:96;;30258:1;30255;30248:12;30166:96;30279:33;;;;;29996:322;-1:-1:-1;;29996:322:39:o;30323:333::-;30424:4;30482:11;30469:25;30576:3;30572:8;30561;30545:14;30541:29;30537:44;30517:18;30513:69;30503:97;;30596:1;30593;30586:12;30661:217;30779:9;30816:56;30857:14;30850:5;30816:56;:::i;30883:521::-;30960:4;30966:6;31026:11;31013:25;31120:2;31116:7;31105:8;31089:14;31085:29;31081:43;31061:18;31057:68;31047:96;;31139:1;31136;31129:12;31047:96;31166:33;;31218:20;;;-1:-1:-1;;;;;;31250:30:39;;31247:50;;;31293:1;31290;31283:12;31247:50;31326:4;31314:17;;-1:-1:-1;31357:14:39;31353:27;;;31343:38;;31340:58;;;31394:1;31391;31384:12;31669:584;31801:4;31807:6;31867:11;31854:25;31961:2;31957:7;31946:8;31930:14;31926:29;31922:43;31902:18;31898:68;31888:96;;31980:1;31977;31970:12;31888:96;32007:33;;32059:20;;;-1:-1:-1;;;;;;32091:30:39;;32088:50;;;32134:1;32131;32124:12;32088:50;32167:4;32155:17;;-1:-1:-1;32218:1:39;32214:14;;;32198;32194:35;32184:46;;32181:66;;;32243:1;32240;32233:12;33519:127;33580:10;33575:3;33571:20;33568:1;33561:31;33611:4;33608:1;33601:15;33635:4;33632:1;33625:15;33651:128;33691:3;33722:1;33718:6;33715:1;33712:13;33709:39;;;33728:18;;:::i;:::-;-1:-1:-1;33764:9:39;;33651:128::o;33784:168::-;33824:7;33890:1;33886;33882:6;33878:14;33875:1;33872:21;33867:1;33860:9;33853:17;33849:45;33846:71;;;33897:18;;:::i;:::-;-1:-1:-1;33937:9:39;;33784:168::o;33957:473::-;34022:3;34060:5;34054:12;34087:6;34082:3;34075:19;34113:4;34142:2;34137:3;34133:12;34126:19;;34179:2;34172:5;34168:14;34200:1;34210:195;34224:6;34221:1;34218:13;34210:195;;;34273:50;34319:3;34310:6;34304:13;34273:50;:::i;:::-;34352:4;34343:14;;;;;34380:15;;;;34246:1;34239:9;34210:195;;34435:1410;34825:4;34854:3;34895:2;34884:9;34880:18;34925:6;34914:9;34907:25;34951:2;34989:1;34985;34980:3;34976:11;34972:19;35039:2;35031:6;35027:15;35022:2;35011:9;35007:18;35000:43;35062:2;35100;35095;35084:9;35080:18;35073:30;35123:6;35158;35152:13;35189:6;35181;35174:22;35227:3;35216:9;35212:19;35205:26;;35266:2;35258:6;35254:15;35240:29;;35287:1;35297:414;35311:6;35308:1;35305:13;35297:414;;;35376:6;35370:13;35396:40;35432:3;35427:2;35421:9;35396:40;:::i;:::-;35480:11;;;35474:18;35470:27;;35456:12;;;35449:49;35538:11;;;35532:18;35518:12;;;35511:40;35574:4;35618:11;;;35612:18;35598:12;;;35591:40;35686:15;;;;35651:12;;;;35333:1;35326:9;35297:414;;;35301:3;;35758:9;35753:3;35749:19;35742:4;35731:9;35727:20;35720:49;35786:53;35835:3;35827:6;35786:53;:::i;:::-;35778:61;34435:1410;-1:-1:-1;;;;;;;;;;;;34435:1410:39:o;35850:125::-;35890:4;35918:1;35915;35912:8;35909:34;;;35923:18;;:::i;:::-;-1:-1:-1;35960:9:39;;35850:125::o;35980:253::-;36077:6;36130:2;36118:9;36109:7;36105:23;36101:32;36098:52;;;36146:1;36143;36136:12;36098:52;36169:58;36219:7;36208:9;36169:58;:::i;36562:135::-;36638:1;36631:5;36628:12;36618:46;;36644:18;;:::i;36702:198::-;36843:2;36828:18;;36855:39;36832:9;36876:6;36855:39;:::i;36905:815::-;36967:3;37005:5;36999:12;37032:6;37027:3;37020:19;37058:4;37087:2;37082:3;37078:12;37071:19;;37124:2;37117:5;37113:14;37145:1;37155:540;37169:6;37166:1;37163:13;37155:540;;;37234:6;37228:13;37254:40;37290:3;37285:2;37279:9;37254:40;:::i;:::-;37338:11;;;37332:18;-1:-1:-1;;;;;37328:44:39;37314:12;;;37307:66;37396:4;37440:11;;;37434:18;37420:12;;;37413:40;37476:4;37520:11;;;37514:18;37500:12;;;37493:40;37556:4;37600:11;;;37594:18;37580:12;;;37573:40;37360:3;37633:14;;;;37670:15;;;;37369:1;37184:9;37155:540;;37725:982;37795:3;37833:5;37827:12;37860:6;37855:3;37848:19;37886:4;37915:2;37910:3;37906:12;37899:19;;37952:2;37945:5;37941:14;37973:1;37983:699;37997:6;37994:1;37991:13;37983:699;;;38062:6;38056:13;38082:40;38118:3;38113:2;38107:9;38082:40;:::i;:::-;38161:11;;;38155:18;-1:-1:-1;;;;;38249:21:39;;;38235:12;;;38228:43;38294:4;38338:11;;;38332:18;38318:12;;;38311:40;38374:4;38418:11;;;38412:18;38398:12;;;38391:40;38454:4;38498:11;;;38492:18;38478:12;;;38471:40;38204:3;38582:11;;;38576:18;38572:27;38558:12;;;38551:49;38629:4;38620:14;;;;38657:15;;;;38213:1;38012:9;37983:699;;38712:140;38793:1;38786:5;38783:12;38773:46;;38799:18;;:::i;38979:435::-;39032:3;39070:5;39064:12;39097:6;39092:3;39085:19;39123:4;39152:2;39147:3;39143:12;39136:19;;39189:2;39182:5;39178:14;39210:1;39220:169;39234:6;39231:1;39228:13;39220:169;;;39295:13;;39283:26;;39329:12;;;;39364:15;;;;39256:1;39249:9;39220:169;;39419:1146;39488:3;39526:5;39520:12;39553:6;39548:3;39541:19;39579:4;39620:2;39615:3;39611:12;39645:11;39672;39665:18;;39722:6;39719:1;39715:14;39708:5;39704:26;39692:38;;39764:2;39757:5;39753:14;39785:1;39795:744;39809:6;39806:1;39803:13;39795:744;;;39880:5;39874:4;39870:16;39865:3;39858:29;39916:6;39910:13;39946:4;39982:2;39976:9;39970:4;39963:23;40033:2;40029;40025:11;40019:18;40050:49;40095:2;40089:4;40085:13;40071:12;40050:49;:::i;:::-;-1:-1:-1;40122:4:39;40167:11;;;40161:18;40146:13;;;40139:41;40203:4;40248:11;;;40242:18;40227:13;;;40220:41;40284:4;40329:11;;;40323:18;40361:13;;;40354:25;;;40400:59;40445:13;;;40323:18;40400:59;:::i;:::-;40517:12;;;;40392:67;-1:-1:-1;;;40482:15:39;;;;39831:1;39824:9;39795:744;;;-1:-1:-1;40555:4:39;;39419:1146;-1:-1:-1;;;;;;;39419:1146:39:o;40570:2814::-;41041:6;41030:9;41023:25;41113:1;41109;41104:3;41100:11;41096:19;41088:6;41084:32;41079:2;41068:9;41064:18;41057:60;41153:3;41148:2;41137:9;41133:18;41126:31;41004:4;41176:3;41214:6;41208:13;41258:3;41252;41241:9;41237:19;41230:32;41271:59;41326:2;41315:9;41311:18;41296:12;41290:19;-1:-1:-1;;;;;11759:31:39;11747:44;;11693:104;41271:59;41385:2;41371:12;41367:21;41361:28;41408:6;41423:54;41473:2;41462:9;41458:18;41442:14;-1:-1:-1;;;;;11759:31:39;11747:44;;11693:104;41423:54;41532:2;41518:12;41514:21;41508:28;41486:50;;41573:2;41567:3;41556:9;41552:19;41545:31;;41599:74;41668:3;41657:9;41653:19;41637:14;41599:74;:::i;:::-;41585:88;;41728:4;41714:12;41710:23;41704:30;41803:3;41799:8;41787:9;41779:6;41775:22;41771:37;41765:3;41754:9;41750:19;41743:66;41832:69;41894:6;41878:14;41832:69;:::i;:::-;41818:83;;;41956:4;41942:12;41938:23;41932:30;41971:62;42028:3;42017:9;42013:19;41997:14;41971:62;:::i;:::-;;42094:3;42080:12;42076:22;42070:29;42064:3;42053:9;42049:19;42042:58;42161:4;42147:12;42143:23;42137:30;42131:3;42120:9;42116:19;42109:59;42229:4;42215:12;42211:23;42205:30;42199:3;42188:9;42184:19;42177:59;42255:6;42322:2;42308:12;42304:21;42298:28;42292:3;42281:9;42277:19;42270:57;42346:6;42413:2;42399:12;42395:21;42389:28;42383:3;42372:9;42368:19;42361:57;42479:2;42465:12;42461:21;42455:28;42449:3;42438:9;42434:19;42427:57;42533:2;42525:6;42521:15;42515:22;42493:44;;42546:56;42596:4;42585:9;42581:20;42565:14;-1:-1:-1;;;;;38923:44:39;38911:57;;38857:117;42546:56;42651:2;42639:15;;42633:22;-1:-1:-1;;;;;38923:44:39;42714:4;42699:20;;38911:57;42769:4;42757:17;;42751:24;42842:22;;;-1:-1:-1;;42838:31:39;;;42818:18;;;42811:59;42751:24;;-1:-1:-1;;;42893:41:39;42846:6;42751:24;42893:41;:::i;:::-;42879:55;;42983:4;42975:6;42971:17;42965:24;42943:46;;43053:2;43041:9;43033:6;43029:22;43025:31;43020:2;43009:9;43005:18;42998:59;;;43077:41;43111:6;43095:14;43077:41;:::i;:::-;43066:52;;;;43165:9;43160:3;43156:19;43149:4;43138:9;43134:20;43127:49;43199:41;43236:3;43228:6;43199:41;:::i;:::-;43185:55;;43290:9;43282:6;43278:22;43271:4;43260:9;43256:20;43249:52;43318:60;43371:6;43363;43318:60;:::i;:::-;43310:68;40570:2814;-1:-1:-1;;;;;;;;40570:2814:39:o
Swarm Source
ipfs://d9ec6bf53c7c4dd207e9b7af873aae1b86f9ebf0a16709b20f4f94de35603786
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.