Source Code
Overview
ETH Balance
0 ETH
ETH Value
$0.00Latest 25 from a total of 1,708 transactions
| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Fulfill Advanced... | 16785704 | 164 days ago | IN | 0.1 ETH | 0.00001606 | ||||
| Fulfill Advanced... | 16635722 | 166 days ago | IN | 0.099 ETH | 0.00001514 | ||||
| Fulfill Advanced... | 16442802 | 168 days ago | IN | 0.09198 ETH | 0.00001447 | ||||
| Fulfill Advanced... | 16263797 | 171 days ago | IN | 0.099 ETH | 0.00001557 | ||||
| Fulfill Advanced... | 15619729 | 178 days ago | IN | 0.07389 ETH | 0.00001625 | ||||
| Fulfill Advanced... | 15591781 | 179 days ago | IN | 0.07389 ETH | 0.00001563 | ||||
| Cancel | 14544321 | 191 days ago | IN | 0 ETH | 0.00000741 | ||||
| Cancel | 14538227 | 191 days ago | IN | 0 ETH | 0.00000739 | ||||
| Cancel | 14495149 | 192 days ago | IN | 0 ETH | 0.00000746 | ||||
| Cancel | 14488034 | 192 days ago | IN | 0 ETH | 0.00002164 | ||||
| Cancel | 14486077 | 192 days ago | IN | 0 ETH | 0.00000783 | ||||
| Fulfill Advanced... | 14472801 | 192 days ago | IN | 0.07 ETH | 0.00001729 | ||||
| Fulfill Advanced... | 14095208 | 196 days ago | IN | 0.049 ETH | 0.00001586 | ||||
| Cancel | 13811574 | 200 days ago | IN | 0 ETH | 0.00000722 | ||||
| Cancel | 13810805 | 200 days ago | IN | 0 ETH | 0.00000724 | ||||
| Cancel | 13200730 | 207 days ago | IN | 0 ETH | 0.0000072 | ||||
| Cancel | 12942909 | 210 days ago | IN | 0 ETH | 0.00000675 | ||||
| Cancel | 12926005 | 210 days ago | IN | 0 ETH | 0.00000675 | ||||
| Cancel | 12915852 | 211 days ago | IN | 0 ETH | 0.00000453 | ||||
| Cancel | 12915787 | 211 days ago | IN | 0 ETH | 0.00000675 | ||||
| Cancel | 12830913 | 212 days ago | IN | 0 ETH | 0.00000677 | ||||
| Cancel | 12801047 | 212 days ago | IN | 0 ETH | 0.00000924 | ||||
| Fulfill Advanced... | 12797455 | 212 days ago | IN | 0.03689 ETH | 0.00001671 | ||||
| Cancel | 12723099 | 213 days ago | IN | 0 ETH | 0.00000462 | ||||
| Cancel | 12723003 | 213 days ago | IN | 0 ETH | 0.00000689 |
Latest 25 internal transactions (View All)
Advanced mode:
| Parent Transaction Hash | Block | From | To | |||
|---|---|---|---|---|---|---|
| 16785704 | 164 days ago | 0.005 ETH | ||||
| 16785704 | 164 days ago | 0.0005 ETH | ||||
| 16785704 | 164 days ago | 0.0945 ETH | ||||
| 16785704 | 164 days ago | 0.1 ETH | ||||
| 16635722 | 166 days ago | 0.00495 ETH | ||||
| 16635722 | 166 days ago | 0.000495 ETH | ||||
| 16635722 | 166 days ago | 0.093555 ETH | ||||
| 16635722 | 166 days ago | 0.099 ETH | ||||
| 16442802 | 168 days ago | 0.004599 ETH | ||||
| 16442802 | 168 days ago | 0.0004599 ETH | ||||
| 16442802 | 168 days ago | 0.0869211 ETH | ||||
| 16442802 | 168 days ago | 0.09198 ETH | ||||
| 16263797 | 171 days ago | 0.00495 ETH | ||||
| 16263797 | 171 days ago | 0.000495 ETH | ||||
| 16263797 | 171 days ago | 0.093555 ETH | ||||
| 16263797 | 171 days ago | 0.099 ETH | ||||
| 15756181 | 177 days ago | 0.004275 ETH | ||||
| 15756181 | 177 days ago | 0.0004275 ETH | ||||
| 15756181 | 177 days ago | 0.0807975 ETH | ||||
| 15756181 | 177 days ago | 0.0855 ETH | ||||
| 15619729 | 178 days ago | 0.0036945 ETH | ||||
| 15619729 | 178 days ago | 0.00036945 ETH | ||||
| 15619729 | 178 days ago | 0.06982605 ETH | ||||
| 15619729 | 178 days ago | 0.07389 ETH | ||||
| 15591781 | 179 days ago | 0.0036945 ETH |
Cross-Chain Transactions
Loading...
Loading
This contract contains unverified libraries: SignatureChecker
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Name:
Seaport
Compiler Version
v0.8.24+commit.e11b9ed9
ZkSolc Version
v1.5.3
Optimization Enabled:
Yes with Mode 3
Other Settings:
cancun EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
import {ConsiderationInterface} from "../seaport-1.5/interfaces/ConsiderationInterface.sol";
import {OrderType} from "../seaport-1.5/lib/ConsiderationEnums.sol";
import {AdvancedOrder, BasicOrderParameters, CriteriaResolver, Execution, Fulfillment, FulfillmentComponent, Order, OrderComponents, OrderParameters} from "../seaport-1.5/lib/ConsiderationStructs.sol";
import {ReferenceOrderCombiner} from "./lib/ReferenceOrderCombiner.sol";
import {OrderToExecute} from "./lib/ReferenceConsiderationStructs.sol";
/**
* @title ReferenceConsideration
* @author 0age
* @custom:coauthor d1ll0n
* @custom:coauthor transmissions11
* @custom:version 1.5-reference
* @notice Consideration is a generalized native token/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 ConsiderationInterface, ReferenceOrderCombiner {
/**
* @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
) ReferenceOrderCombiner(conduitController) {}
/**
* @notice Accept native token transfers during execution that may then be
* used to facilitate native token transfers, where any tokens that
* remain will be transferred to the caller. Native tokens are only
* acceptable mid-fulfillment (and not during basic fulfillment).
*/
receive() external payable {
// Ensure the reentrancy guard is currently set to accept native tokens.
_assertAcceptingNativeTokens();
}
/**
* @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 with 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
* fulfilled.
*/
function fulfillBasicOrder(
BasicOrderParameters calldata parameters
) external payable override nonReentrant(false) returns (bool fulfilled) {
// Validate and fulfill the basic order.
fulfilled = _validateAndFulfillBasicOrder(parameters);
}
/**
* @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 with this method and what orders are compatible with it.
* Note that this function costs less gas than `fulfillBasicOrder`
* due to the zero bytes in the function selector (0x00000000) which
* also results in earlier function dispatch.
*
* @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
* fulfilled.
*/
function fulfillBasicOrder_efficient_6GL6yc(
BasicOrderParameters calldata parameters
) external payable override nonReentrant(false) 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
* fulfilled.
*/
function fulfillOrder(
Order calldata order,
bytes32 fulfillerConduitKey
)
external
payable
override
nonReentrant(order.parameters.orderType == OrderType.CONTRACT)
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 proxy 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
* fulfilled.
*/
function fulfillAdvancedOrder(
AdvancedOrder calldata advancedOrder,
CriteriaResolver[] calldata criteriaResolvers,
bytes32 fulfillerConduitKey,
address recipient
)
external
payable
override
nonReentrant(advancedOrder.parameters.orderType == OrderType.CONTRACT)
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
nonReentrant(true)
returns (bool[] memory availableOrders, Execution[] memory executions)
{
// Convert orders to "advanced" orders.
AdvancedOrder[] memory advancedOrders = _convertOrdersToAdvanced(
orders
);
// Convert Advanced Orders to Orders To Execute
OrderToExecute[]
memory ordersToExecute = _convertAdvancedToOrdersToExecute(
advancedOrders
);
// Fulfill all available orders.
return
_fulfillAvailableAdvancedOrders(
advancedOrders,
ordersToExecute,
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 proxy 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 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
nonReentrant(true)
returns (bool[] memory availableOrders, Execution[] memory executions)
{
// Convert Advanced Orders to Orders to Execute
OrderToExecute[]
memory ordersToExecute = _convertAdvancedToOrdersToExecute(
advancedOrders
);
// Fulfill all available orders.
return
_fulfillAvailableAdvancedOrders(
advancedOrders,
ordersToExecute,
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. Note that unspent offer item amounts or
* native tokens will not be reflected as part of this
* array.
*/
function matchOrders(
Order[] calldata orders,
Fulfillment[] calldata fulfillments
)
external
payable
override
nonReentrant(true)
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,
msg.sender
);
}
/**
* @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 proxy 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.
* @param recipient The intended recipient for all unspent offer
* item amounts, or the caller if the null address
* is supplied.
*
* @return executions An array of elements indicating the sequence of
* transfers performed as part of matching the given
* orders. Note that unspent offer item amounts or
* native tokens will not be reflected as part of this
* array.
*/
function matchAdvancedOrders(
AdvancedOrder[] memory advancedOrders,
CriteriaResolver[] calldata criteriaResolvers,
Fulfillment[] calldata fulfillments,
address recipient
)
external
payable
override
nonReentrant(true)
returns (Execution[] memory executions)
{
// Validate and match the advanced orders using supplied fulfillments.
return
_matchAdvancedOrders(
advancedOrders,
criteriaResolvers,
fulfillments,
recipient == address(0) ? msg.sender : recipient
);
}
/**
* @notice Cancel an arbitrary number of orders. Note that only the offerer
* or the zone of a given order may cancel it.
*
* @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 notEntered returns (bool cancelled) {
// Cancel the orders.
cancelled = _cancel(orders);
}
/**
* @notice Validate an arbitrary number of orders, thereby registering them
* as valid and allowing the fulfiller to skip verification. 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 notEntered 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
notEntered
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 the
// 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. Since the _orderStatus[orderHash]
* does not get set for contract orders, getOrderStatus will always
* return (false, false, 0, 0) for those hashes. Note that this
* function is susceptible to view reentrancy and so should be used
* with care when calling from other contracts.
*
* @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();
}
/**
* @dev Gets the contract offerer nonce for the specified contract offerer.
* Note that this function is susceptible to view reentrancy and so
* should be used with care when calling from other contracts.
*
* @param contractOfferer The contract offerer for which to get the nonce.
*
* @return nonce The contract offerer nonce.
*/
function getContractOffererNonce(
address contractOfferer
) external view override returns (uint256 nonce) {
nonce = _contractNonces[contractOfferer];
}
/**
* @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;
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,
// 4: contract order type
CONTRACT
}
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
}
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
}
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
}
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;
import {
BasicOrderType,
ItemType,
OrderType,
Side
} from "./ConsiderationEnums.sol";
import {
CalldataPointer,
MemoryPointer
} from "../helpers/PointerLibraries.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 provided to the zone if the
* order type is restricted and the zone is not the caller, or will be
* provided to the offerer as context for contract order types.
*/
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;
}
/**
* @dev Restricted orders are validated post-execution by calling validateOrder
* on the zone. This struct provides context about the order fulfillment
* and any supplied extraData, as well as all order hashes fulfilled in a
* call to a match or fulfillAvailable method.
*/
struct ZoneParameters {
bytes32 orderHash;
address fulfiller;
address offerer;
SpentItem[] offer;
ReceivedItem[] consideration;
bytes extraData;
bytes32[] orderHashes;
uint256 startTime;
uint256 endTime;
bytes32 zoneHash;
}
/**
* @dev Zones and contract offerers can communicate which schemas they implement
* along with any associated metadata related to each schema.
*/
struct Schema {
uint256 id;
bytes metadata;
}
using StructPointers for OrderComponents global;
using StructPointers for OfferItem global;
using StructPointers for ConsiderationItem global;
using StructPointers for SpentItem global;
using StructPointers for ReceivedItem global;
using StructPointers for BasicOrderParameters global;
using StructPointers for AdditionalRecipient global;
using StructPointers for OrderParameters global;
using StructPointers for Order global;
using StructPointers for AdvancedOrder global;
using StructPointers for OrderStatus global;
using StructPointers for CriteriaResolver global;
using StructPointers for Fulfillment global;
using StructPointers for FulfillmentComponent global;
using StructPointers for Execution global;
using StructPointers for ZoneParameters global;
/**
* @dev This library provides a set of functions for converting structs to
* pointers.
*/
library StructPointers {
/**
* @dev Get a MemoryPointer from OrderComponents.
*
* @param obj The OrderComponents object.
*
* @return ptr The MemoryPointer.
*/
function toMemoryPointer(
OrderComponents memory obj
) internal pure returns (MemoryPointer ptr) {
assembly {
ptr := obj
}
}
/**
* @dev Get a CalldataPointer from OrderComponents.
*
* @param obj The OrderComponents object.
*
* @return ptr The CalldataPointer.
*/
function toCalldataPointer(
OrderComponents calldata obj
) internal pure returns (CalldataPointer ptr) {
assembly {
ptr := obj
}
}
/**
* @dev Get a MemoryPointer from OfferItem.
*
* @param obj The OfferItem object.
*
* @return ptr The MemoryPointer.
*/
function toMemoryPointer(
OfferItem memory obj
) internal pure returns (MemoryPointer ptr) {
assembly {
ptr := obj
}
}
/**
* @dev Get a CalldataPointer from OfferItem.
*
* @param obj The OfferItem object.
*
* @return ptr The CalldataPointer.
*/
function toCalldataPointer(
OfferItem calldata obj
) internal pure returns (CalldataPointer ptr) {
assembly {
ptr := obj
}
}
/**
* @dev Get a MemoryPointer from ConsiderationItem.
*
* @param obj The ConsiderationItem object.
*
* @return ptr The MemoryPointer.
*/
function toMemoryPointer(
ConsiderationItem memory obj
) internal pure returns (MemoryPointer ptr) {
assembly {
ptr := obj
}
}
/**
* @dev Get a CalldataPointer from ConsiderationItem.
*
* @param obj The ConsiderationItem object.
*
* @return ptr The CalldataPointer.
*/
function toCalldataPointer(
ConsiderationItem calldata obj
) internal pure returns (CalldataPointer ptr) {
assembly {
ptr := obj
}
}
/**
* @dev Get a MemoryPointer from SpentItem.
*
* @param obj The SpentItem object.
*
* @return ptr The MemoryPointer.
*/
function toMemoryPointer(
SpentItem memory obj
) internal pure returns (MemoryPointer ptr) {
assembly {
ptr := obj
}
}
/**
* @dev Get a CalldataPointer from SpentItem.
*
* @param obj The SpentItem object.
*
* @return ptr The CalldataPointer.
*/
function toCalldataPointer(
SpentItem calldata obj
) internal pure returns (CalldataPointer ptr) {
assembly {
ptr := obj
}
}
/**
* @dev Get a MemoryPointer from ReceivedItem.
*
* @param obj The ReceivedItem object.
*
* @return ptr The MemoryPointer.
*/
function toMemoryPointer(
ReceivedItem memory obj
) internal pure returns (MemoryPointer ptr) {
assembly {
ptr := obj
}
}
/**
* @dev Get a CalldataPointer from ReceivedItem.
*
* @param obj The ReceivedItem object.
*
* @return ptr The CalldataPointer.
*/
function toCalldataPointer(
ReceivedItem calldata obj
) internal pure returns (CalldataPointer ptr) {
assembly {
ptr := obj
}
}
/**
* @dev Get a MemoryPointer from BasicOrderParameters.
*
* @param obj The BasicOrderParameters object.
*
* @return ptr The MemoryPointer.
*/
function toMemoryPointer(
BasicOrderParameters memory obj
) internal pure returns (MemoryPointer ptr) {
assembly {
ptr := obj
}
}
/**
* @dev Get a CalldataPointer from BasicOrderParameters.
*
* @param obj The BasicOrderParameters object.
*
* @return ptr The CalldataPointer.
*/
function toCalldataPointer(
BasicOrderParameters calldata obj
) internal pure returns (CalldataPointer ptr) {
assembly {
ptr := obj
}
}
/**
* @dev Get a MemoryPointer from AdditionalRecipient.
*
* @param obj The AdditionalRecipient object.
*
* @return ptr The MemoryPointer.
*/
function toMemoryPointer(
AdditionalRecipient memory obj
) internal pure returns (MemoryPointer ptr) {
assembly {
ptr := obj
}
}
/**
* @dev Get a CalldataPointer from AdditionalRecipient.
*
* @param obj The AdditionalRecipient object.
*
* @return ptr The CalldataPointer.
*/
function toCalldataPointer(
AdditionalRecipient calldata obj
) internal pure returns (CalldataPointer ptr) {
assembly {
ptr := obj
}
}
/**
* @dev Get a MemoryPointer from OrderParameters.
*
* @param obj The OrderParameters object.
*
* @return ptr The MemoryPointer.
*/
function toMemoryPointer(
OrderParameters memory obj
) internal pure returns (MemoryPointer ptr) {
assembly {
ptr := obj
}
}
/**
* @dev Get a CalldataPointer from OrderParameters.
*
* @param obj The OrderParameters object.
*
* @return ptr The CalldataPointer.
*/
function toCalldataPointer(
OrderParameters calldata obj
) internal pure returns (CalldataPointer ptr) {
assembly {
ptr := obj
}
}
/**
* @dev Get a MemoryPointer from Order.
*
* @param obj The Order object.
*
* @return ptr The MemoryPointer.
*/
function toMemoryPointer(
Order memory obj
) internal pure returns (MemoryPointer ptr) {
assembly {
ptr := obj
}
}
/**
* @dev Get a CalldataPointer from Order.
*
* @param obj The Order object.
*
* @return ptr The CalldataPointer.
*/
function toCalldataPointer(
Order calldata obj
) internal pure returns (CalldataPointer ptr) {
assembly {
ptr := obj
}
}
/**
* @dev Get a MemoryPointer from AdvancedOrder.
*
* @param obj The AdvancedOrder object.
*
* @return ptr The MemoryPointer.
*/
function toMemoryPointer(
AdvancedOrder memory obj
) internal pure returns (MemoryPointer ptr) {
assembly {
ptr := obj
}
}
/**
* @dev Get a CalldataPointer from AdvancedOrder.
*
* @param obj The AdvancedOrder object.
*
* @return ptr The CalldataPointer.
*/
function toCalldataPointer(
AdvancedOrder calldata obj
) internal pure returns (CalldataPointer ptr) {
assembly {
ptr := obj
}
}
/**
* @dev Get a MemoryPointer from OrderStatus.
*
* @param obj The OrderStatus object.
*
* @return ptr The MemoryPointer.
*/
function toMemoryPointer(
OrderStatus memory obj
) internal pure returns (MemoryPointer ptr) {
assembly {
ptr := obj
}
}
/**
* @dev Get a CalldataPointer from OrderStatus.
*
* @param obj The OrderStatus object.
*
* @return ptr The CalldataPointer.
*/
function toCalldataPointer(
OrderStatus calldata obj
) internal pure returns (CalldataPointer ptr) {
assembly {
ptr := obj
}
}
/**
* @dev Get a MemoryPointer from CriteriaResolver.
*
* @param obj The CriteriaResolver object.
*
* @return ptr The MemoryPointer.
*/
function toMemoryPointer(
CriteriaResolver memory obj
) internal pure returns (MemoryPointer ptr) {
assembly {
ptr := obj
}
}
/**
* @dev Get a CalldataPointer from CriteriaResolver.
*
* @param obj The CriteriaResolver object.
*
* @return ptr The CalldataPointer.
*/
function toCalldataPointer(
CriteriaResolver calldata obj
) internal pure returns (CalldataPointer ptr) {
assembly {
ptr := obj
}
}
/**
* @dev Get a MemoryPointer from Fulfillment.
*
* @param obj The Fulfillment object.
*
* @return ptr The MemoryPointer.
*/
function toMemoryPointer(
Fulfillment memory obj
) internal pure returns (MemoryPointer ptr) {
assembly {
ptr := obj
}
}
/**
* @dev Get a CalldataPointer from Fulfillment.
*
* @param obj The Fulfillment object.
*
* @return ptr The CalldataPointer.
*/
function toCalldataPointer(
Fulfillment calldata obj
) internal pure returns (CalldataPointer ptr) {
assembly {
ptr := obj
}
}
/**
* @dev Get a MemoryPointer from FulfillmentComponent.
*
* @param obj The FulfillmentComponent object.
*
* @return ptr The MemoryPointer.
*/
function toMemoryPointer(
FulfillmentComponent memory obj
) internal pure returns (MemoryPointer ptr) {
assembly {
ptr := obj
}
}
/**
* @dev Get a CalldataPointer from FulfillmentComponent.
*
* @param obj The FulfillmentComponent object.
*
* @return ptr The CalldataPointer.
*/
function toCalldataPointer(
FulfillmentComponent calldata obj
) internal pure returns (CalldataPointer ptr) {
assembly {
ptr := obj
}
}
/**
* @dev Get a MemoryPointer from Execution.
*
* @param obj The Execution object.
*
* @return ptr The MemoryPointer.
*/
function toMemoryPointer(
Execution memory obj
) internal pure returns (MemoryPointer ptr) {
assembly {
ptr := obj
}
}
/**
* @dev Get a CalldataPointer from Execution.
*
* @param obj The Execution object.
*
* @return ptr The CalldataPointer.
*/
function toCalldataPointer(
Execution calldata obj
) internal pure returns (CalldataPointer ptr) {
assembly {
ptr := obj
}
}
/**
* @dev Get a MemoryPointer from ZoneParameters.
*
* @param obj The ZoneParameters object.
*
* @return ptr The MemoryPointer.
*/
function toMemoryPointer(
ZoneParameters memory obj
) internal pure returns (MemoryPointer ptr) {
assembly {
ptr := obj
}
}
/**
* @dev Get a CalldataPointer from ZoneParameters.
*
* @param obj The ZoneParameters object.
*
* @return ptr The CalldataPointer.
*/
function toCalldataPointer(
ZoneParameters calldata obj
) internal pure returns (CalldataPointer ptr) {
assembly {
ptr := obj
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
import {
AdvancedOrder,
BasicOrderParameters,
CriteriaResolver,
Execution,
Fulfillment,
FulfillmentComponent,
Order,
OrderComponents
} from "../lib/ConsiderationStructs.sol";
/**
* @title ConsiderationInterface
* @author 0age
* @custom:version 1.5
* @notice Consideration is a generalized native token/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. Note that unspent offer item amounts or
* native tokens will not be reflected as part of
* this array.
*/
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. Note that unspent offer item amounts or
* native tokens will not be reflected as part of
* this array.
*/
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 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). Any unspent
* offer item amounts or native tokens will be transferred to the
* caller.
*
* @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. Note that unspent offer item amounts or
* native tokens will not be reflected as part of this
* array.
*/
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. Any unspent offer item
* amounts will be transferred to the designated recipient (with the
* null address signifying to use the caller) and any unspent native
* tokens will be returned to the caller.
*
* @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.
* @param recipient The intended recipient for all unspent offer
* item amounts, or the caller if the null address
* is supplied.
*
* @return executions An array of elements indicating the sequence of
* transfers performed as part of matching the given
* orders. Note that unspent offer item amounts or native
* tokens will not be reflected as part of this array.
*/
function matchAdvancedOrders(
AdvancedOrder[] calldata orders,
CriteriaResolver[] calldata criteriaResolvers,
Fulfillment[] calldata fulfillments,
address recipient
) 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 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. Note that this function costs less gas than
* `fulfillBasicOrder` due to the zero bytes in the function
* selector (0x00000000) which also results in earlier function
* dispatch.
*
* @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_efficient_6GL6yc(
BasicOrderParameters calldata parameters
) external payable returns (bool fulfilled);
/**
* @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
);
function getContractOffererNonce(
address contractOfferer
) external view returns (uint256 nonce);
/**
* @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.13;
import {ItemType, OrderType, Side} from "../../seaport-1.5/lib/ConsiderationEnums.sol";
import {AdvancedOrder, ConsiderationItem, CriteriaResolver, Execution, Fulfillment, FulfillmentComponent, OfferItem, OrderParameters, ReceivedItem, SpentItem} from "../../seaport-1.5/lib/ConsiderationStructs.sol";
import {AccumulatorStruct, OrderToExecute} from "./ReferenceConsiderationStructs.sol";
import {ReferenceOrderFulfiller} from "./ReferenceOrderFulfiller.sol";
import {ReferenceFulfillmentApplier} from "./ReferenceFulfillmentApplier.sol";
import {SeaportInterface} from "../../seaport-1.5/interfaces/SeaportInterface.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 ReferenceOrderCombiner is
ReferenceOrderFulfiller,
ReferenceFulfillmentApplier
{
/**
* @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
) ReferenceOrderFulfiller(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 their proxy 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 ordersToExecute The orders to execute. This is an
* explicit version of advancedOrders
* without memory optimization, that
* provides an array of spentItems and
* receivedItems for fulfillment and
* event emission.
*
* @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,
OrderToExecute[] memory ordersToExecute,
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 use conduits.
(
bytes32[] memory orderHashes,
bool containsNonOpen
) = _validateOrdersAndPrepareToFulfill(
advancedOrders,
ordersToExecute,
criteriaResolvers,
false, // Signifies that invalid orders should NOT revert.
maximumFulfilled,
recipient
);
// Execute transfers.
(availableOrders, executions) = _executeAvailableFulfillments(
advancedOrders,
ordersToExecute,
offerFulfillments,
considerationFulfillments,
fulfillerConduitKey,
recipient,
orderHashes,
containsNonOpen
);
// 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 ordersToExecute The orders to validate and execute.
* @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.
*
* @return orderHashes The hashes of the orders being fulfilled.
* @return containsNonOpen A boolean indicating whether any restricted or
* contract orders are present within the provided
* array of advanced orders.
*/
function _validateOrdersAndPrepareToFulfill(
AdvancedOrder[] memory advancedOrders,
OrderToExecute[] memory ordersToExecute,
CriteriaResolver[] memory criteriaResolvers,
bool revertOnInvalid,
uint256 maximumFulfilled,
address recipient
) internal returns (bytes32[] memory orderHashes, bool containsNonOpen) {
// Track the order hash for each order being fulfilled.
orderHashes = new bytes32[](advancedOrders.length);
// Determine whether or not order matching is underway.
bool nonMatchFn = msg.sig !=
SeaportInterface.matchAdvancedOrders.selector &&
msg.sig != SeaportInterface.matchOrders.selector;
// Declare a variable for tracking whether native offer items are
// present on orders that are not contract orders.
bool anyNativeOfferItemsOnNonContractOrders;
OfferItem[] memory offer;
// Iterate over each order.
for (uint256 i = 0; i < advancedOrders.length; ++i) {
// Retrieve the current order.
AdvancedOrder memory advancedOrder = advancedOrders[i];
// Retrieve the order to execute.
OrderToExecute memory orderToExecute = ordersToExecute[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;
// Mark fill fraction as zero as the order will not be used.
orderToExecute.numerator = 0;
// Continue iterating through the remaining orders.
continue;
}
// Validate it, update status, and determine fraction to fill.
(
bytes32 orderHash,
uint256 numerator,
uint256 denominator
) = _validateOrderAndUpdateStatus(advancedOrder, revertOnInvalid);
// 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;
// Mark fill fraction as zero as the order will not be used.
orderToExecute.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.
maximumFulfilled--;
// Retrieve array of offer items for the order in question.
offer = advancedOrder.parameters.offer;
// Determine the order type, used to check for eligibility for
// native token offer items as well as for the presence of
// restricted and contract orders (or non-open orders).
OrderType orderType = advancedOrder.parameters.orderType;
{
bool isNonContractOrder = orderType != OrderType.CONTRACT;
bool isNonOpenOrder = orderType != OrderType.FULL_OPEN &&
orderType != OrderType.PARTIAL_OPEN;
if (containsNonOpen == true || isNonOpenOrder == true) {
containsNonOpen = true;
}
// Iterate over each offer item on the order.
for (uint256 j = 0; j < offer.length; ++j) {
// Retrieve the offer item.
OfferItem memory offerItem = offer[j];
// Determine if there are any native offer items on non-contract
// orders.
anyNativeOfferItemsOnNonContractOrders =
anyNativeOfferItemsOnNonContractOrders ||
(offerItem.itemType == ItemType.NATIVE &&
isNonContractOrder);
// 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,
advancedOrder.parameters.startTime,
advancedOrder.parameters.endTime,
false // Round down.
);
// Modify the OrderToExecute Spent Item Amount.
orderToExecute.spentItems[j].amount = offerItem.startAmount;
// Modify the OrderToExecute Spent Item Original Amount.
orderToExecute.spentItemOriginalAmounts[j] = offerItem
.startAmount;
}
}
// Retrieve array of consideration items for order in question.
ConsiderationItem[] memory consideration = (
advancedOrder.parameters.consideration
);
// Iterate over each consideration item on the order.
for (uint256 j = 0; j < consideration.length; ++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
);
}
// TODO: Check with 0. Appears to be no longer in optimized.
// // Update end amount in memory to match the derived amount.
// considerationItem.endAmount = endAmount;
uint256 currentAmount = (
_locateCurrentAmount(
considerationItem.startAmount,
endAmount,
advancedOrder.parameters.startTime,
advancedOrder.parameters.endTime,
true // round up
)
);
considerationItem.startAmount = currentAmount;
// Modify the OrderToExecute Received item amount.
orderToExecute.receivedItems[j].amount = considerationItem
.startAmount;
// Modify the OrderToExecute Received item original amount.
orderToExecute.receivedItemOriginalAmounts[
j
] = considerationItem.startAmount;
}
}
if (anyNativeOfferItemsOnNonContractOrders && nonMatchFn) {
revert InvalidNativeOfferItem();
}
// Apply criteria resolvers to each order as applicable.
_applyCriteriaResolvers(ordersToExecute, criteriaResolvers);
// Emit an event for each order signifying that it has been fulfilled.
// Iterate over each order.
for (uint256 i = 0; i < advancedOrders.length; ++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
);
// Get the array of spentItems from the orderToExecute struct.
SpentItem[] memory spentItems = ordersToExecute[i].spentItems;
// Get the array of spent receivedItems from the
// orderToExecute struct.
ReceivedItem[] memory receivedItems = ordersToExecute[i]
.receivedItems;
// Emit an event signifying that the order has been fulfilled.
emit OrderFulfilled(
orderHashes[i],
orderParameters.offerer,
orderParameters.zone,
recipient,
spentItems,
receivedItems
);
}
}
/**
* @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 ordersToExecute The orders to execute. This is an
* explicit version of advancedOrders
* without memory optimization, that
* provides an array of spentItems and
* receivedItems for fulfillment and
* event emission.
* 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 (and
* direct approvals set on Consideration).
* @param recipient The intended recipient for all received
* items.
* @param orderHashes An array of order hashes for each order.
* @param containsNonOpen A boolean indicating whether any restricted or
* contract orders are present within the provided
* array of advanced 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.
* @return executions An array of elements indicating the
* sequence of transfers performed as part
* of matching the given orders.
*/
function _executeAvailableFulfillments(
AdvancedOrder[] memory advancedOrders,
OrderToExecute[] memory ordersToExecute,
FulfillmentComponent[][] memory offerFulfillments,
FulfillmentComponent[][] memory considerationFulfillments,
bytes32 fulfillerConduitKey,
address recipient,
bytes32[] memory orderHashes,
bool containsNonOpen
)
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
);
// Track number of filtered executions.
uint256 totalFilteredExecutions = 0;
// Iterate over each offer fulfillment.
for (uint256 i = 0; i < totalOfferFulfillments; ++i) {
// Derive aggregated execution corresponding with fulfillment.
Execution memory execution = _aggregateAvailable(
ordersToExecute,
Side.OFFER,
offerFulfillments[i],
fulfillerConduitKey,
recipient
);
// If offerer and recipient on the execution are the same and the
// execution item has a non-native item type...
if (
execution.item.recipient == execution.offerer &&
execution.item.itemType != ItemType.NATIVE
) {
// 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) {
// Derive aggregated execution corresponding with fulfillment.
Execution memory execution = _aggregateAvailable(
ordersToExecute,
Side.CONSIDERATION,
considerationFulfillments[i],
fulfillerConduitKey,
address(0) // unused
);
// If offerer and recipient on the execution are the same and the
// execution item has a non-native item type...
if (
execution.item.recipient == execution.offerer &&
execution.item.itemType != ItemType.NATIVE
) {
// 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) {
/**
* The following is highly inefficient, but written this way
* to show in the most simplest form what the optimized
* contract is performing inside its assembly.
*/
// Get the total execution length.
uint256 executionLength = (totalOfferFulfillments +
totalConsiderationFulfillments) - totalFilteredExecutions;
// Create an array of executions that will be executed.
Execution[] memory filteredExecutions = new Execution[](
executionLength
);
// Create new array from the existing Executions
for (uint256 i = 0; i < executionLength; ++i) {
filteredExecutions[i] = executions[i];
}
// Set the executions array to the newly created array.
executions = filteredExecutions;
}
// Revert if no orders are available.
if (executions.length == 0) {
revert NoSpecifiedOrdersAvailable();
}
// Perform final checks and compress executions into standard and batch.
availableOrders = _performFinalChecksAndExecuteOrders(
advancedOrders,
ordersToExecute,
executions,
orderHashes,
recipient,
containsNonOpen
);
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 ordersToExecute The orders to check and perform executions.
* @param executions An array of uncompressed elements indicating
* the sequence of transfers to perform when
* fulfilling the given orders.
*
* @param executions An array of elements indicating the sequence of
* transfers to perform when fulfilling the given
* orders.
* @param orderHashes An array of order hashes for each order.
* @param containsNonOpen A boolean indicating whether any restricted or
* contract orders are present within the provided
* array of advanced 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,
OrderToExecute[] memory ordersToExecute,
Execution[] memory executions,
bytes32[] memory orderHashes,
address recipient,
bool containsNonOpen
) 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);
// Create the accumulator struct.
AccumulatorStruct memory accumulatorStruct;
{
// Iterate over each execution.
for (uint256 i = 0; i < executions.length; ++i) {
// 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 > address(this).balance) {
revert InsufficientNativeTokensSupplied();
}
}
// Transfer the item specified by the execution.
_transfer(
item,
execution.offerer,
execution.conduitKey,
accumulatorStruct
);
}
}
// Duplicate recipient onto stack to avoid stack-too-deep.
address _recipient = recipient;
// Iterate over orders to ensure all consideration items are met.
for (uint256 i = 0; i < ordersToExecute.length; ++i) {
// Retrieve the order in question.
OrderToExecute memory orderToExecute = ordersToExecute[i];
// Skip consideration item checks for order if not fulfilled.
if (orderToExecute.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 the original order in question.
AdvancedOrder memory advancedOrder = advancedOrders[i];
// Retrieve the order parameters.
OrderParameters memory parameters = advancedOrder.parameters;
{
// Retrieve offer items.
OfferItem[] memory offer = parameters.offer;
// Read length of offer array & place on the stack.
uint256 totalOfferItems = offer.length;
// Iterate over each offer item to restore it.
for (uint256 j = 0; j < totalOfferItems; ++j) {
SpentItem memory offerSpentItem = orderToExecute.spentItems[
j
];
// Retrieve remaining amount on the offer item.
uint256 unspentAmount = offerSpentItem.amount;
// Retrieve original amount on the offer item.
uint256 originalAmount = orderToExecute
.spentItemOriginalAmounts[j];
// Transfer to recipient if unspent amount is not zero.
// Note that the transfer will not be reflected in the
// executions array.
if (unspentAmount != 0) {
_transfer(
_convertSpentItemToReceivedItemWithRecipient(
offerSpentItem,
_recipient
),
parameters.offerer,
parameters.conduitKey,
accumulatorStruct
);
}
// Restore original amount on the offer item.
offerSpentItem.amount = originalAmount;
}
}
{
// Retrieve consideration items to ensure they are fulfilled.
ReceivedItem[] memory consideration = (
orderToExecute.receivedItems
);
// Iterate over each consideration item to ensure it is met.
for (uint256 j = 0; j < consideration.length; ++j) {
// Retrieve remaining amount on the consideration item.
uint256 unmetAmount = consideration[j].amount;
// Revert if the remaining amount is not zero.
if (unmetAmount != 0) {
revert ConsiderationNotMet(i, j, unmetAmount);
}
// Restore original amount.
consideration[j].amount = orderToExecute
.receivedItemOriginalAmounts[j];
}
}
{
// Get offer items as well.
SpentItem[] memory offer = (orderToExecute.spentItems);
// Iterate over each consideration item to ensure it is met.
for (uint256 j = 0; j < offer.length; ++j) {
// Restore original amount.
offer[j].amount = orderToExecute.spentItemOriginalAmounts[
j
];
}
}
}
// Trigger any remaining accumulated transfers via call to the
// conduit.
_triggerIfArmed(accumulatorStruct);
// If any native token remains after fulfillments, return it to the
// caller.
if (address(this).balance != 0) {
_transferNativeTokens(payable(msg.sender), address(this).balance);
}
// If any restricted or contract orders are present in the group of
// orders being fulfilled, perform any validateOrder or ratifyOrder
// calls after all executions and related transfers are complete.
if (containsNonOpen) {
// Iterate over orders to ensure all consideration items are met.
for (uint256 i = 0; i < ordersToExecute.length; ++i) {
// Retrieve the order in question.
OrderToExecute memory orderToExecute = ordersToExecute[i];
// Skip consideration item checks for order if not fulfilled.
if (orderToExecute.numerator == 0) {
continue;
}
// Retrieve the original order in question.
AdvancedOrder memory advancedOrder = advancedOrders[i];
// Ensure restricted orders have valid submitter or pass check.
_assertRestrictedAdvancedOrderValidity(
advancedOrder,
orderToExecute,
orderHashes,
orderHashes[i],
advancedOrder.parameters.zoneHash,
advancedOrder.parameters.orderType,
orderToExecute.offerer,
advancedOrder.parameters.zone
);
}
}
// Return the array containing available orders.
return availableOrders;
}
/**
* @dev Internal function to convert a spent item to an equivalent
* ReceivedItem with a specified recipient.
*
* @param offerItem The "offerItem" represented by a SpentItem
* struct.
* @param recipient The intended recipient of the converted
* ReceivedItem
*
* @return ReceivedItem The derived ReceivedItem including the
* specified recipient.
*/
function _convertSpentItemToReceivedItemWithRecipient(
SpentItem memory offerItem,
address recipient
) internal pure returns (ReceivedItem memory) {
address payable _recipient;
_recipient = payable(recipient);
return
ReceivedItem(
offerItem.itemType,
offerItem.token,
offerItem.identifier,
offerItem.amount,
_recipient
);
}
/**
* @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.
* @param recipient The intended recipient for all unspent offer
* item amounts.
*
* @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,
address recipient
) internal returns (Execution[] memory executions) {
// Convert Advanced Orders to Orders to Execute
OrderToExecute[]
memory ordersToExecute = _convertAdvancedToOrdersToExecute(
advancedOrders
);
// Validate orders, apply amounts, & determine if they utilize conduits.
(
bytes32[] memory orderHashes,
bool containsNonOpen
) = _validateOrdersAndPrepareToFulfill(
advancedOrders,
ordersToExecute,
criteriaResolvers,
true, // Signifies that invalid orders should revert.
advancedOrders.length,
recipient
);
// Emit OrdersMatched event.
emit OrdersMatched(orderHashes);
// Fulfill the orders using the supplied fulfillments.
return
_fulfillAdvancedOrders(
advancedOrders,
ordersToExecute,
fulfillments,
orderHashes,
recipient,
containsNonOpen
);
}
/**
* @dev Internal function to fulfill an arbitrary number of orders, either
* full or partial, after validating, adjusting amounts, and applying
* criteria resolvers.
*
* @param ordersToExecute 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.
* @param orderHashes An array of order hashes for each order.
*
* @param containsNonOpen A boolean indicating whether any restricted or
* contract orders are present within the provided
* array of advanced orders.
*
* @return executions An array of elements indicating the sequence
* of transfers performed as part of
* matching the given orders.
*/
function _fulfillAdvancedOrders(
AdvancedOrder[] memory advancedOrders,
OrderToExecute[] memory ordersToExecute,
Fulfillment[] calldata fulfillments,
bytes32[] memory orderHashes,
address recipient,
bool containsNonOpen
) 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);
// 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(
ordersToExecute,
fulfillment.offerComponents,
fulfillment.considerationComponents,
i
);
// If offerer and recipient on the execution are the same and the
// execution item has a non-native item type...
if (
execution.item.recipient == execution.offerer &&
execution.item.itemType != ItemType.NATIVE
) {
// 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) {
uint256 executionLength = totalFulfillments -
totalFilteredExecutions;
Execution[] memory filteredExecutions = new Execution[](
executionLength
);
// Create new array from executions.
for (uint256 i = 0; i < executionLength; ++i) {
filteredExecutions[i] = executions[i];
}
executions = filteredExecutions;
}
// Perform final checks and execute orders.
_performFinalChecksAndExecuteOrders(
advancedOrders,
ordersToExecute,
executions,
orderHashes,
recipient,
containsNonOpen
);
// Return executions.
return executions;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
import {ItemType, OrderType} from "../../seaport-1.5/lib/ConsiderationEnums.sol";
import {ReceivedItem, SpentItem} from "../../seaport-1.5/lib/ConsiderationStructs.sol";
import {ConduitTransfer} from "../../seaport-1.5/conduit/lib/ConduitStructs.sol";
// This file should only be used by the Reference Implementation
/**
* @dev A struct used to hold Consideration Indexes and Fulfillment validity.
*/
struct ConsiderationItemIndicesAndValidity {
uint256 orderIndex;
uint256 itemIndex;
bool invalidFulfillment;
bool missingItemAmount;
}
/**
* @dev A struct used to hold all ItemTypes/Token of a Basic Order Fulfillment
* used in _prepareBasicFulfillmentFromCalldata
*/
struct FulfillmentItemTypes {
OrderType orderType;
ItemType receivedItemType;
ItemType additionalRecipientsItemType;
address additionalRecipientsToken;
ItemType offeredItemType;
}
/**
* @dev A struct used to hold all the hashes of a Basic Order Fulfillment
* used in _prepareBasicFulfillmentFromCalldata and _hashOrder
*/
struct BasicFulfillmentHashes {
bytes32 typeHash;
bytes32 orderHash;
bytes32 offerItemsHash;
bytes32[] considerationHashes;
bytes32 receivedItemsHash;
bytes32 receivedItemHash;
bytes32 offerItemHash;
}
/**
* @dev A struct that is an explicit version of advancedOrders without
* memory optimization, that provides an array of spentItems
* and receivedItems for fulfillment and event emission.
*/
struct OrderToExecute {
address offerer;
SpentItem[] spentItems; // Offer
ReceivedItem[] receivedItems; // Consideration
bytes32 conduitKey;
uint120 numerator;
uint256[] spentItemOriginalAmounts;
uint256[] receivedItemOriginalAmounts;
}
/**
* @dev A struct containing the data used to apply a
* fraction to an order.
*/
struct FractionData {
uint256 numerator; // The portion of the order that should be filled.
uint256 denominator; // The total size of the order
bytes32 fulfillerConduitKey; // The fulfiller's conduit key.
uint256 startTime; // The start time of the order.
uint256 endTime; // The end time of the order.
}
/**
* @dev A struct containing conduit transfer data and its
* corresponding conduitKey.
*/
struct AccumulatorStruct {
bytes32 conduitKey;
ConduitTransfer[] transfers;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
type CalldataPointer is uint256;
type ReturndataPointer is uint256;
type MemoryPointer is uint256;
using CalldataPointerLib for CalldataPointer global;
using MemoryPointerLib for MemoryPointer global;
using ReturndataPointerLib for ReturndataPointer global;
using CalldataReaders for CalldataPointer global;
using ReturndataReaders for ReturndataPointer global;
using MemoryReaders for MemoryPointer global;
using MemoryWriters for MemoryPointer global;
CalldataPointer constant CalldataStart = CalldataPointer.wrap(0x04);
MemoryPointer constant FreeMemoryPPtr = MemoryPointer.wrap(0x40);
uint256 constant IdentityPrecompileAddress = 0x4;
uint256 constant OffsetOrLengthMask = 0xffffffff;
uint256 constant _OneWord = 0x20;
uint256 constant _FreeMemoryPointerSlot = 0x40;
/// @dev Allocates `size` bytes in memory by increasing the free memory pointer
/// and returns the memory pointer to the first byte of the allocated region.
// (Free functions cannot have visibility.)
// solhint-disable-next-line func-visibility
function malloc(uint256 size) pure returns (MemoryPointer mPtr) {
assembly {
mPtr := mload(_FreeMemoryPointerSlot)
mstore(_FreeMemoryPointerSlot, add(mPtr, size))
}
}
// (Free functions cannot have visibility.)
// solhint-disable-next-line func-visibility
function getFreeMemoryPointer() pure returns (MemoryPointer mPtr) {
mPtr = FreeMemoryPPtr.readMemoryPointer();
}
// (Free functions cannot have visibility.)
// solhint-disable-next-line func-visibility
function setFreeMemoryPointer(MemoryPointer mPtr) pure {
FreeMemoryPPtr.write(mPtr);
}
library CalldataPointerLib {
function lt(
CalldataPointer a,
CalldataPointer b
) internal pure returns (bool c) {
assembly {
c := lt(a, b)
}
}
function gt(
CalldataPointer a,
CalldataPointer b
) internal pure returns (bool c) {
assembly {
c := gt(a, b)
}
}
function eq(
CalldataPointer a,
CalldataPointer b
) internal pure returns (bool c) {
assembly {
c := eq(a, b)
}
}
function isNull(CalldataPointer a) internal pure returns (bool b) {
assembly {
b := iszero(a)
}
}
/// @dev Resolves an offset stored at `cdPtr + headOffset` to a calldata.
/// pointer `cdPtr` must point to some parent object with a dynamic
/// type's head stored at `cdPtr + headOffset`.
function pptr(
CalldataPointer cdPtr,
uint256 headOffset
) internal pure returns (CalldataPointer cdPtrChild) {
cdPtrChild = cdPtr.offset(
cdPtr.offset(headOffset).readUint256() & OffsetOrLengthMask
);
}
/// @dev Resolves an offset stored at `cdPtr` to a calldata pointer.
/// `cdPtr` must point to some parent object with a dynamic type as its
/// first member, e.g. `struct { bytes data; }`
function pptr(
CalldataPointer cdPtr
) internal pure returns (CalldataPointer cdPtrChild) {
cdPtrChild = cdPtr.offset(cdPtr.readUint256() & OffsetOrLengthMask);
}
/// @dev Returns the calldata pointer one word after `cdPtr`.
function next(
CalldataPointer cdPtr
) internal pure returns (CalldataPointer cdPtrNext) {
assembly {
cdPtrNext := add(cdPtr, _OneWord)
}
}
/// @dev Returns the calldata pointer `_offset` bytes after `cdPtr`.
function offset(
CalldataPointer cdPtr,
uint256 _offset
) internal pure returns (CalldataPointer cdPtrNext) {
assembly {
cdPtrNext := add(cdPtr, _offset)
}
}
/// @dev Copies `size` bytes from calldata starting at `src` to memory at
/// `dst`.
function copy(
CalldataPointer src,
MemoryPointer dst,
uint256 size
) internal pure {
assembly {
calldatacopy(dst, src, size)
}
}
}
library ReturndataPointerLib {
function lt(
ReturndataPointer a,
ReturndataPointer b
) internal pure returns (bool c) {
assembly {
c := lt(a, b)
}
}
function gt(
ReturndataPointer a,
ReturndataPointer b
) internal pure returns (bool c) {
assembly {
c := gt(a, b)
}
}
function eq(
ReturndataPointer a,
ReturndataPointer b
) internal pure returns (bool c) {
assembly {
c := eq(a, b)
}
}
function isNull(ReturndataPointer a) internal pure returns (bool b) {
assembly {
b := iszero(a)
}
}
/// @dev Resolves an offset stored at `rdPtr + headOffset` to a returndata
/// pointer. `rdPtr` must point to some parent object with a dynamic
/// type's head stored at `rdPtr + headOffset`.
function pptr(
ReturndataPointer rdPtr,
uint256 headOffset
) internal pure returns (ReturndataPointer rdPtrChild) {
rdPtrChild = rdPtr.offset(
rdPtr.offset(headOffset).readUint256() & OffsetOrLengthMask
);
}
/// @dev Resolves an offset stored at `rdPtr` to a returndata pointer.
/// `rdPtr` must point to some parent object with a dynamic type as its
/// first member, e.g. `struct { bytes data; }`
function pptr(
ReturndataPointer rdPtr
) internal pure returns (ReturndataPointer rdPtrChild) {
rdPtrChild = rdPtr.offset(rdPtr.readUint256() & OffsetOrLengthMask);
}
/// @dev Returns the returndata pointer one word after `cdPtr`.
function next(
ReturndataPointer rdPtr
) internal pure returns (ReturndataPointer rdPtrNext) {
assembly {
rdPtrNext := add(rdPtr, _OneWord)
}
}
/// @dev Returns the returndata pointer `_offset` bytes after `cdPtr`.
function offset(
ReturndataPointer rdPtr,
uint256 _offset
) internal pure returns (ReturndataPointer rdPtrNext) {
assembly {
rdPtrNext := add(rdPtr, _offset)
}
}
/// @dev Copies `size` bytes from returndata starting at `src` to memory at
/// `dst`.
function copy(
ReturndataPointer src,
MemoryPointer dst,
uint256 size
) internal pure {
assembly {
returndatacopy(dst, src, size)
}
}
}
library MemoryPointerLib {
function copy(
MemoryPointer src,
MemoryPointer dst,
uint256 size
) internal view {
assembly {
let success := staticcall(
gas(),
IdentityPrecompileAddress,
src,
size,
dst,
size
)
if or(iszero(returndatasize()), iszero(success)) {
revert(0, 0)
}
}
}
function lt(
MemoryPointer a,
MemoryPointer b
) internal pure returns (bool c) {
assembly {
c := lt(a, b)
}
}
function gt(
MemoryPointer a,
MemoryPointer b
) internal pure returns (bool c) {
assembly {
c := gt(a, b)
}
}
function eq(
MemoryPointer a,
MemoryPointer b
) internal pure returns (bool c) {
assembly {
c := eq(a, b)
}
}
function isNull(MemoryPointer a) internal pure returns (bool b) {
assembly {
b := iszero(a)
}
}
function hash(
MemoryPointer ptr,
uint256 length
) internal pure returns (bytes32 _hash) {
assembly {
_hash := keccak256(ptr, length)
}
}
/// @dev Returns the memory pointer one word after `mPtr`.
function next(
MemoryPointer mPtr
) internal pure returns (MemoryPointer mPtrNext) {
assembly {
mPtrNext := add(mPtr, _OneWord)
}
}
/// @dev Returns the memory pointer `_offset` bytes after `mPtr`.
function offset(
MemoryPointer mPtr,
uint256 _offset
) internal pure returns (MemoryPointer mPtrNext) {
assembly {
mPtrNext := add(mPtr, _offset)
}
}
/// @dev Resolves a pointer at `mPtr + headOffset` to a memory
/// pointer. `mPtr` must point to some parent object with a dynamic
/// type's pointer stored at `mPtr + headOffset`.
function pptr(
MemoryPointer mPtr,
uint256 headOffset
) internal pure returns (MemoryPointer mPtrChild) {
mPtrChild = mPtr.offset(headOffset).readMemoryPointer();
}
/// @dev Resolves a pointer stored at `mPtr` to a memory pointer.
/// `mPtr` must point to some parent object with a dynamic type as its
/// first member, e.g. `struct { bytes data; }`
function pptr(
MemoryPointer mPtr
) internal pure returns (MemoryPointer mPtrChild) {
mPtrChild = mPtr.readMemoryPointer();
}
}
library CalldataReaders {
/// @dev Reads the value at `cdPtr` and applies a mask to return only the
/// last 4 bytes.
function readMaskedUint256(
CalldataPointer cdPtr
) internal pure returns (uint256 value) {
value = cdPtr.readUint256() & OffsetOrLengthMask;
}
/// @dev Reads the bool at `cdPtr` in calldata.
function readBool(
CalldataPointer cdPtr
) internal pure returns (bool value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the address at `cdPtr` in calldata.
function readAddress(
CalldataPointer cdPtr
) internal pure returns (address value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the bytes1 at `cdPtr` in calldata.
function readBytes1(
CalldataPointer cdPtr
) internal pure returns (bytes1 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the bytes2 at `cdPtr` in calldata.
function readBytes2(
CalldataPointer cdPtr
) internal pure returns (bytes2 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the bytes3 at `cdPtr` in calldata.
function readBytes3(
CalldataPointer cdPtr
) internal pure returns (bytes3 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the bytes4 at `cdPtr` in calldata.
function readBytes4(
CalldataPointer cdPtr
) internal pure returns (bytes4 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the bytes5 at `cdPtr` in calldata.
function readBytes5(
CalldataPointer cdPtr
) internal pure returns (bytes5 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the bytes6 at `cdPtr` in calldata.
function readBytes6(
CalldataPointer cdPtr
) internal pure returns (bytes6 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the bytes7 at `cdPtr` in calldata.
function readBytes7(
CalldataPointer cdPtr
) internal pure returns (bytes7 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the bytes8 at `cdPtr` in calldata.
function readBytes8(
CalldataPointer cdPtr
) internal pure returns (bytes8 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the bytes9 at `cdPtr` in calldata.
function readBytes9(
CalldataPointer cdPtr
) internal pure returns (bytes9 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the bytes10 at `cdPtr` in calldata.
function readBytes10(
CalldataPointer cdPtr
) internal pure returns (bytes10 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the bytes11 at `cdPtr` in calldata.
function readBytes11(
CalldataPointer cdPtr
) internal pure returns (bytes11 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the bytes12 at `cdPtr` in calldata.
function readBytes12(
CalldataPointer cdPtr
) internal pure returns (bytes12 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the bytes13 at `cdPtr` in calldata.
function readBytes13(
CalldataPointer cdPtr
) internal pure returns (bytes13 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the bytes14 at `cdPtr` in calldata.
function readBytes14(
CalldataPointer cdPtr
) internal pure returns (bytes14 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the bytes15 at `cdPtr` in calldata.
function readBytes15(
CalldataPointer cdPtr
) internal pure returns (bytes15 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the bytes16 at `cdPtr` in calldata.
function readBytes16(
CalldataPointer cdPtr
) internal pure returns (bytes16 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the bytes17 at `cdPtr` in calldata.
function readBytes17(
CalldataPointer cdPtr
) internal pure returns (bytes17 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the bytes18 at `cdPtr` in calldata.
function readBytes18(
CalldataPointer cdPtr
) internal pure returns (bytes18 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the bytes19 at `cdPtr` in calldata.
function readBytes19(
CalldataPointer cdPtr
) internal pure returns (bytes19 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the bytes20 at `cdPtr` in calldata.
function readBytes20(
CalldataPointer cdPtr
) internal pure returns (bytes20 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the bytes21 at `cdPtr` in calldata.
function readBytes21(
CalldataPointer cdPtr
) internal pure returns (bytes21 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the bytes22 at `cdPtr` in calldata.
function readBytes22(
CalldataPointer cdPtr
) internal pure returns (bytes22 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the bytes23 at `cdPtr` in calldata.
function readBytes23(
CalldataPointer cdPtr
) internal pure returns (bytes23 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the bytes24 at `cdPtr` in calldata.
function readBytes24(
CalldataPointer cdPtr
) internal pure returns (bytes24 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the bytes25 at `cdPtr` in calldata.
function readBytes25(
CalldataPointer cdPtr
) internal pure returns (bytes25 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the bytes26 at `cdPtr` in calldata.
function readBytes26(
CalldataPointer cdPtr
) internal pure returns (bytes26 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the bytes27 at `cdPtr` in calldata.
function readBytes27(
CalldataPointer cdPtr
) internal pure returns (bytes27 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the bytes28 at `cdPtr` in calldata.
function readBytes28(
CalldataPointer cdPtr
) internal pure returns (bytes28 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the bytes29 at `cdPtr` in calldata.
function readBytes29(
CalldataPointer cdPtr
) internal pure returns (bytes29 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the bytes30 at `cdPtr` in calldata.
function readBytes30(
CalldataPointer cdPtr
) internal pure returns (bytes30 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the bytes31 at `cdPtr` in calldata.
function readBytes31(
CalldataPointer cdPtr
) internal pure returns (bytes31 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the bytes32 at `cdPtr` in calldata.
function readBytes32(
CalldataPointer cdPtr
) internal pure returns (bytes32 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the uint8 at `cdPtr` in calldata.
function readUint8(
CalldataPointer cdPtr
) internal pure returns (uint8 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the uint16 at `cdPtr` in calldata.
function readUint16(
CalldataPointer cdPtr
) internal pure returns (uint16 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the uint24 at `cdPtr` in calldata.
function readUint24(
CalldataPointer cdPtr
) internal pure returns (uint24 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the uint32 at `cdPtr` in calldata.
function readUint32(
CalldataPointer cdPtr
) internal pure returns (uint32 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the uint40 at `cdPtr` in calldata.
function readUint40(
CalldataPointer cdPtr
) internal pure returns (uint40 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the uint48 at `cdPtr` in calldata.
function readUint48(
CalldataPointer cdPtr
) internal pure returns (uint48 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the uint56 at `cdPtr` in calldata.
function readUint56(
CalldataPointer cdPtr
) internal pure returns (uint56 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the uint64 at `cdPtr` in calldata.
function readUint64(
CalldataPointer cdPtr
) internal pure returns (uint64 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the uint72 at `cdPtr` in calldata.
function readUint72(
CalldataPointer cdPtr
) internal pure returns (uint72 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the uint80 at `cdPtr` in calldata.
function readUint80(
CalldataPointer cdPtr
) internal pure returns (uint80 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the uint88 at `cdPtr` in calldata.
function readUint88(
CalldataPointer cdPtr
) internal pure returns (uint88 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the uint96 at `cdPtr` in calldata.
function readUint96(
CalldataPointer cdPtr
) internal pure returns (uint96 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the uint104 at `cdPtr` in calldata.
function readUint104(
CalldataPointer cdPtr
) internal pure returns (uint104 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the uint112 at `cdPtr` in calldata.
function readUint112(
CalldataPointer cdPtr
) internal pure returns (uint112 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the uint120 at `cdPtr` in calldata.
function readUint120(
CalldataPointer cdPtr
) internal pure returns (uint120 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the uint128 at `cdPtr` in calldata.
function readUint128(
CalldataPointer cdPtr
) internal pure returns (uint128 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the uint136 at `cdPtr` in calldata.
function readUint136(
CalldataPointer cdPtr
) internal pure returns (uint136 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the uint144 at `cdPtr` in calldata.
function readUint144(
CalldataPointer cdPtr
) internal pure returns (uint144 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the uint152 at `cdPtr` in calldata.
function readUint152(
CalldataPointer cdPtr
) internal pure returns (uint152 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the uint160 at `cdPtr` in calldata.
function readUint160(
CalldataPointer cdPtr
) internal pure returns (uint160 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the uint168 at `cdPtr` in calldata.
function readUint168(
CalldataPointer cdPtr
) internal pure returns (uint168 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the uint176 at `cdPtr` in calldata.
function readUint176(
CalldataPointer cdPtr
) internal pure returns (uint176 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the uint184 at `cdPtr` in calldata.
function readUint184(
CalldataPointer cdPtr
) internal pure returns (uint184 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the uint192 at `cdPtr` in calldata.
function readUint192(
CalldataPointer cdPtr
) internal pure returns (uint192 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the uint200 at `cdPtr` in calldata.
function readUint200(
CalldataPointer cdPtr
) internal pure returns (uint200 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the uint208 at `cdPtr` in calldata.
function readUint208(
CalldataPointer cdPtr
) internal pure returns (uint208 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the uint216 at `cdPtr` in calldata.
function readUint216(
CalldataPointer cdPtr
) internal pure returns (uint216 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the uint224 at `cdPtr` in calldata.
function readUint224(
CalldataPointer cdPtr
) internal pure returns (uint224 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the uint232 at `cdPtr` in calldata.
function readUint232(
CalldataPointer cdPtr
) internal pure returns (uint232 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the uint240 at `cdPtr` in calldata.
function readUint240(
CalldataPointer cdPtr
) internal pure returns (uint240 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the uint248 at `cdPtr` in calldata.
function readUint248(
CalldataPointer cdPtr
) internal pure returns (uint248 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the uint256 at `cdPtr` in calldata.
function readUint256(
CalldataPointer cdPtr
) internal pure returns (uint256 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the int8 at `cdPtr` in calldata.
function readInt8(
CalldataPointer cdPtr
) internal pure returns (int8 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the int16 at `cdPtr` in calldata.
function readInt16(
CalldataPointer cdPtr
) internal pure returns (int16 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the int24 at `cdPtr` in calldata.
function readInt24(
CalldataPointer cdPtr
) internal pure returns (int24 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the int32 at `cdPtr` in calldata.
function readInt32(
CalldataPointer cdPtr
) internal pure returns (int32 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the int40 at `cdPtr` in calldata.
function readInt40(
CalldataPointer cdPtr
) internal pure returns (int40 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the int48 at `cdPtr` in calldata.
function readInt48(
CalldataPointer cdPtr
) internal pure returns (int48 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the int56 at `cdPtr` in calldata.
function readInt56(
CalldataPointer cdPtr
) internal pure returns (int56 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the int64 at `cdPtr` in calldata.
function readInt64(
CalldataPointer cdPtr
) internal pure returns (int64 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the int72 at `cdPtr` in calldata.
function readInt72(
CalldataPointer cdPtr
) internal pure returns (int72 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the int80 at `cdPtr` in calldata.
function readInt80(
CalldataPointer cdPtr
) internal pure returns (int80 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the int88 at `cdPtr` in calldata.
function readInt88(
CalldataPointer cdPtr
) internal pure returns (int88 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the int96 at `cdPtr` in calldata.
function readInt96(
CalldataPointer cdPtr
) internal pure returns (int96 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the int104 at `cdPtr` in calldata.
function readInt104(
CalldataPointer cdPtr
) internal pure returns (int104 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the int112 at `cdPtr` in calldata.
function readInt112(
CalldataPointer cdPtr
) internal pure returns (int112 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the int120 at `cdPtr` in calldata.
function readInt120(
CalldataPointer cdPtr
) internal pure returns (int120 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the int128 at `cdPtr` in calldata.
function readInt128(
CalldataPointer cdPtr
) internal pure returns (int128 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the int136 at `cdPtr` in calldata.
function readInt136(
CalldataPointer cdPtr
) internal pure returns (int136 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the int144 at `cdPtr` in calldata.
function readInt144(
CalldataPointer cdPtr
) internal pure returns (int144 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the int152 at `cdPtr` in calldata.
function readInt152(
CalldataPointer cdPtr
) internal pure returns (int152 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the int160 at `cdPtr` in calldata.
function readInt160(
CalldataPointer cdPtr
) internal pure returns (int160 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the int168 at `cdPtr` in calldata.
function readInt168(
CalldataPointer cdPtr
) internal pure returns (int168 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the int176 at `cdPtr` in calldata.
function readInt176(
CalldataPointer cdPtr
) internal pure returns (int176 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the int184 at `cdPtr` in calldata.
function readInt184(
CalldataPointer cdPtr
) internal pure returns (int184 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the int192 at `cdPtr` in calldata.
function readInt192(
CalldataPointer cdPtr
) internal pure returns (int192 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the int200 at `cdPtr` in calldata.
function readInt200(
CalldataPointer cdPtr
) internal pure returns (int200 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the int208 at `cdPtr` in calldata.
function readInt208(
CalldataPointer cdPtr
) internal pure returns (int208 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the int216 at `cdPtr` in calldata.
function readInt216(
CalldataPointer cdPtr
) internal pure returns (int216 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the int224 at `cdPtr` in calldata.
function readInt224(
CalldataPointer cdPtr
) internal pure returns (int224 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the int232 at `cdPtr` in calldata.
function readInt232(
CalldataPointer cdPtr
) internal pure returns (int232 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the int240 at `cdPtr` in calldata.
function readInt240(
CalldataPointer cdPtr
) internal pure returns (int240 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the int248 at `cdPtr` in calldata.
function readInt248(
CalldataPointer cdPtr
) internal pure returns (int248 value) {
assembly {
value := calldataload(cdPtr)
}
}
/// @dev Reads the int256 at `cdPtr` in calldata.
function readInt256(
CalldataPointer cdPtr
) internal pure returns (int256 value) {
assembly {
value := calldataload(cdPtr)
}
}
}
library ReturndataReaders {
/// @dev Reads value at `rdPtr` & applies a mask to return only last 4 bytes
function readMaskedUint256(
ReturndataPointer rdPtr
) internal pure returns (uint256 value) {
value = rdPtr.readUint256() & OffsetOrLengthMask;
}
/// @dev Reads the bool at `rdPtr` in returndata.
function readBool(
ReturndataPointer rdPtr
) internal pure returns (bool value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the address at `rdPtr` in returndata.
function readAddress(
ReturndataPointer rdPtr
) internal pure returns (address value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the bytes1 at `rdPtr` in returndata.
function readBytes1(
ReturndataPointer rdPtr
) internal pure returns (bytes1 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the bytes2 at `rdPtr` in returndata.
function readBytes2(
ReturndataPointer rdPtr
) internal pure returns (bytes2 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the bytes3 at `rdPtr` in returndata.
function readBytes3(
ReturndataPointer rdPtr
) internal pure returns (bytes3 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the bytes4 at `rdPtr` in returndata.
function readBytes4(
ReturndataPointer rdPtr
) internal pure returns (bytes4 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the bytes5 at `rdPtr` in returndata.
function readBytes5(
ReturndataPointer rdPtr
) internal pure returns (bytes5 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the bytes6 at `rdPtr` in returndata.
function readBytes6(
ReturndataPointer rdPtr
) internal pure returns (bytes6 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the bytes7 at `rdPtr` in returndata.
function readBytes7(
ReturndataPointer rdPtr
) internal pure returns (bytes7 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the bytes8 at `rdPtr` in returndata.
function readBytes8(
ReturndataPointer rdPtr
) internal pure returns (bytes8 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the bytes9 at `rdPtr` in returndata.
function readBytes9(
ReturndataPointer rdPtr
) internal pure returns (bytes9 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the bytes10 at `rdPtr` in returndata.
function readBytes10(
ReturndataPointer rdPtr
) internal pure returns (bytes10 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the bytes11 at `rdPtr` in returndata.
function readBytes11(
ReturndataPointer rdPtr
) internal pure returns (bytes11 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the bytes12 at `rdPtr` in returndata.
function readBytes12(
ReturndataPointer rdPtr
) internal pure returns (bytes12 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the bytes13 at `rdPtr` in returndata.
function readBytes13(
ReturndataPointer rdPtr
) internal pure returns (bytes13 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the bytes14 at `rdPtr` in returndata.
function readBytes14(
ReturndataPointer rdPtr
) internal pure returns (bytes14 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the bytes15 at `rdPtr` in returndata.
function readBytes15(
ReturndataPointer rdPtr
) internal pure returns (bytes15 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the bytes16 at `rdPtr` in returndata.
function readBytes16(
ReturndataPointer rdPtr
) internal pure returns (bytes16 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the bytes17 at `rdPtr` in returndata.
function readBytes17(
ReturndataPointer rdPtr
) internal pure returns (bytes17 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the bytes18 at `rdPtr` in returndata.
function readBytes18(
ReturndataPointer rdPtr
) internal pure returns (bytes18 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the bytes19 at `rdPtr` in returndata.
function readBytes19(
ReturndataPointer rdPtr
) internal pure returns (bytes19 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the bytes20 at `rdPtr` in returndata.
function readBytes20(
ReturndataPointer rdPtr
) internal pure returns (bytes20 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the bytes21 at `rdPtr` in returndata.
function readBytes21(
ReturndataPointer rdPtr
) internal pure returns (bytes21 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the bytes22 at `rdPtr` in returndata.
function readBytes22(
ReturndataPointer rdPtr
) internal pure returns (bytes22 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the bytes23 at `rdPtr` in returndata.
function readBytes23(
ReturndataPointer rdPtr
) internal pure returns (bytes23 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the bytes24 at `rdPtr` in returndata.
function readBytes24(
ReturndataPointer rdPtr
) internal pure returns (bytes24 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the bytes25 at `rdPtr` in returndata.
function readBytes25(
ReturndataPointer rdPtr
) internal pure returns (bytes25 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the bytes26 at `rdPtr` in returndata.
function readBytes26(
ReturndataPointer rdPtr
) internal pure returns (bytes26 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the bytes27 at `rdPtr` in returndata.
function readBytes27(
ReturndataPointer rdPtr
) internal pure returns (bytes27 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the bytes28 at `rdPtr` in returndata.
function readBytes28(
ReturndataPointer rdPtr
) internal pure returns (bytes28 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the bytes29 at `rdPtr` in returndata.
function readBytes29(
ReturndataPointer rdPtr
) internal pure returns (bytes29 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the bytes30 at `rdPtr` in returndata.
function readBytes30(
ReturndataPointer rdPtr
) internal pure returns (bytes30 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the bytes31 at `rdPtr` in returndata.
function readBytes31(
ReturndataPointer rdPtr
) internal pure returns (bytes31 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the bytes32 at `rdPtr` in returndata.
function readBytes32(
ReturndataPointer rdPtr
) internal pure returns (bytes32 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the uint8 at `rdPtr` in returndata.
function readUint8(
ReturndataPointer rdPtr
) internal pure returns (uint8 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the uint16 at `rdPtr` in returndata.
function readUint16(
ReturndataPointer rdPtr
) internal pure returns (uint16 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the uint24 at `rdPtr` in returndata.
function readUint24(
ReturndataPointer rdPtr
) internal pure returns (uint24 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the uint32 at `rdPtr` in returndata.
function readUint32(
ReturndataPointer rdPtr
) internal pure returns (uint32 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the uint40 at `rdPtr` in returndata.
function readUint40(
ReturndataPointer rdPtr
) internal pure returns (uint40 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the uint48 at `rdPtr` in returndata.
function readUint48(
ReturndataPointer rdPtr
) internal pure returns (uint48 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the uint56 at `rdPtr` in returndata.
function readUint56(
ReturndataPointer rdPtr
) internal pure returns (uint56 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the uint64 at `rdPtr` in returndata.
function readUint64(
ReturndataPointer rdPtr
) internal pure returns (uint64 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the uint72 at `rdPtr` in returndata.
function readUint72(
ReturndataPointer rdPtr
) internal pure returns (uint72 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the uint80 at `rdPtr` in returndata.
function readUint80(
ReturndataPointer rdPtr
) internal pure returns (uint80 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the uint88 at `rdPtr` in returndata.
function readUint88(
ReturndataPointer rdPtr
) internal pure returns (uint88 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the uint96 at `rdPtr` in returndata.
function readUint96(
ReturndataPointer rdPtr
) internal pure returns (uint96 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the uint104 at `rdPtr` in returndata.
function readUint104(
ReturndataPointer rdPtr
) internal pure returns (uint104 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the uint112 at `rdPtr` in returndata.
function readUint112(
ReturndataPointer rdPtr
) internal pure returns (uint112 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the uint120 at `rdPtr` in returndata.
function readUint120(
ReturndataPointer rdPtr
) internal pure returns (uint120 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the uint128 at `rdPtr` in returndata.
function readUint128(
ReturndataPointer rdPtr
) internal pure returns (uint128 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the uint136 at `rdPtr` in returndata.
function readUint136(
ReturndataPointer rdPtr
) internal pure returns (uint136 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the uint144 at `rdPtr` in returndata.
function readUint144(
ReturndataPointer rdPtr
) internal pure returns (uint144 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the uint152 at `rdPtr` in returndata.
function readUint152(
ReturndataPointer rdPtr
) internal pure returns (uint152 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the uint160 at `rdPtr` in returndata.
function readUint160(
ReturndataPointer rdPtr
) internal pure returns (uint160 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the uint168 at `rdPtr` in returndata.
function readUint168(
ReturndataPointer rdPtr
) internal pure returns (uint168 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the uint176 at `rdPtr` in returndata.
function readUint176(
ReturndataPointer rdPtr
) internal pure returns (uint176 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the uint184 at `rdPtr` in returndata.
function readUint184(
ReturndataPointer rdPtr
) internal pure returns (uint184 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the uint192 at `rdPtr` in returndata.
function readUint192(
ReturndataPointer rdPtr
) internal pure returns (uint192 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the uint200 at `rdPtr` in returndata.
function readUint200(
ReturndataPointer rdPtr
) internal pure returns (uint200 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the uint208 at `rdPtr` in returndata.
function readUint208(
ReturndataPointer rdPtr
) internal pure returns (uint208 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the uint216 at `rdPtr` in returndata.
function readUint216(
ReturndataPointer rdPtr
) internal pure returns (uint216 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the uint224 at `rdPtr` in returndata.
function readUint224(
ReturndataPointer rdPtr
) internal pure returns (uint224 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the uint232 at `rdPtr` in returndata.
function readUint232(
ReturndataPointer rdPtr
) internal pure returns (uint232 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the uint240 at `rdPtr` in returndata.
function readUint240(
ReturndataPointer rdPtr
) internal pure returns (uint240 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the uint248 at `rdPtr` in returndata.
function readUint248(
ReturndataPointer rdPtr
) internal pure returns (uint248 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the uint256 at `rdPtr` in returndata.
function readUint256(
ReturndataPointer rdPtr
) internal pure returns (uint256 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the int8 at `rdPtr` in returndata.
function readInt8(
ReturndataPointer rdPtr
) internal pure returns (int8 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the int16 at `rdPtr` in returndata.
function readInt16(
ReturndataPointer rdPtr
) internal pure returns (int16 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the int24 at `rdPtr` in returndata.
function readInt24(
ReturndataPointer rdPtr
) internal pure returns (int24 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the int32 at `rdPtr` in returndata.
function readInt32(
ReturndataPointer rdPtr
) internal pure returns (int32 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the int40 at `rdPtr` in returndata.
function readInt40(
ReturndataPointer rdPtr
) internal pure returns (int40 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the int48 at `rdPtr` in returndata.
function readInt48(
ReturndataPointer rdPtr
) internal pure returns (int48 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the int56 at `rdPtr` in returndata.
function readInt56(
ReturndataPointer rdPtr
) internal pure returns (int56 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the int64 at `rdPtr` in returndata.
function readInt64(
ReturndataPointer rdPtr
) internal pure returns (int64 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the int72 at `rdPtr` in returndata.
function readInt72(
ReturndataPointer rdPtr
) internal pure returns (int72 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the int80 at `rdPtr` in returndata.
function readInt80(
ReturndataPointer rdPtr
) internal pure returns (int80 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the int88 at `rdPtr` in returndata.
function readInt88(
ReturndataPointer rdPtr
) internal pure returns (int88 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the int96 at `rdPtr` in returndata.
function readInt96(
ReturndataPointer rdPtr
) internal pure returns (int96 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the int104 at `rdPtr` in returndata.
function readInt104(
ReturndataPointer rdPtr
) internal pure returns (int104 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the int112 at `rdPtr` in returndata.
function readInt112(
ReturndataPointer rdPtr
) internal pure returns (int112 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the int120 at `rdPtr` in returndata.
function readInt120(
ReturndataPointer rdPtr
) internal pure returns (int120 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the int128 at `rdPtr` in returndata.
function readInt128(
ReturndataPointer rdPtr
) internal pure returns (int128 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the int136 at `rdPtr` in returndata.
function readInt136(
ReturndataPointer rdPtr
) internal pure returns (int136 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the int144 at `rdPtr` in returndata.
function readInt144(
ReturndataPointer rdPtr
) internal pure returns (int144 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the int152 at `rdPtr` in returndata.
function readInt152(
ReturndataPointer rdPtr
) internal pure returns (int152 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the int160 at `rdPtr` in returndata.
function readInt160(
ReturndataPointer rdPtr
) internal pure returns (int160 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the int168 at `rdPtr` in returndata.
function readInt168(
ReturndataPointer rdPtr
) internal pure returns (int168 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the int176 at `rdPtr` in returndata.
function readInt176(
ReturndataPointer rdPtr
) internal pure returns (int176 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the int184 at `rdPtr` in returndata.
function readInt184(
ReturndataPointer rdPtr
) internal pure returns (int184 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the int192 at `rdPtr` in returndata.
function readInt192(
ReturndataPointer rdPtr
) internal pure returns (int192 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the int200 at `rdPtr` in returndata.
function readInt200(
ReturndataPointer rdPtr
) internal pure returns (int200 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the int208 at `rdPtr` in returndata.
function readInt208(
ReturndataPointer rdPtr
) internal pure returns (int208 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the int216 at `rdPtr` in returndata.
function readInt216(
ReturndataPointer rdPtr
) internal pure returns (int216 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the int224 at `rdPtr` in returndata.
function readInt224(
ReturndataPointer rdPtr
) internal pure returns (int224 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the int232 at `rdPtr` in returndata.
function readInt232(
ReturndataPointer rdPtr
) internal pure returns (int232 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the int240 at `rdPtr` in returndata.
function readInt240(
ReturndataPointer rdPtr
) internal pure returns (int240 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the int248 at `rdPtr` in returndata.
function readInt248(
ReturndataPointer rdPtr
) internal pure returns (int248 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
/// @dev Reads the int256 at `rdPtr` in returndata.
function readInt256(
ReturndataPointer rdPtr
) internal pure returns (int256 value) {
assembly {
returndatacopy(0, rdPtr, _OneWord)
value := mload(0)
}
}
}
library MemoryReaders {
/// @dev Reads the memory pointer at `mPtr` in memory.
function readMemoryPointer(
MemoryPointer mPtr
) internal pure returns (MemoryPointer value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads value at `mPtr` & applies a mask to return only last 4 bytes
function readMaskedUint256(
MemoryPointer mPtr
) internal pure returns (uint256 value) {
value = mPtr.readUint256() & OffsetOrLengthMask;
}
/// @dev Reads the bool at `mPtr` in memory.
function readBool(MemoryPointer mPtr) internal pure returns (bool value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the address at `mPtr` in memory.
function readAddress(
MemoryPointer mPtr
) internal pure returns (address value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the bytes1 at `mPtr` in memory.
function readBytes1(
MemoryPointer mPtr
) internal pure returns (bytes1 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the bytes2 at `mPtr` in memory.
function readBytes2(
MemoryPointer mPtr
) internal pure returns (bytes2 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the bytes3 at `mPtr` in memory.
function readBytes3(
MemoryPointer mPtr
) internal pure returns (bytes3 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the bytes4 at `mPtr` in memory.
function readBytes4(
MemoryPointer mPtr
) internal pure returns (bytes4 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the bytes5 at `mPtr` in memory.
function readBytes5(
MemoryPointer mPtr
) internal pure returns (bytes5 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the bytes6 at `mPtr` in memory.
function readBytes6(
MemoryPointer mPtr
) internal pure returns (bytes6 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the bytes7 at `mPtr` in memory.
function readBytes7(
MemoryPointer mPtr
) internal pure returns (bytes7 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the bytes8 at `mPtr` in memory.
function readBytes8(
MemoryPointer mPtr
) internal pure returns (bytes8 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the bytes9 at `mPtr` in memory.
function readBytes9(
MemoryPointer mPtr
) internal pure returns (bytes9 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the bytes10 at `mPtr` in memory.
function readBytes10(
MemoryPointer mPtr
) internal pure returns (bytes10 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the bytes11 at `mPtr` in memory.
function readBytes11(
MemoryPointer mPtr
) internal pure returns (bytes11 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the bytes12 at `mPtr` in memory.
function readBytes12(
MemoryPointer mPtr
) internal pure returns (bytes12 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the bytes13 at `mPtr` in memory.
function readBytes13(
MemoryPointer mPtr
) internal pure returns (bytes13 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the bytes14 at `mPtr` in memory.
function readBytes14(
MemoryPointer mPtr
) internal pure returns (bytes14 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the bytes15 at `mPtr` in memory.
function readBytes15(
MemoryPointer mPtr
) internal pure returns (bytes15 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the bytes16 at `mPtr` in memory.
function readBytes16(
MemoryPointer mPtr
) internal pure returns (bytes16 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the bytes17 at `mPtr` in memory.
function readBytes17(
MemoryPointer mPtr
) internal pure returns (bytes17 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the bytes18 at `mPtr` in memory.
function readBytes18(
MemoryPointer mPtr
) internal pure returns (bytes18 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the bytes19 at `mPtr` in memory.
function readBytes19(
MemoryPointer mPtr
) internal pure returns (bytes19 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the bytes20 at `mPtr` in memory.
function readBytes20(
MemoryPointer mPtr
) internal pure returns (bytes20 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the bytes21 at `mPtr` in memory.
function readBytes21(
MemoryPointer mPtr
) internal pure returns (bytes21 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the bytes22 at `mPtr` in memory.
function readBytes22(
MemoryPointer mPtr
) internal pure returns (bytes22 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the bytes23 at `mPtr` in memory.
function readBytes23(
MemoryPointer mPtr
) internal pure returns (bytes23 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the bytes24 at `mPtr` in memory.
function readBytes24(
MemoryPointer mPtr
) internal pure returns (bytes24 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the bytes25 at `mPtr` in memory.
function readBytes25(
MemoryPointer mPtr
) internal pure returns (bytes25 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the bytes26 at `mPtr` in memory.
function readBytes26(
MemoryPointer mPtr
) internal pure returns (bytes26 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the bytes27 at `mPtr` in memory.
function readBytes27(
MemoryPointer mPtr
) internal pure returns (bytes27 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the bytes28 at `mPtr` in memory.
function readBytes28(
MemoryPointer mPtr
) internal pure returns (bytes28 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the bytes29 at `mPtr` in memory.
function readBytes29(
MemoryPointer mPtr
) internal pure returns (bytes29 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the bytes30 at `mPtr` in memory.
function readBytes30(
MemoryPointer mPtr
) internal pure returns (bytes30 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the bytes31 at `mPtr` in memory.
function readBytes31(
MemoryPointer mPtr
) internal pure returns (bytes31 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the bytes32 at `mPtr` in memory.
function readBytes32(
MemoryPointer mPtr
) internal pure returns (bytes32 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the uint8 at `mPtr` in memory.
function readUint8(MemoryPointer mPtr) internal pure returns (uint8 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the uint16 at `mPtr` in memory.
function readUint16(
MemoryPointer mPtr
) internal pure returns (uint16 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the uint24 at `mPtr` in memory.
function readUint24(
MemoryPointer mPtr
) internal pure returns (uint24 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the uint32 at `mPtr` in memory.
function readUint32(
MemoryPointer mPtr
) internal pure returns (uint32 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the uint40 at `mPtr` in memory.
function readUint40(
MemoryPointer mPtr
) internal pure returns (uint40 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the uint48 at `mPtr` in memory.
function readUint48(
MemoryPointer mPtr
) internal pure returns (uint48 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the uint56 at `mPtr` in memory.
function readUint56(
MemoryPointer mPtr
) internal pure returns (uint56 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the uint64 at `mPtr` in memory.
function readUint64(
MemoryPointer mPtr
) internal pure returns (uint64 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the uint72 at `mPtr` in memory.
function readUint72(
MemoryPointer mPtr
) internal pure returns (uint72 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the uint80 at `mPtr` in memory.
function readUint80(
MemoryPointer mPtr
) internal pure returns (uint80 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the uint88 at `mPtr` in memory.
function readUint88(
MemoryPointer mPtr
) internal pure returns (uint88 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the uint96 at `mPtr` in memory.
function readUint96(
MemoryPointer mPtr
) internal pure returns (uint96 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the uint104 at `mPtr` in memory.
function readUint104(
MemoryPointer mPtr
) internal pure returns (uint104 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the uint112 at `mPtr` in memory.
function readUint112(
MemoryPointer mPtr
) internal pure returns (uint112 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the uint120 at `mPtr` in memory.
function readUint120(
MemoryPointer mPtr
) internal pure returns (uint120 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the uint128 at `mPtr` in memory.
function readUint128(
MemoryPointer mPtr
) internal pure returns (uint128 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the uint136 at `mPtr` in memory.
function readUint136(
MemoryPointer mPtr
) internal pure returns (uint136 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the uint144 at `mPtr` in memory.
function readUint144(
MemoryPointer mPtr
) internal pure returns (uint144 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the uint152 at `mPtr` in memory.
function readUint152(
MemoryPointer mPtr
) internal pure returns (uint152 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the uint160 at `mPtr` in memory.
function readUint160(
MemoryPointer mPtr
) internal pure returns (uint160 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the uint168 at `mPtr` in memory.
function readUint168(
MemoryPointer mPtr
) internal pure returns (uint168 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the uint176 at `mPtr` in memory.
function readUint176(
MemoryPointer mPtr
) internal pure returns (uint176 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the uint184 at `mPtr` in memory.
function readUint184(
MemoryPointer mPtr
) internal pure returns (uint184 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the uint192 at `mPtr` in memory.
function readUint192(
MemoryPointer mPtr
) internal pure returns (uint192 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the uint200 at `mPtr` in memory.
function readUint200(
MemoryPointer mPtr
) internal pure returns (uint200 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the uint208 at `mPtr` in memory.
function readUint208(
MemoryPointer mPtr
) internal pure returns (uint208 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the uint216 at `mPtr` in memory.
function readUint216(
MemoryPointer mPtr
) internal pure returns (uint216 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the uint224 at `mPtr` in memory.
function readUint224(
MemoryPointer mPtr
) internal pure returns (uint224 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the uint232 at `mPtr` in memory.
function readUint232(
MemoryPointer mPtr
) internal pure returns (uint232 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the uint240 at `mPtr` in memory.
function readUint240(
MemoryPointer mPtr
) internal pure returns (uint240 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the uint248 at `mPtr` in memory.
function readUint248(
MemoryPointer mPtr
) internal pure returns (uint248 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the uint256 at `mPtr` in memory.
function readUint256(
MemoryPointer mPtr
) internal pure returns (uint256 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the int8 at `mPtr` in memory.
function readInt8(MemoryPointer mPtr) internal pure returns (int8 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the int16 at `mPtr` in memory.
function readInt16(MemoryPointer mPtr) internal pure returns (int16 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the int24 at `mPtr` in memory.
function readInt24(MemoryPointer mPtr) internal pure returns (int24 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the int32 at `mPtr` in memory.
function readInt32(MemoryPointer mPtr) internal pure returns (int32 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the int40 at `mPtr` in memory.
function readInt40(MemoryPointer mPtr) internal pure returns (int40 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the int48 at `mPtr` in memory.
function readInt48(MemoryPointer mPtr) internal pure returns (int48 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the int56 at `mPtr` in memory.
function readInt56(MemoryPointer mPtr) internal pure returns (int56 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the int64 at `mPtr` in memory.
function readInt64(MemoryPointer mPtr) internal pure returns (int64 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the int72 at `mPtr` in memory.
function readInt72(MemoryPointer mPtr) internal pure returns (int72 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the int80 at `mPtr` in memory.
function readInt80(MemoryPointer mPtr) internal pure returns (int80 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the int88 at `mPtr` in memory.
function readInt88(MemoryPointer mPtr) internal pure returns (int88 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the int96 at `mPtr` in memory.
function readInt96(MemoryPointer mPtr) internal pure returns (int96 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the int104 at `mPtr` in memory.
function readInt104(
MemoryPointer mPtr
) internal pure returns (int104 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the int112 at `mPtr` in memory.
function readInt112(
MemoryPointer mPtr
) internal pure returns (int112 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the int120 at `mPtr` in memory.
function readInt120(
MemoryPointer mPtr
) internal pure returns (int120 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the int128 at `mPtr` in memory.
function readInt128(
MemoryPointer mPtr
) internal pure returns (int128 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the int136 at `mPtr` in memory.
function readInt136(
MemoryPointer mPtr
) internal pure returns (int136 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the int144 at `mPtr` in memory.
function readInt144(
MemoryPointer mPtr
) internal pure returns (int144 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the int152 at `mPtr` in memory.
function readInt152(
MemoryPointer mPtr
) internal pure returns (int152 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the int160 at `mPtr` in memory.
function readInt160(
MemoryPointer mPtr
) internal pure returns (int160 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the int168 at `mPtr` in memory.
function readInt168(
MemoryPointer mPtr
) internal pure returns (int168 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the int176 at `mPtr` in memory.
function readInt176(
MemoryPointer mPtr
) internal pure returns (int176 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the int184 at `mPtr` in memory.
function readInt184(
MemoryPointer mPtr
) internal pure returns (int184 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the int192 at `mPtr` in memory.
function readInt192(
MemoryPointer mPtr
) internal pure returns (int192 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the int200 at `mPtr` in memory.
function readInt200(
MemoryPointer mPtr
) internal pure returns (int200 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the int208 at `mPtr` in memory.
function readInt208(
MemoryPointer mPtr
) internal pure returns (int208 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the int216 at `mPtr` in memory.
function readInt216(
MemoryPointer mPtr
) internal pure returns (int216 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the int224 at `mPtr` in memory.
function readInt224(
MemoryPointer mPtr
) internal pure returns (int224 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the int232 at `mPtr` in memory.
function readInt232(
MemoryPointer mPtr
) internal pure returns (int232 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the int240 at `mPtr` in memory.
function readInt240(
MemoryPointer mPtr
) internal pure returns (int240 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the int248 at `mPtr` in memory.
function readInt248(
MemoryPointer mPtr
) internal pure returns (int248 value) {
assembly {
value := mload(mPtr)
}
}
/// @dev Reads the int256 at `mPtr` in memory.
function readInt256(
MemoryPointer mPtr
) internal pure returns (int256 value) {
assembly {
value := mload(mPtr)
}
}
}
library MemoryWriters {
/// @dev Writes `valuePtr` to memory at `mPtr`.
function write(MemoryPointer mPtr, MemoryPointer valuePtr) internal pure {
assembly {
mstore(mPtr, valuePtr)
}
}
/// @dev Writes a boolean `value` to `mPtr` in memory.
function write(MemoryPointer mPtr, bool value) internal pure {
assembly {
mstore(mPtr, value)
}
}
/// @dev Writes an address `value` to `mPtr` in memory.
function write(MemoryPointer mPtr, address value) internal pure {
assembly {
mstore(mPtr, value)
}
}
/// @dev Writes a bytes32 `value` to `mPtr` in memory.
/// Separate name to disambiguate literal write parameters.
function writeBytes32(MemoryPointer mPtr, bytes32 value) internal pure {
assembly {
mstore(mPtr, value)
}
}
/// @dev Writes a uint256 `value` to `mPtr` in memory.
function write(MemoryPointer mPtr, uint256 value) internal pure {
assembly {
mstore(mPtr, value)
}
}
/// @dev Writes an int256 `value` to `mPtr` in memory.
/// Separate name to disambiguate literal write parameters.
function writeInt(MemoryPointer mPtr, int256 value) internal pure {
assembly {
mstore(mPtr, value)
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
import {
AdvancedOrder,
BasicOrderParameters,
CriteriaResolver,
Execution,
Fulfillment,
FulfillmentComponent,
Order,
OrderComponents
} from "../lib/ConsiderationStructs.sol";
/**
* @title SeaportInterface
* @author 0age
* @custom:version 1.5
* @notice Seaport is a generalized native token/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 SeaportInterface contains all external function interfaces for Seaport.
*/
interface SeaportInterface {
/**
* @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
* Seaport.
*
* @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
* Seaport.
* @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. Note that unspent offer item amounts or
* native tokens will not be reflected as part of
* this array.
*/
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. Note that unspent offer item amounts or
* native tokens will not be reflected as part of
* this array.
*/
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 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). Any unspent
* offer item amounts or native tokens will be transferred to the
* caller.
*
* @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. Note that unspent offer item amounts or
* native tokens will not be reflected as part of this
* array.
*/
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. Any unspent offer item
* amounts will be transferred to the designated recipient (with the
* null address signifying to use the caller) and any unspent native
* tokens will be returned to the caller.
*
* @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.
* @param recipient The intended recipient for all unspent offer
* item amounts, or the caller if the null address
* is supplied.
*
* @return executions An array of elements indicating the sequence of
* transfers performed as part of matching the given
* orders. Note that unspent offer item amounts or native
* tokens will not be reflected as part of this array.
*/
function matchAdvancedOrders(
AdvancedOrder[] calldata orders,
CriteriaResolver[] calldata criteriaResolvers,
Fulfillment[] calldata fulfillments,
address recipient
) 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 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. Note that this function costs less gas than
* `fulfillBasicOrder` due to the zero bytes in the function
* selector (0x00000000) which also results in earlier function
* dispatch.
*
* @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_efficient_6GL6yc(
BasicOrderParameters calldata parameters
) external payable returns (bool fulfilled);
/**
* @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
);
function getContractOffererNonce(
address contractOfferer
) external view returns (uint256 nonce);
/**
* @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.13;
import {ItemType, Side} from "../../seaport-1.5/lib/ConsiderationEnums.sol";
import {Execution, FulfillmentComponent, ReceivedItem, SpentItem} from "../../seaport-1.5/lib/ConsiderationStructs.sol";
import {ConsiderationItemIndicesAndValidity, OrderToExecute} from "./ReferenceConsiderationStructs.sol";
import {FulfillmentApplicationErrors} from "../../seaport-1.5/interfaces/FulfillmentApplicationErrors.sol";
import {TokenTransferrerErrors} from "../../seaport-1.5/interfaces/TokenTransferrerErrors.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 ReferenceFulfillmentApplier is
FulfillmentApplicationErrors,
TokenTransferrerErrors
{
/**
* @dev Internal pure function to match offer items to consideration items
* on a group of orders via a supplied fulfillment.
*
* @param ordersToExecute 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.
* @param fulfillmentIndex The index of the fulfillment component
* that does not match the initial offer
* item.
*
* @return execution The transfer performed as a result of the fulfillment.
*/
function _applyFulfillment(
OrderToExecute[] memory ordersToExecute,
FulfillmentComponent[] memory offerComponents,
FulfillmentComponent[] memory considerationComponents,
uint256 fulfillmentIndex
) 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();
}
// Recipient does not need to be specified because it will always be set
// to that of the consideration.
// Validate and aggregate consideration items and store the result as a
// ReceivedItem.
ReceivedItem memory considerationItem = (
_aggregateValidFulfillmentConsiderationItems(
ordersToExecute,
considerationComponents
)
);
// Skip aggregating offer items if no consideration items are available.
if (considerationItem.amount == 0) {
// Set the offerer and recipient to null address and item type to a
// non-native item type if execution amount is zero. This will cause
// the execution item to be skipped.
execution.offerer = address(0);
execution.item.recipient = payable(0);
execution.item.itemType = ItemType.ERC20;
return execution;
}
// Validate & aggregate offer items and store result as an Execution.
(
execution
/**
* ItemType itemType,
* address token,
* uint256 identifier,
* address offerer,
* bytes32 conduitKey,
* uint256 offerAmount
*/
) = _aggregateValidFulfillmentOfferItems(
ordersToExecute,
offerComponents,
address(0) // unused
);
// 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(
fulfillmentIndex
);
}
// 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]
);
// Add excess consideration item amount to original array of orders.
ordersToExecute[targetComponent.orderIndex]
.receivedItems[targetComponent.itemIndex]
.amount = 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]);
// Add excess offer item amount to the original array of orders.
ordersToExecute[targetComponent.orderIndex]
.spentItems[targetComponent.itemIndex]
.amount = execution.item.amount - considerationItem.amount;
}
// Reuse execution struct with consideration amount and recipient.
execution.item.amount = considerationItem.amount;
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 ordersToExecute 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 (and direct
* approvals set on Consideration)
* @param recipient The intended recipient for all received
* items.
*
* @return _execution The transfer performed as a result of the fulfillment.
*/
function _aggregateAvailable(
OrderToExecute[] memory ordersToExecute,
Side side,
FulfillmentComponent[] memory fulfillmentComponents,
bytes32 fulfillerConduitKey,
address recipient
) internal view returns (Execution memory _execution) {
// Retrieve fulfillment components array length and place on stack.
uint256 totalFulfillmentComponents = fulfillmentComponents.length;
// Ensure at least one fulfillment component has been supplied.
if (totalFulfillmentComponents == 0) {
revert MissingFulfillmentComponentOnAggregation(side);
}
Execution memory execution;
// If the fulfillment components are offer components...
if (side == Side.OFFER) {
// Return execution for aggregated items provided by offerer.
execution = _aggregateValidFulfillmentOfferItems(
ordersToExecute,
fulfillmentComponents,
recipient
);
} else {
// Otherwise, fulfillment components are consideration
// components. Return execution for aggregated items provided by
// the fulfiller.
execution = _aggregateConsiderationItems(
ordersToExecute,
fulfillmentComponents,
fulfillerConduitKey
);
}
if (execution.item.amount == 0) {
return
Execution(
ReceivedItem(
ItemType.ERC20,
address(0),
0,
0,
payable(address(0))
),
address(0),
bytes32(0)
);
}
return execution;
}
/**
* @dev Internal pure function to check the indicated offer item
* matches original item.
*
* @param orderToExecute The order to compare.
* @param offer The offer to compare.
* @param execution The aggregated offer item.
*
* @return invalidFulfillment A boolean indicating whether the
* fulfillment is invalid.
*/
function _checkMatchingOffer(
OrderToExecute memory orderToExecute,
SpentItem memory offer,
Execution memory execution
) internal pure returns (bool invalidFulfillment) {
return
execution.item.identifier != offer.identifier ||
execution.offerer != orderToExecute.offerer ||
execution.conduitKey != orderToExecute.conduitKey ||
execution.item.itemType != offer.itemType ||
execution.item.token != offer.token;
}
/**
* @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 ordersToExecute 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 recipient The recipient for the aggregated offer items.
*
* @return execution The aggregated offer items.
*/
function _aggregateValidFulfillmentOfferItems(
OrderToExecute[] memory ordersToExecute,
FulfillmentComponent[] memory offerComponents,
address recipient
) internal pure returns (Execution memory execution) {
bool foundItem = false;
// Get the order index and item index of the offer component.
uint256 orderIndex;
uint256 itemIndex;
OrderToExecute memory orderToExecute;
// Declare variables indicating whether the aggregation is invalid.
// Ensure that the order index is not out of range.
bool invalidFulfillment;
// Ensure that no available items have missing amounts.
bool missingItemAmount;
// Loop through the offer components, checking for validity.
for (uint256 i = 0; i < offerComponents.length; ++i) {
// Get the order index and item index of the offer component.
orderIndex = offerComponents[i].orderIndex;
itemIndex = offerComponents[i].itemIndex;
// Ensure that the order index is not out of range.
invalidFulfillment = orderIndex >= ordersToExecute.length;
// Break if invalid.
if (invalidFulfillment) {
break;
}
// Get the order based on offer components order index.
orderToExecute = ordersToExecute[orderIndex];
if (
orderToExecute.numerator != 0 &&
itemIndex < orderToExecute.spentItems.length
) {
// Get the spent item based on the offer components item index.
SpentItem memory offer = orderToExecute.spentItems[itemIndex];
if (!foundItem) {
foundItem = true;
// Create the Execution.
execution = Execution(
ReceivedItem(
offer.itemType,
offer.token,
offer.identifier,
offer.amount,
payable(recipient)
),
orderToExecute.offerer,
orderToExecute.conduitKey
);
// If component index > 0, swap component pointer with
// pointer to first component so that any remainder after
// fulfillment can be added back to the first item.
if (i != 0) {
FulfillmentComponent
memory firstComponent = offerComponents[0];
offerComponents[0] = offerComponents[i];
offerComponents[i] = firstComponent;
}
} else {
// Update the Received Item amount.
execution.item.amount =
execution.item.amount +
offer.amount;
// Ensure indicated offer item matches original item.
invalidFulfillment = _checkMatchingOffer(
orderToExecute,
offer,
execution
);
}
// Ensure the item has a nonzero amount.
missingItemAmount = offer.amount == 0;
invalidFulfillment = invalidFulfillment || missingItemAmount;
// Zero out amount on original offerItem to indicate it's spent.
offer.amount = 0;
// Break if invalid.
if (invalidFulfillment) {
break;
}
}
}
// Revert if an order/item was out of range or was not aggregatable.
if (invalidFulfillment) {
if (missingItemAmount) {
revert MissingItemAmount();
}
revert InvalidFulfillmentComponentData();
}
}
/**
* @dev Internal view function to aggregate consideration items from a group
* of orders into a single execution via a supplied components array.
* Consideration items that are not available to aggregate will not be
* included in the aggregated execution.
*
* @param ordersToExecute The orders to aggregate.
* @param considerationComponents An array designating consideration
* 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 (and direct
* approvals set on Consideration)
*
* @return execution The transfer performed as a result of the fulfillment.
*/
function _aggregateConsiderationItems(
OrderToExecute[] memory ordersToExecute,
FulfillmentComponent[] memory considerationComponents,
bytes32 fulfillerConduitKey
) internal view returns (Execution memory execution) {
// Validate and aggregate consideration items on available orders and
// store result as a ReceivedItem.
ReceivedItem memory receiveConsiderationItem = (
_aggregateValidFulfillmentConsiderationItems(
ordersToExecute,
considerationComponents
)
);
// Return execution for aggregated items provided by the fulfiller.
execution = Execution(
receiveConsiderationItem,
msg.sender,
fulfillerConduitKey
);
}
/**
* @dev Internal pure function to check the indicated consideration item
* matches original item.
*
* @param consideration The consideration to compare.
* @param receivedItem The aggregated received item.
*
* @return invalidFulfillment A boolean indicating whether the fulfillment
* is invalid.
*/
function _checkMatchingConsideration(
ReceivedItem memory consideration,
ReceivedItem memory receivedItem
) internal pure returns (bool invalidFulfillment) {
return
receivedItem.recipient != consideration.recipient ||
receivedItem.itemType != consideration.itemType ||
receivedItem.token != consideration.token ||
receivedItem.identifier != consideration.identifier;
}
/**
* @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 ordersToExecute 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.
*
* @return receivedItem The aggregated consideration items.
*/
function _aggregateValidFulfillmentConsiderationItems(
OrderToExecute[] memory ordersToExecute,
FulfillmentComponent[] memory considerationComponents
) internal pure returns (ReceivedItem memory receivedItem) {
bool foundItem = false;
// Declare struct in memory to avoid declaring multiple local variables.
ConsiderationItemIndicesAndValidity memory potentialCandidate;
ReceivedItem memory consideration;
OrderToExecute memory orderToExecute;
// Loop through the consideration components and validate
// their fulfillment.
for (uint256 i = 0; i < considerationComponents.length; ++i) {
// Get the order index and item index of the consideration
// component.
potentialCandidate.orderIndex = considerationComponents[i]
.orderIndex;
potentialCandidate.itemIndex = considerationComponents[i].itemIndex;
/// Ensure that the order index is not out of range.
potentialCandidate.invalidFulfillment =
potentialCandidate.orderIndex >= ordersToExecute.length;
// Break if invalid.
if (potentialCandidate.invalidFulfillment) {
break;
}
// Get order based on consideration components order index.
orderToExecute = ordersToExecute[potentialCandidate.orderIndex];
// Confirm that the order is being fulfilled.
if (
orderToExecute.numerator != 0 &&
potentialCandidate.itemIndex <
orderToExecute.receivedItems.length
) {
// Retrieve relevant item using item index.
consideration = orderToExecute.receivedItems[
potentialCandidate.itemIndex
];
if (!foundItem) {
foundItem = true;
// Create the received item.
receivedItem = ReceivedItem(
consideration.itemType,
consideration.token,
consideration.identifier,
consideration.amount,
consideration.recipient
);
// If component index > 0, swap component pointer with
// pointer to first component so that any remainder after
// fulfillment can be added back to the first item.
if (i != 0) {
FulfillmentComponent
memory firstComponent = considerationComponents[0];
considerationComponents[0] = considerationComponents[i];
considerationComponents[i] = firstComponent;
}
} else {
// Update Received Item amount.
receivedItem.amount =
receivedItem.amount +
consideration.amount;
// Ensure the indicated consideration item matches
// original item.
potentialCandidate
.invalidFulfillment = _checkMatchingConsideration(
consideration,
receivedItem
);
}
// Ensure the item has a nonzero amount.
potentialCandidate.missingItemAmount =
consideration.amount == 0;
potentialCandidate.invalidFulfillment =
potentialCandidate.invalidFulfillment ||
potentialCandidate.missingItemAmount;
// Zero out amount on original consideration item to
// indicate it is spent.
consideration.amount = 0;
// Break if invalid.
if (potentialCandidate.invalidFulfillment) {
break;
}
}
}
// Revert if an order/item was out of range or was not aggregatable.
if (potentialCandidate.invalidFulfillment) {
if (potentialCandidate.missingItemAmount) {
revert MissingItemAmount();
}
revert InvalidFulfillmentComponentData();
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
import {ItemType, OrderType} from "../../seaport-1.5/lib/ConsiderationEnums.sol";
import {AdvancedOrder, ConsiderationItem, CriteriaResolver, OfferItem, Order, OrderParameters, ReceivedItem, SpentItem} from "../../seaport-1.5/lib/ConsiderationStructs.sol";
import {AccumulatorStruct, FractionData, OrderToExecute} from "./ReferenceConsiderationStructs.sol";
import {ReferenceBasicOrderFulfiller} from "./ReferenceBasicOrderFulfiller.sol";
import {ReferenceCriteriaResolution} from "./ReferenceCriteriaResolution.sol";
import {ReferenceAmountDeriver} from "./ReferenceAmountDeriver.sol";
/**
* @title OrderFulfiller
* @author 0age
* @notice OrderFulfiller contains logic related to order fulfillment.
*/
contract ReferenceOrderFulfiller is
ReferenceBasicOrderFulfiller,
ReferenceCriteriaResolution,
ReferenceAmountDeriver
{
/**
* @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
) ReferenceBasicOrderFulfiller(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 (and 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) {
// Validate order, update status, and determine fraction to fill.
(
bytes32 orderHash,
uint256 fillNumerator,
uint256 fillDenominator
) = _validateOrderAndUpdateStatus(advancedOrder, true);
// Apply criteria resolvers using generated orders and details arrays.
_applyCriteriaResolversAdvanced(advancedOrder, criteriaResolvers);
// Retrieve the order parameters after applying criteria resolvers.
OrderParameters memory orderParameters = advancedOrder.parameters;
// Perform each item transfer with the appropriate fractional amount.
OrderToExecute memory orderToExecute = _applyFractionsAndTransferEach(
orderParameters,
fillNumerator,
fillDenominator,
fulfillerConduitKey,
recipient
);
// Declare bytes32 array with this order's hash
bytes32[] memory priorOrderHashes = new bytes32[](1);
priorOrderHashes[0] = orderHash;
// Ensure restricted orders have a valid submitter or pass a zone check.
_assertRestrictedAdvancedOrderValidity(
advancedOrder,
orderToExecute,
priorOrderHashes,
orderHash,
orderParameters.zoneHash,
orderParameters.orderType,
orderParameters.offerer,
orderParameters.zone
);
// Emit an event signifying that the order has been fulfilled.
emit OrderFulfilled(
orderHash,
orderParameters.offerer,
orderParameters.zone,
recipient,
orderToExecute.spentItems,
orderToExecute.receivedItems
);
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 (and direct approvals set on
* Consideration).
* @param recipient The intended recipient for all received items.
* @return orderToExecute Returns the order of items that are being
* transferred. This will be used for the
* OrderFulfilled Event.
*/
function _applyFractionsAndTransferEach(
OrderParameters memory orderParameters,
uint256 numerator,
uint256 denominator,
bytes32 fulfillerConduitKey,
address recipient
) internal returns (OrderToExecute memory orderToExecute) {
// Derive order duration, time elapsed, and time remaining.
// Store in memory to avoid stack too deep issues.
FractionData memory fractionData = FractionData(
numerator,
denominator,
fulfillerConduitKey,
orderParameters.startTime,
orderParameters.endTime
);
// Create the accumulator struct.
AccumulatorStruct memory accumulatorStruct;
// Get the offerer of the order.
address offerer = orderParameters.offerer;
// Get the conduitKey of the order
bytes32 conduitKey = orderParameters.conduitKey;
// Create the array to store the spent items for event.
orderToExecute.spentItems = new SpentItem[](
orderParameters.offer.length
);
// Declare a nested scope to minimize stack depth.
{
// Iterate over each offer on the order.
for (uint256 i = 0; i < orderParameters.offer.length; ++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 except as part of a contract order.
if (
offerItem.itemType == ItemType.NATIVE &&
orderParameters.orderType != OrderType.CONTRACT
) {
revert InvalidNativeOfferItem();
}
// Apply fill fraction to derive offer item amount to transfer.
uint256 amount = _applyFraction(
offerItem.startAmount,
offerItem.endAmount,
fractionData,
false
);
// Create Received Item from Offer Item for transfer.
ReceivedItem memory receivedItem = ReceivedItem(
offerItem.itemType,
offerItem.token,
offerItem.identifierOrCriteria,
amount,
payable(recipient)
);
// Create Spent Item for the OrderFulfilled event.
orderToExecute.spentItems[i] = SpentItem(
receivedItem.itemType,
receivedItem.token,
receivedItem.identifier,
amount
);
// Transfer the item from the offerer to the recipient.
_transfer(receivedItem, offerer, conduitKey, accumulatorStruct);
}
}
// Create the array to store the received items for event.
orderToExecute.receivedItems = new ReceivedItem[](
orderParameters.consideration.length
);
// Declare a nested scope to minimize stack depth.
{
// Iterate over each consideration on the order.
for (uint256 i = 0; i < orderParameters.consideration.length; ++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,
fractionData,
true
);
// Create Received Item from Offer item.
ReceivedItem memory receivedItem = ReceivedItem(
considerationItem.itemType,
considerationItem.token,
considerationItem.identifierOrCriteria,
amount,
considerationItem.recipient
);
// Add ReceivedItem to structs array.
orderToExecute.receivedItems[i] = receivedItem;
if (receivedItem.itemType == ItemType.NATIVE) {
// Ensure that sufficient native tokens are still available.
if (amount > address(this).balance) {
revert InsufficientNativeTokensSupplied();
}
}
// Transfer item from caller to recipient specified by the item.
_transfer(
receivedItem,
msg.sender,
fractionData.fulfillerConduitKey,
accumulatorStruct
);
}
}
// Trigger any remaining accumulated transfers via call to the conduit.
_triggerIfArmed(accumulatorStruct);
// If any native token remains after fulfillments...
if (address(this).balance != 0) {
// return it to the caller.
_transferNativeTokens(payable(msg.sender), address(this).balance);
}
// Return the order to execute.
return orderToExecute;
}
/**
* @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);
// 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;
}
/**
* @dev Internal pure function to convert an advanced order to an order
* to execute with numerator of 1.
*
* @param advancedOrder The advanced order to convert.
*
* @return orderToExecute The new order to execute.
*/
function _convertAdvancedToOrder(
AdvancedOrder memory advancedOrder
) internal pure returns (OrderToExecute memory orderToExecute) {
// Retrieve the advanced orders offers.
OfferItem[] memory offer = advancedOrder.parameters.offer;
// Create an array of spent items equal to the offer length.
SpentItem[] memory spentItems = new SpentItem[](offer.length);
uint256[] memory spentItemOriginalAmounts = new uint256[](offer.length);
// Iterate over each offer item on the order.
for (uint256 i = 0; i < offer.length; ++i) {
// Retrieve the offer item.
OfferItem memory offerItem = offer[i];
// Create spent item for event based on the offer item.
SpentItem memory spentItem = SpentItem(
offerItem.itemType,
offerItem.token,
offerItem.identifierOrCriteria,
offerItem.startAmount
);
// Add to array of spent items.
spentItems[i] = spentItem;
spentItemOriginalAmounts[i] = offerItem.startAmount;
}
// Retrieve the consideration array from the advanced order.
ConsiderationItem[] memory consideration = advancedOrder
.parameters
.consideration;
// Create an array of received items equal to the consideration length.
ReceivedItem[] memory receivedItems = new ReceivedItem[](
consideration.length
);
// Create an array of uint256 values equal in length to the
// consideration length containing the amounts of each item.
uint256[] memory receivedItemOriginalAmounts = new uint256[](
consideration.length
);
// Iterate over each consideration item on the order.
for (uint256 i = 0; i < consideration.length; ++i) {
// Retrieve the consideration item.
ConsiderationItem memory considerationItem = (consideration[i]);
// Create received item for event based on the consideration item.
ReceivedItem memory receivedItem = ReceivedItem(
considerationItem.itemType,
considerationItem.token,
considerationItem.identifierOrCriteria,
considerationItem.startAmount,
considerationItem.recipient
);
// Add to array of received items.
receivedItems[i] = receivedItem;
// Add to array of received item amounts.
receivedItemOriginalAmounts[i] = considerationItem.startAmount;
}
// Create the order to execute from the advanced order data.
orderToExecute = OrderToExecute(
advancedOrder.parameters.offerer,
spentItems,
receivedItems,
advancedOrder.parameters.conduitKey,
advancedOrder.numerator,
spentItemOriginalAmounts,
receivedItemOriginalAmounts
);
// Return the order.
return orderToExecute;
}
/**
* @dev Internal pure function to convert an array of advanced orders to
* an array of orders to execute.
*
* @param advancedOrders The advanced orders to convert.
*
* @return ordersToExecute The new array of orders.
*/
function _convertAdvancedToOrdersToExecute(
AdvancedOrder[] memory advancedOrders
) internal pure returns (OrderToExecute[] memory ordersToExecute) {
// Read the number of orders from memory and place on the stack.
uint256 totalOrders = advancedOrders.length;
// Allocate new empty array for each advanced order in memory.
ordersToExecute = new OrderToExecute[](totalOrders);
// Iterate over the given orders.
for (uint256 i = 0; i < totalOrders; ++i) {
// Convert and update array.
ordersToExecute[i] = _convertAdvancedToOrder(advancedOrders[i]);
}
// Return the array of orders to execute
return ordersToExecute;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
import { ConduitItemType } from "./ConduitEnums.sol";
/**
* @dev A ConduitTransfer is a struct that contains the information needed for a
* conduit to transfer an item from one address to another.
*/
struct ConduitTransfer {
ConduitItemType itemType;
address token;
address from;
address to;
uint256 identifier;
uint256 amount;
}
/**
* @dev A ConduitBatch1155Transfer is a struct that contains the information
* needed for a conduit to transfer a batch of ERC-1155 tokens from one
* address to another.
*/
struct ConduitBatch1155Transfer {
address token;
address from;
address to;
uint256[] ids;
uint256[] amounts;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
import { Side } from "../lib/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.
*
* @param fulfillmentIndex The index of the fulfillment component that
* does not match the initial offer item.
*/
error MismatchedFulfillmentOfferAndConsiderationComponents(
uint256 fulfillmentIndex
);
/**
* @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.13;
/**
* @title TokenTransferrerErrors
*/
interface TokenTransferrerErrors {
/**
* @dev Revert with an error when an ERC721 transfer with amount other than
* one is attempted.
*
* @param amount The amount of the ERC721 tokens to transfer.
*/
error InvalidERC721TransferAmount(uint256 amount);
/**
* @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.13;
import {AmountDerivationErrors} from "../../seaport-1.5/interfaces/AmountDerivationErrors.sol";
import {FractionData} from "./ReferenceConsiderationStructs.sol";
/**
* @title ReferenceAmountDeriver
* @author 0age
* @notice ReferenceAmountDeriver 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 ReferenceAmountDeriver 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.
*
* @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 The current amount.
*/
function _locateCurrentAmount(
uint256 startAmount,
uint256 endAmount,
uint256 startTime,
uint256 endTime,
bool roundUp
) internal view returns (uint256) {
// Only modify end amount if it doesn't already equal start amount.
if (startAmount != endAmount) {
// Leave extra amount to add for rounding at zero (i.e. round down).
uint256 extraCeiling = 0;
// Derive the duration for the order and place it on the stack.
uint256 duration = endTime - startTime;
// Derive time elapsed since the order started & place on stack.
uint256 elapsed = block.timestamp - startTime;
// Derive time remaining until order expires and place on stack.
uint256 remaining = duration - elapsed;
// If rounding up, set rounding factor to one less than denominator.
if (roundUp) {
extraCeiling = duration - 1;
}
// Aggregate new amounts weighted by time with rounding factor.
uint256 totalBeforeDivision = ((startAmount * remaining) +
(endAmount * elapsed) +
extraCeiling);
// Divide totalBeforeDivision by duration to get the new amount.
uint256 newAmount = totalBeforeDivision / duration;
// Return the current amount.
return newAmount;
}
// Return the original amount.
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.
*
* @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 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;
}
// Multiply the numerator by the value and ensure no overflow occurs.
uint256 valueTimesNumerator = value * numerator;
// Divide that value by the denominator to get the new value.
newValue = valueTimesNumerator / denominator;
// Ensure that division gave a final result with no remainder.
bool exact = ((newValue * denominator) / numerator) == value;
if (!exact) {
revert InexactFraction();
}
}
/**
* @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 fractionData A struct containing the data used to apply a
* fraction to an 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,
FractionData memory fractionData,
bool roundUp
) internal view returns (uint256 amount) {
// If start amount equals end amount, apply fraction to end amount.
if (startAmount == endAmount) {
amount = _getFraction(
fractionData.numerator,
fractionData.denominator,
endAmount
);
} else {
// Otherwise, apply fraction to both to interpolated final amount.
amount = _locateCurrentAmount(
_getFraction(
fractionData.numerator,
fractionData.denominator,
startAmount
),
_getFraction(
fractionData.numerator,
fractionData.denominator,
endAmount
),
fractionData.startTime,
fractionData.endTime,
roundUp
);
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
import {ItemType, Side} from "../../seaport-1.5/lib/ConsiderationEnums.sol";
import {AdvancedOrder, ConsiderationItem, CriteriaResolver, OfferItem, OrderParameters, ReceivedItem, SpentItem} from "../../seaport-1.5/lib/ConsiderationStructs.sol";
import {OrderToExecute} from "./ReferenceConsiderationStructs.sol";
import {CriteriaResolutionErrors} from "../../seaport-1.5/interfaces/CriteriaResolutionErrors.sol";
/**
* @title CriteriaResolution
* @author 0age
* @notice CriteriaResolution contains a collection of pure functions related to
* resolving criteria-based items.
*/
contract ReferenceCriteriaResolution is CriteriaResolutionErrors {
/**
* @dev Internal pure function to apply criteria resolvers containing
* specific token identifiers and associated proofs to order items.
*
* @param ordersToExecute 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(
OrderToExecute[] memory ordersToExecute,
CriteriaResolver[] memory criteriaResolvers
) internal pure {
// Retrieve length of criteria resolvers array and place on stack.
uint256 arraySize = criteriaResolvers.length;
// Iterate over each criteria resolver.
for (uint256 i = 0; i < arraySize; ++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 >= ordersToExecute.length) {
revert OrderCriteriaResolverOutOfRange(criteriaResolver.side);
}
// Skip criteria resolution for order if not fulfilled.
if (ordersToExecute[orderIndex].numerator == 0) {
continue;
}
// 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) {
SpentItem[] memory spentItems = ordersToExecute[orderIndex]
.spentItems;
// Ensure that the component index is in range.
if (componentIndex >= spentItems.length) {
revert OfferCriteriaResolverOutOfRange();
}
// Retrieve relevant item using component index.
SpentItem memory offer = (spentItems[componentIndex]);
// Read item type and criteria from memory & place on stack.
itemType = offer.itemType;
identifierOrCriteria = offer.identifier;
// Optimistically update item type to remove criteria usage.
if (itemType == ItemType.ERC721_WITH_CRITERIA) {
offer.itemType = ItemType.ERC721;
} else {
offer.itemType = ItemType.ERC1155;
}
// Optimistically update identifier w/ supplied identifier.
offer.identifier = criteriaResolver.identifier;
} else {
// Otherwise, the resolver refers to a consideration item.
// Retrieve relevant item using order index.
ReceivedItem[] memory receivedItems = ordersToExecute[
orderIndex
].receivedItems;
// Ensure that the component index is in range.
if (componentIndex >= receivedItems.length) {
revert ConsiderationCriteriaResolverOutOfRange();
}
// Retrieve relevant item using component index.
ReceivedItem memory consideration = (
receivedItems[componentIndex]
);
// Read item type and criteria from memory & place on stack.
itemType = consideration.itemType;
identifierOrCriteria = consideration.identifier;
// Optimistically update item type to remove criteria usage.
if (itemType == ItemType.ERC721_WITH_CRITERIA) {
consideration.itemType = ItemType.ERC721;
} else {
consideration.itemType = ItemType.ERC1155;
}
// Optimistically update identifier w/ supplied identifier.
consideration.identifier = (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 criteria item)...
if (identifierOrCriteria != uint256(0)) {
// Verify identifier inclusion in criteria root using proof.
_verifyProof(
criteriaResolver.identifier,
identifierOrCriteria,
criteriaResolver.criteriaProof
);
} else if (criteriaResolver.criteriaProof.length != 0) {
// Revert if a proof is supplied for a collection-wide item.
revert InvalidProof();
}
}
// Retrieve length of orders array and place on stack.
arraySize = ordersToExecute.length;
// Iterate over each order to execute.
for (uint256 i = 0; i < arraySize; ++i) {
// Retrieve the order to execute.
OrderToExecute memory orderToExecute = ordersToExecute[i];
// Read offer length from memory and place on stack.
uint256 totalItems = orderToExecute.spentItems.length;
// Skip criteria resolution for order if not fulfilled.
if (orderToExecute.numerator == 0) {
continue;
}
// 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(orderToExecute.spentItems[j].itemType)
) {
revert UnresolvedOfferCriteria(i, j);
}
}
// Read consideration length from memory and place on stack.
totalItems = (orderToExecute.receivedItems.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(
orderToExecute.receivedItems[j].itemType
)
) {
revert UnresolvedConsiderationCriteria(i, j);
}
}
}
}
/**
* @dev Internal pure function to apply criteria resolvers containing
* specific token identifiers and associated proofs to order items.
*
* @param advancedOrder The order 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 _applyCriteriaResolversAdvanced(
AdvancedOrder memory advancedOrder,
CriteriaResolver[] memory criteriaResolvers
) internal pure {
// Retrieve length of criteria resolvers array and place on stack.
uint256 arraySize = criteriaResolvers.length;
// Retrieve the parameters for the order.
OrderParameters memory orderParameters = (advancedOrder.parameters);
// Iterate over each criteria resolver.
for (uint256 i = 0; i < arraySize; ++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;
if (orderIndex != 0) {
revert OrderCriteriaResolverOutOfRange(criteriaResolver.side);
}
// 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) {
// Ensure that the component index is in range.
if (componentIndex >= orderParameters.offer.length) {
revert OfferCriteriaResolverOutOfRange();
}
// Retrieve relevant item using order and component index.
OfferItem memory offer = (
orderParameters.offer[componentIndex]
);
// Read item type and criteria from memory & place on stack.
itemType = offer.itemType;
identifierOrCriteria = offer.identifierOrCriteria;
// Optimistically update item type to remove criteria usage.
if (itemType == ItemType.ERC721_WITH_CRITERIA) {
offer.itemType = ItemType.ERC721;
} else {
offer.itemType = ItemType.ERC1155;
}
// Optimistically update identifier w/ supplied identifier.
offer.identifierOrCriteria = criteriaResolver.identifier;
} else {
// Otherwise, the resolver refers to a consideration item.
// Ensure that the component index is in range.
if (componentIndex >= orderParameters.consideration.length) {
revert ConsiderationCriteriaResolverOutOfRange();
}
// Retrieve relevant item using order and component index.
ConsiderationItem memory consideration = (
orderParameters.consideration[componentIndex]
);
// Read item type and criteria from memory & place on stack.
itemType = consideration.itemType;
identifierOrCriteria = consideration.identifierOrCriteria;
// Optimistically update item type to remove criteria usage.
if (itemType == ItemType.ERC721_WITH_CRITERIA) {
consideration.itemType = ItemType.ERC721;
} else {
consideration.itemType = ItemType.ERC1155;
}
// Optimistically update identifier w/ supplied identifier.
consideration.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
);
} else if (criteriaResolver.criteriaProof.length != 0) {
// Revert if a proof is supplied for a collection-wide item.
revert InvalidProof();
}
}
// Validate Criteria on order has been resolved
// Read consideration length from memory and place on stack.
uint256 totalItems = (advancedOrder.parameters.consideration.length);
// Iterate over each consideration item on the order.
for (uint256 i = 0; i < totalItems; ++i) {
// Ensure item type no longer indicates criteria usage.
if (
_isItemWithCriteria(
advancedOrder.parameters.consideration[i].itemType
)
) {
revert UnresolvedConsiderationCriteria(0, i);
}
}
// Read offer length from memory and place on stack.
totalItems = advancedOrder.parameters.offer.length;
// Iterate over each offer item on the order.
for (uint256 i = 0; i < totalItems; ++i) {
// Ensure item type no longer indicates criteria usage.
if (
_isItemWithCriteria(advancedOrder.parameters.offer[i].itemType)
) {
revert UnresolvedOfferCriteria(0, i);
}
}
}
/**
* @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 item type 4. ERC1155WithCriteria is item type
// 5.
withCriteria = uint256(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 {
// Hash the supplied leaf to use as the initial proof element.
bytes32 computedHash = keccak256(abi.encodePacked(leaf));
// Iterate over each proof element.
for (uint256 i = 0; i < proof.length; ++i) {
// Retrieve the proof element.
bytes32 proofElement = proof[i];
// Sort and hash proof elements and update the computed hash.
if (computedHash <= proofElement) {
// Hash(current computed hash + current element of proof)
computedHash = keccak256(
abi.encodePacked(computedHash, proofElement)
);
} else {
// Hash(current element of proof + current computed hash)
computedHash = keccak256(
abi.encodePacked(proofElement, computedHash)
);
}
}
// Ensure that the final derived hash matches the expected root.
if (computedHash != bytes32(root)) {
revert InvalidProof();
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
enum ConduitItemType {
NATIVE, // unused
ERC20,
ERC721,
ERC1155
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
import {BasicOrderRouteType, BasicOrderType, ItemType, OrderType} from "../../seaport-1.5/lib/ConsiderationEnums.sol";
import {AdditionalRecipient, BasicOrderParameters, ConsiderationItem, OfferItem, ReceivedItem, SpentItem} from "../../seaport-1.5/lib/ConsiderationStructs.sol";
import {AccumulatorStruct, BasicFulfillmentHashes, FulfillmentItemTypes} from "./ReferenceConsiderationStructs.sol";
import {ReferenceOrderValidator} from "./ReferenceOrderValidator.sol";
/**
* @title BasicOrderFulfiller
* @author 0age
* @notice BasicOrderFulfiller contains functionality for fulfilling "basic"
* orders.
*/
contract ReferenceBasicOrderFulfiller is ReferenceOrderValidator {
// Map BasicOrderType to BasicOrderRouteType
mapping(BasicOrderType => BasicOrderRouteType) internal _OrderToRouteType;
// Map BasicOrderType to OrderType
mapping(BasicOrderType => OrderType) internal _BasicOrderToOrderType;
/**
* @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
) ReferenceOrderValidator(conduitController) {
createMappings();
}
/**
* @dev Creates a mapping of BasicOrderType Enums to BasicOrderRouteType
* Enums and BasicOrderType Enums to OrderType Enums. Note that this
* is wildly inefficient, but makes the logic easier to follow when
* performing the fulfillment.
*/
function createMappings() internal {
// BasicOrderType to BasicOrderRouteType
// ETH TO ERC 721
_OrderToRouteType[
BasicOrderType.ETH_TO_ERC721_FULL_OPEN
] = BasicOrderRouteType.ETH_TO_ERC721;
_OrderToRouteType[
BasicOrderType.ETH_TO_ERC721_PARTIAL_OPEN
] = BasicOrderRouteType.ETH_TO_ERC721;
_OrderToRouteType[
BasicOrderType.ETH_TO_ERC721_FULL_RESTRICTED
] = BasicOrderRouteType.ETH_TO_ERC721;
_OrderToRouteType[
BasicOrderType.ETH_TO_ERC721_PARTIAL_RESTRICTED
] = BasicOrderRouteType.ETH_TO_ERC721;
// ETH TO ERC 1155
_OrderToRouteType[
BasicOrderType.ETH_TO_ERC1155_FULL_OPEN
] = BasicOrderRouteType.ETH_TO_ERC1155;
_OrderToRouteType[
BasicOrderType.ETH_TO_ERC1155_PARTIAL_OPEN
] = BasicOrderRouteType.ETH_TO_ERC1155;
_OrderToRouteType[
BasicOrderType.ETH_TO_ERC1155_FULL_RESTRICTED
] = BasicOrderRouteType.ETH_TO_ERC1155;
_OrderToRouteType[
BasicOrderType.ETH_TO_ERC1155_PARTIAL_RESTRICTED
] = BasicOrderRouteType.ETH_TO_ERC1155;
// ERC 20 TO ERC 721
_OrderToRouteType[
BasicOrderType.ERC20_TO_ERC721_FULL_OPEN
] = BasicOrderRouteType.ERC20_TO_ERC721;
_OrderToRouteType[
BasicOrderType.ERC20_TO_ERC721_PARTIAL_OPEN
] = BasicOrderRouteType.ERC20_TO_ERC721;
_OrderToRouteType[
BasicOrderType.ERC20_TO_ERC721_FULL_RESTRICTED
] = BasicOrderRouteType.ERC20_TO_ERC721;
_OrderToRouteType[
BasicOrderType.ERC20_TO_ERC721_PARTIAL_RESTRICTED
] = BasicOrderRouteType.ERC20_TO_ERC721;
// ERC 20 TO ERC 1155
_OrderToRouteType[
BasicOrderType.ERC20_TO_ERC1155_FULL_OPEN
] = BasicOrderRouteType.ERC20_TO_ERC1155;
_OrderToRouteType[
BasicOrderType.ERC20_TO_ERC1155_PARTIAL_OPEN
] = BasicOrderRouteType.ERC20_TO_ERC1155;
_OrderToRouteType[
BasicOrderType.ERC20_TO_ERC1155_FULL_RESTRICTED
] = BasicOrderRouteType.ERC20_TO_ERC1155;
_OrderToRouteType[
BasicOrderType.ERC20_TO_ERC1155_PARTIAL_RESTRICTED
] = BasicOrderRouteType.ERC20_TO_ERC1155;
// ERC 721 TO ERC 20
_OrderToRouteType[
BasicOrderType.ERC721_TO_ERC20_FULL_OPEN
] = BasicOrderRouteType.ERC721_TO_ERC20;
_OrderToRouteType[
BasicOrderType.ERC721_TO_ERC20_PARTIAL_OPEN
] = BasicOrderRouteType.ERC721_TO_ERC20;
_OrderToRouteType[
BasicOrderType.ERC721_TO_ERC20_FULL_RESTRICTED
] = BasicOrderRouteType.ERC721_TO_ERC20;
_OrderToRouteType[
BasicOrderType.ERC721_TO_ERC20_PARTIAL_RESTRICTED
] = BasicOrderRouteType.ERC721_TO_ERC20;
// ERC 1155 TO ERC 20
_OrderToRouteType[
BasicOrderType.ERC1155_TO_ERC20_FULL_OPEN
] = BasicOrderRouteType.ERC1155_TO_ERC20;
_OrderToRouteType[
BasicOrderType.ERC1155_TO_ERC20_PARTIAL_OPEN
] = BasicOrderRouteType.ERC1155_TO_ERC20;
_OrderToRouteType[
BasicOrderType.ERC1155_TO_ERC20_FULL_RESTRICTED
] = BasicOrderRouteType.ERC1155_TO_ERC20;
_OrderToRouteType[
BasicOrderType.ERC1155_TO_ERC20_PARTIAL_RESTRICTED
] = BasicOrderRouteType.ERC1155_TO_ERC20;
// Basic OrderType to OrderType
// FULL OPEN
_BasicOrderToOrderType[
BasicOrderType.ETH_TO_ERC721_FULL_OPEN
] = OrderType.FULL_OPEN;
_BasicOrderToOrderType[
BasicOrderType.ETH_TO_ERC1155_FULL_OPEN
] = OrderType.FULL_OPEN;
_BasicOrderToOrderType[
BasicOrderType.ERC20_TO_ERC721_FULL_OPEN
] = OrderType.FULL_OPEN;
_BasicOrderToOrderType[
BasicOrderType.ERC20_TO_ERC1155_FULL_OPEN
] = OrderType.FULL_OPEN;
_BasicOrderToOrderType[
BasicOrderType.ERC721_TO_ERC20_FULL_OPEN
] = OrderType.FULL_OPEN;
_BasicOrderToOrderType[
BasicOrderType.ERC1155_TO_ERC20_FULL_OPEN
] = OrderType.FULL_OPEN;
// PARTIAL OPEN
_BasicOrderToOrderType[
BasicOrderType.ETH_TO_ERC721_PARTIAL_OPEN
] = OrderType.PARTIAL_OPEN;
_BasicOrderToOrderType[
BasicOrderType.ETH_TO_ERC1155_PARTIAL_OPEN
] = OrderType.PARTIAL_OPEN;
_BasicOrderToOrderType[
BasicOrderType.ERC20_TO_ERC721_PARTIAL_OPEN
] = OrderType.PARTIAL_OPEN;
_BasicOrderToOrderType[
BasicOrderType.ERC20_TO_ERC1155_PARTIAL_OPEN
] = OrderType.PARTIAL_OPEN;
_BasicOrderToOrderType[
BasicOrderType.ERC721_TO_ERC20_PARTIAL_OPEN
] = OrderType.PARTIAL_OPEN;
_BasicOrderToOrderType[
BasicOrderType.ERC1155_TO_ERC20_PARTIAL_OPEN
] = OrderType.PARTIAL_OPEN;
// FULL RESTRICTED
_BasicOrderToOrderType[
BasicOrderType.ETH_TO_ERC721_FULL_RESTRICTED
] = OrderType.FULL_RESTRICTED;
_BasicOrderToOrderType[
BasicOrderType.ETH_TO_ERC1155_FULL_RESTRICTED
] = OrderType.FULL_RESTRICTED;
_BasicOrderToOrderType[
BasicOrderType.ERC20_TO_ERC721_FULL_RESTRICTED
] = OrderType.FULL_RESTRICTED;
_BasicOrderToOrderType[
BasicOrderType.ERC20_TO_ERC1155_FULL_RESTRICTED
] = OrderType.FULL_RESTRICTED;
_BasicOrderToOrderType[
BasicOrderType.ERC721_TO_ERC20_FULL_RESTRICTED
] = OrderType.FULL_RESTRICTED;
_BasicOrderToOrderType[
BasicOrderType.ERC1155_TO_ERC20_FULL_RESTRICTED
] = OrderType.FULL_RESTRICTED;
// PARTIAL RESTRICTED
_BasicOrderToOrderType[
BasicOrderType.ETH_TO_ERC721_PARTIAL_RESTRICTED
] = OrderType.PARTIAL_RESTRICTED;
_BasicOrderToOrderType[
BasicOrderType.ETH_TO_ERC1155_PARTIAL_RESTRICTED
] = OrderType.PARTIAL_RESTRICTED;
_BasicOrderToOrderType[
BasicOrderType.ERC20_TO_ERC721_PARTIAL_RESTRICTED
] = OrderType.PARTIAL_RESTRICTED;
_BasicOrderToOrderType[
BasicOrderType.ERC20_TO_ERC1155_PARTIAL_RESTRICTED
] = OrderType.PARTIAL_RESTRICTED;
_BasicOrderToOrderType[
BasicOrderType.ERC721_TO_ERC20_PARTIAL_RESTRICTED
] = OrderType.PARTIAL_RESTRICTED;
_BasicOrderToOrderType[
BasicOrderType.ERC1155_TO_ERC20_PARTIAL_RESTRICTED
] = OrderType.PARTIAL_RESTRICTED;
}
/**
* @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 with 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) {
// Determine the basic order route type from the basic order type.
BasicOrderRouteType route;
{
BasicOrderType basicType = parameters.basicOrderType;
route = _OrderToRouteType[basicType];
}
// Determine the order type from the basic order type.
OrderType orderType;
{
BasicOrderType basicType = parameters.basicOrderType;
orderType = _BasicOrderToOrderType[basicType];
}
// Declare additional recipient item type to derive from the route type.
ItemType additionalRecipientsItemType;
if (
route == BasicOrderRouteType.ETH_TO_ERC721 ||
route == BasicOrderRouteType.ETH_TO_ERC1155
) {
additionalRecipientsItemType = ItemType.NATIVE;
} else {
additionalRecipientsItemType = ItemType.ERC20;
}
// Revert if msg.value was not supplied as part of a payable route.
if (msg.value == 0 && additionalRecipientsItemType == ItemType.NATIVE) {
revert InvalidMsgValue(msg.value);
}
// Revert if msg.value was supplied as part of a non-payable route.
if (msg.value != 0 && additionalRecipientsItemType == ItemType.ERC20) {
revert InvalidMsgValue(msg.value);
}
// Determine the token that additional recipients should have set.
address additionalRecipientsToken;
if (
route == BasicOrderRouteType.ERC721_TO_ERC20 ||
route == BasicOrderRouteType.ERC1155_TO_ERC20
) {
additionalRecipientsToken = parameters.offerToken;
} else {
additionalRecipientsToken = parameters.considerationToken;
}
// Determine the item type for received items.
ItemType receivedItemType;
if (
route == BasicOrderRouteType.ETH_TO_ERC721 ||
route == BasicOrderRouteType.ETH_TO_ERC1155
) {
receivedItemType = ItemType.NATIVE;
} else if (
route == BasicOrderRouteType.ERC20_TO_ERC721 ||
route == BasicOrderRouteType.ERC20_TO_ERC1155
) {
receivedItemType = ItemType.ERC20;
} else if (route == BasicOrderRouteType.ERC721_TO_ERC20) {
receivedItemType = ItemType.ERC721;
} else {
receivedItemType = ItemType.ERC1155;
}
// Determine the item type for the offered item.
ItemType offeredItemType;
if (
route == BasicOrderRouteType.ERC721_TO_ERC20 ||
route == BasicOrderRouteType.ERC1155_TO_ERC20
) {
offeredItemType = ItemType.ERC20;
} else if (
route == BasicOrderRouteType.ETH_TO_ERC721 ||
route == BasicOrderRouteType.ERC20_TO_ERC721
) {
offeredItemType = ItemType.ERC721;
} else {
offeredItemType = ItemType.ERC1155;
}
// Derive & validate order using parameters and update order status.
bytes32 orderHash = _prepareBasicFulfillment(
parameters,
orderType,
receivedItemType,
additionalRecipientsItemType,
additionalRecipientsToken,
offeredItemType
);
// Determine conduitKey argument used by transfer functions.
bytes32 conduitKey;
if (
route == BasicOrderRouteType.ERC721_TO_ERC20 ||
route == BasicOrderRouteType.ERC1155_TO_ERC20
) {
conduitKey = parameters.fulfillerConduitKey;
} else {
conduitKey = parameters.offererConduitKey;
}
// Check for dirtied unused parameters.
if (
((route == BasicOrderRouteType.ETH_TO_ERC721 ||
route == BasicOrderRouteType.ETH_TO_ERC1155) &&
(uint160(parameters.considerationToken) |
parameters.considerationIdentifier) !=
0) ||
((route == BasicOrderRouteType.ERC20_TO_ERC721 ||
route == BasicOrderRouteType.ERC20_TO_ERC1155) &&
parameters.considerationIdentifier != 0) ||
((route == BasicOrderRouteType.ERC721_TO_ERC20 ||
route == BasicOrderRouteType.ERC1155_TO_ERC20) &&
parameters.offerIdentifier != 0)
) {
revert UnusedItemParameters();
}
// Declare transfer accumulator that will collect transfers that can be
// bundled into a single call to their associated conduit.
AccumulatorStruct memory accumulatorStruct;
// Transfer tokens based on the route.
if (route == BasicOrderRouteType.ETH_TO_ERC721) {
// Transfer ERC721 to caller using offerer's conduit if applicable.
_transferERC721(
parameters.offerToken,
parameters.offerer,
msg.sender,
parameters.offerIdentifier,
parameters.offerAmount,
conduitKey,
accumulatorStruct
);
// Transfer native to recipients, return excess to caller & wrap up.
_transferEthAndFinalize(parameters.considerationAmount, parameters);
} else if (route == BasicOrderRouteType.ETH_TO_ERC1155) {
// Transfer ERC1155 to caller using offerer's conduit if applicable.
_transferERC1155(
parameters.offerToken,
parameters.offerer,
msg.sender,
parameters.offerIdentifier,
parameters.offerAmount,
conduitKey,
accumulatorStruct
);
// Transfer native to recipients, return excess to caller & wrap up.
_transferEthAndFinalize(parameters.considerationAmount, parameters);
} else if (route == BasicOrderRouteType.ERC20_TO_ERC721) {
// Transfer ERC721 to caller using offerer's conduit if applicable.
_transferERC721(
parameters.offerToken,
parameters.offerer,
msg.sender,
parameters.offerIdentifier,
parameters.offerAmount,
conduitKey,
accumulatorStruct
);
// Transfer ERC20 tokens to all recipients and wrap up.
_transferERC20AndFinalize(
msg.sender,
parameters.offerer,
parameters.considerationToken,
parameters.considerationAmount,
parameters,
false, // Send full amount indicated by all consideration items.
accumulatorStruct
);
} else if (route == BasicOrderRouteType.ERC20_TO_ERC1155) {
// Transfer ERC1155 to caller using offerer's conduit if applicable.
_transferERC1155(
parameters.offerToken,
parameters.offerer,
msg.sender,
parameters.offerIdentifier,
parameters.offerAmount,
conduitKey,
accumulatorStruct
);
// Transfer ERC20 tokens to all recipients and wrap up.
_transferERC20AndFinalize(
msg.sender,
parameters.offerer,
parameters.considerationToken,
parameters.considerationAmount,
parameters,
false, // Send full amount indicated by all consideration items.
accumulatorStruct
);
} else if (route == BasicOrderRouteType.ERC721_TO_ERC20) {
// Transfer ERC721 to offerer using caller's conduit if applicable.
_transferERC721(
parameters.considerationToken,
msg.sender,
parameters.offerer,
parameters.considerationIdentifier,
parameters.considerationAmount,
conduitKey,
accumulatorStruct
);
// Transfer ERC20 tokens to all recipients and wrap up.
_transferERC20AndFinalize(
parameters.offerer,
msg.sender,
parameters.offerToken,
parameters.offerAmount,
parameters,
true, // Reduce amount sent to fulfiller by additional amounts.
accumulatorStruct
);
} else {
// route == BasicOrderRouteType.ERC1155_TO_ERC20
// Transfer ERC1155 to offerer using caller's conduit if applicable.
_transferERC1155(
parameters.considerationToken,
msg.sender,
parameters.offerer,
parameters.considerationIdentifier,
parameters.considerationAmount,
conduitKey,
accumulatorStruct
);
// Transfer ERC20 tokens to all recipients and wrap up.
_transferERC20AndFinalize(
parameters.offerer,
msg.sender,
parameters.offerToken,
parameters.offerAmount,
parameters,
true, // Reduce amount sent to fulfiller by additional amounts.
accumulatorStruct
);
}
// Trigger any remaining accumulated transfers via call to the conduit.
_triggerIfArmed(accumulatorStruct);
// Determine whether order is restricted and, if so, that it is valid.
_assertRestrictedBasicOrderValidity(
orderHash,
orderType,
parameters,
offeredItemType,
receivedItemType
);
return true;
}
/**
* @dev Internal function to calculate the order hash.
*
* @param hashes The array of offerItems and receivedItems
* hashes.
* @param parameters The parameters of the basic order.
* @param fulfillmentItemTypes The fulfillment's item type.
*
* @return orderHash The order hash.
*/
function _hashOrder(
BasicFulfillmentHashes memory hashes,
BasicOrderParameters calldata parameters,
FulfillmentItemTypes memory fulfillmentItemTypes
) internal view returns (bytes32 orderHash) {
// Read offerer's current counter from storage and place on the stack.
uint256 counter = _getCounter(parameters.offerer);
// Hash the contents to get the orderHash
orderHash = keccak256(
abi.encode(
hashes.typeHash,
parameters.offerer,
parameters.zone,
hashes.offerItemsHash,
hashes.receivedItemsHash,
fulfillmentItemTypes.orderType,
parameters.startTime,
parameters.endTime,
parameters.zoneHash,
parameters.salt,
parameters.offererConduitKey,
counter
)
);
}
/**
* @dev Internal function to prepare fulfillment of a basic order. This
* calculates the order hash, emits an OrderFulfilled event, and
* asserts basic order validity.
*
* @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.
*
* @return orderHash The calculated order hash.
*/
function _prepareBasicFulfillment(
BasicOrderParameters calldata parameters,
OrderType orderType,
ItemType receivedItemType,
ItemType additionalRecipientsItemType,
address additionalRecipientsToken,
ItemType offeredItemType
) internal returns (bytes32 orderHash) {
// 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 is only required on the optimized contract,
// but is included here to maintain parity.
_assertValidBasicOrderParameters();
// Ensure supplied consideration array length is not less than original.
_assertConsiderationLengthIsNotLessThanOriginalConsiderationLength(
parameters.additionalRecipients.length,
parameters.totalOriginalAdditionalRecipients
);
// Memory to store hashes.
BasicFulfillmentHashes memory hashes;
// Store ItemType/Token parameters in a struct in memory to avoid stack
// issues.
FulfillmentItemTypes memory fulfillmentItemTypes = FulfillmentItemTypes(
orderType,
receivedItemType,
additionalRecipientsItemType,
additionalRecipientsToken,
offeredItemType
);
// Array of Received Items for use with OrderFulfilled event.
ReceivedItem[] memory consideration = new ReceivedItem[](
parameters.additionalRecipients.length + 1
);
{
// Load consideration item typehash from runtime and place on stack.
hashes.typeHash = _CONSIDERATION_ITEM_TYPEHASH;
// Create Consideration item.
ConsiderationItem memory primaryConsiderationItem = (
ConsiderationItem(
fulfillmentItemTypes.receivedItemType,
parameters.considerationToken,
parameters.considerationIdentifier,
parameters.considerationAmount,
parameters.considerationAmount,
parameters.offerer
)
);
// Array of all consideration item hashes.
hashes.considerationHashes = new bytes32[](
parameters.totalOriginalAdditionalRecipients + 1
);
// Hash contents.
hashes.considerationHashes[0] = keccak256(
abi.encode(
hashes.typeHash,
primaryConsiderationItem.itemType,
primaryConsiderationItem.token,
primaryConsiderationItem.identifierOrCriteria,
primaryConsiderationItem.startAmount,
primaryConsiderationItem.endAmount,
primaryConsiderationItem.recipient
)
);
// Declare memory for additionalReceivedItem and
// additionalRecipientItem.
ReceivedItem memory additionalReceivedItem;
ConsiderationItem memory additionalRecipientItem;
// Create Received item.
ReceivedItem memory primaryReceivedItem = ReceivedItem(
fulfillmentItemTypes.receivedItemType,
primaryConsiderationItem.token,
primaryConsiderationItem.identifierOrCriteria,
primaryConsiderationItem.endAmount,
primaryConsiderationItem.recipient
);
// Add the Received item to the
// OrderFulfilled ReceivedItem[].
consideration[0] = primaryReceivedItem;
/** Loop through all additionalRecipients, to generate
* ReceivedItems for OrderFulfilled Event and
* ConsiderationItems for hashing.
*/
for (
uint256 recipientCount = 0;
recipientCount < parameters.totalOriginalAdditionalRecipients;
++recipientCount
) {
// Get the next additionalRecipient.
AdditionalRecipient memory additionalRecipient = (
parameters.additionalRecipients[recipientCount]
);
// Create a Received item for each additional recipients.
additionalReceivedItem = ReceivedItem(
fulfillmentItemTypes.additionalRecipientsItemType,
fulfillmentItemTypes.additionalRecipientsToken,
0,
additionalRecipient.amount,
additionalRecipient.recipient
);
// Add additional Received items to the
// OrderFulfilled ReceivedItem[].
consideration[recipientCount + 1] = additionalReceivedItem;
// Create a new consideration item for each additional
// recipient.
additionalRecipientItem = ConsiderationItem(
fulfillmentItemTypes.additionalRecipientsItemType,
fulfillmentItemTypes.additionalRecipientsToken,
0,
additionalRecipient.amount,
additionalRecipient.amount,
additionalRecipient.recipient
);
// Calculate the EIP712 ConsiderationItem hash for
// each additional recipients.
hashes.considerationHashes[recipientCount + 1] = keccak256(
abi.encode(
hashes.typeHash,
additionalRecipientItem.itemType,
additionalRecipientItem.token,
additionalRecipientItem.identifierOrCriteria,
additionalRecipientItem.startAmount,
additionalRecipientItem.endAmount,
additionalRecipientItem.recipient
)
);
}
/**
* The considerationHashes array now contains
* all consideration Item hashes.
*
* The consideration array now contains all received
* items excluding tips for OrderFulfilled Event.
*/
// Get hash of all consideration items.
hashes.receivedItemsHash = keccak256(
abi.encodePacked(hashes.considerationHashes)
);
// Get remainder of additionalRecipients for tips.
for (
uint256 additionalTips = parameters
.totalOriginalAdditionalRecipients;
additionalTips < parameters.additionalRecipients.length;
++additionalTips
) {
// Get the next additionalRecipient.
AdditionalRecipient memory additionalRecipient = (
parameters.additionalRecipients[additionalTips]
);
// Create the ReceivedItem.
additionalReceivedItem = ReceivedItem(
fulfillmentItemTypes.additionalRecipientsItemType,
fulfillmentItemTypes.additionalRecipientsToken,
0,
additionalRecipient.amount,
additionalRecipient.recipient
);
// Add additional received items to the
// OrderFulfilled ReceivedItem[].
consideration[additionalTips + 1] = additionalReceivedItem;
}
}
// Now let's handle the offer side.
// Write the offer to the Event SpentItem array.
SpentItem[] memory offer = new SpentItem[](1);
{
// Place offer item typehash on the stack.
hashes.typeHash = _OFFER_ITEM_TYPEHASH;
// Create Spent item.
SpentItem memory offerItem = SpentItem(
fulfillmentItemTypes.offeredItemType,
parameters.offerToken,
parameters.offerIdentifier,
parameters.offerAmount
);
// Add the offer item to the SpentItem array.
offer[0] = offerItem;
// Get the hash of the Spent item, treated as an Offer item.
bytes32[1] memory offerItemHashes = [
keccak256(
abi.encode(
hashes.typeHash,
offerItem.itemType,
offerItem.token,
offerItem.identifier,
offerItem.amount,
// Assembly uses OfferItem instead of SpentItem.
offerItem.amount
)
)
];
// Get hash of all Spent items.
hashes.offerItemsHash = keccak256(
abi.encodePacked(offerItemHashes)
);
}
{
// Create the OrderComponent in order to derive
// the orderHash.
// Load order typehash from runtime code and place on stack.
hashes.typeHash = _ORDER_TYPEHASH;
// Derive the order hash.
hashes.orderHash = _hashOrder(
hashes,
parameters,
fulfillmentItemTypes
);
// Emit an event signifying that the order has been fulfilled.
emit OrderFulfilled(
hashes.orderHash,
parameters.offerer,
parameters.zone,
msg.sender,
offer,
consideration
);
}
// Verify and update the status of the derived order.
_validateBasicOrderAndUpdateStatus(
hashes.orderHash,
parameters.offerer,
parameters.signature
);
// Return the derived order hash.
return hashes.orderHash;
}
/**
* @dev Internal function to transfer Ether (or other native tokens) to a
* given recipient as part of basic order fulfillment. Note that
* proxies are not utilized for native tokens as the transferred amount
* must be provided as msg.value.
*
* @param amount The amount to transfer.
* @param parameters The parameters of the basic order in question.
*/
function _transferEthAndFinalize(
uint256 amount,
BasicOrderParameters calldata parameters
) internal {
// Put native token value supplied by the caller on the stack.
uint256 nativeTokensRemaining = msg.value;
// Iterate over each additional recipient.
for (uint256 i = 0; i < parameters.additionalRecipients.length; ++i) {
// Retrieve the additional recipient.
AdditionalRecipient calldata additionalRecipient = (
parameters.additionalRecipients[i]
);
// Read native token amount to transfer to recipient & put on stack.
uint256 additionalRecipientAmount = additionalRecipient.amount;
// Ensure that sufficient native tokens are available.
if (additionalRecipientAmount > nativeTokensRemaining) {
revert InsufficientNativeTokensSupplied();
}
// Transfer native token to the additional recipient.
_transferNativeTokens(
additionalRecipient.recipient,
additionalRecipientAmount
);
// Reduce native token value available.
nativeTokensRemaining -= additionalRecipientAmount;
}
// Ensure that sufficient native token is still available.
if (amount > nativeTokensRemaining) {
revert InsufficientNativeTokensSupplied();
}
// Transfer native token to the offerer.
_transferNativeTokens(parameters.offerer, amount);
// If any native token remains after transfers, return it to the caller.
if (nativeTokensRemaining > amount) {
// Transfer remaining native token to the caller.
_transferNativeTokens(
payable(msg.sender),
nativeTokensRemaining - amount
);
}
}
/**
* @dev Internal function to transfer ERC20 tokens to a given recipient as
* part of basic order fulfillment. Note that proxies are not utilized
* for ERC20 tokens.
*
* @param from The originator of the ERC20 token transfer.
* @param to The recipient of the ERC20 token transfer.
* @param erc20Token The ERC20 token to transfer.
* @param amount The amount of ERC20 tokens to transfer.
* @param parameters The parameters of the order.
* @param fromOfferer Whether to decrement amount from the
* offered amount.
* @param accumulatorStruct A struct containing conduit transfer data
* and its corresponding conduitKey.
*/
function _transferERC20AndFinalize(
address from,
address to,
address erc20Token,
uint256 amount,
BasicOrderParameters calldata parameters,
bool fromOfferer,
AccumulatorStruct memory accumulatorStruct
) internal {
// Determine the appropriate conduit to utilize.
bytes32 conduitKey;
if (fromOfferer) {
conduitKey = parameters.offererConduitKey;
} else {
conduitKey = parameters.fulfillerConduitKey;
}
// Iterate over each additional recipient.
for (uint256 i = 0; i < parameters.additionalRecipients.length; ++i) {
// Retrieve the additional recipient.
AdditionalRecipient calldata additionalRecipient = (
parameters.additionalRecipients[i]
);
// Decrement the amount to transfer to fulfiller if indicated.
if (fromOfferer) {
amount -= additionalRecipient.amount;
}
// Transfer ERC20 tokens to additional recipient given approval.
_transferERC20(
erc20Token,
from,
additionalRecipient.recipient,
additionalRecipient.amount,
conduitKey,
accumulatorStruct
);
}
// Transfer ERC20 token amount (from account must have proper approval).
_transferERC20(
erc20Token,
from,
to,
amount,
conduitKey,
accumulatorStruct
);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
/**
* @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 { Side } from "../lib/ConsiderationEnums.sol";
/**
* @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.
*
* @param side The side of the order that was not supplied.
*/
error OrderCriteriaResolverOutOfRange(Side side);
/**
* @dev Revert with an error if an offer item still has unresolved criteria
* after applying all criteria resolvers.
*
* @param orderIndex The index of the order that contains the offer item.
* @param offerIndex The index of the offer item that still has unresolved
* criteria.
*/
error UnresolvedOfferCriteria(uint256 orderIndex, uint256 offerIndex);
/**
* @dev Revert with an error if a consideration item still has unresolved
* criteria after applying all criteria resolvers.
*
* @param orderIndex The index of the order that contains the
* consideration item.
* @param considerationIndex The index of the consideration item that still
* has unresolved criteria.
*/
error UnresolvedConsiderationCriteria(
uint256 orderIndex,
uint256 considerationIndex
);
/**
* @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, ItemType} from "../../seaport-1.5/lib/ConsiderationEnums.sol";
import {AdvancedOrder, ConsiderationItem, OfferItem, Order, OrderComponents, OrderParameters, OrderStatus, ReceivedItem, SpentItem} from "../../seaport-1.5/lib/ConsiderationStructs.sol";
import {ReferenceExecutor} from "./ReferenceExecutor.sol";
import {ReferenceZoneInteraction} from "./ReferenceZoneInteraction.sol";
import {ContractOffererInterface} from "../../seaport-1.5/interfaces/ContractOffererInterface.sol";
import {ReferenceGenerateOrderReturndataDecoder} from "./ReferenceGenerateOrderReturndataDecoder.sol";
/**
* @title OrderValidator
* @author 0age
* @notice OrderValidator contains functionality related to validating orders
* and updating their status.
*/
contract ReferenceOrderValidator is
ReferenceExecutor,
ReferenceZoneInteraction
{
// Track status of each order (validated, cancelled, and fraction filled).
mapping(bytes32 => OrderStatus) private _orderStatus;
// Track nonces for contract offerers.
mapping(address => uint256) internal _contractNonces;
/**
* @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
) ReferenceExecutor(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 revertOnInvalid A boolean indicating whether to revert if the
* order is invalid due to the time or order status.
*
* @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,
bool revertOnInvalid
)
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);
// If the order is a contract order, return the generated order.
if (orderParameters.orderType == OrderType.CONTRACT) {
// Ensure that numerator and denominator are both equal to 1.
if (numerator != 1 || denominator != 1) {
revert BadFraction();
}
return
_getGeneratedOrder(
orderParameters,
advancedOrder.extraData,
revertOnInvalid
);
}
// Ensure that the supplied numerator and denominator are valid. The
// numerator should not exceed denominator and should not be zero.
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 and use it w/ parameters to get order hash.
orderHash = _assertConsiderationLengthAndGetOrderHash(orderParameters);
// 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 = uint256(orderStatus.numerator);
uint256 filledDenominator = uint256(orderStatus.denominator);
// If order 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) {
// Reduce current numerator so it + supplied = denominator.
numerator = denominator - filledNumerator;
}
// Increment the filled numerator by the new numerator.
filledNumerator += numerator;
// Ensure fractional amounts are below max uint120.
if (
filledNumerator > type(uint120).max ||
denominator > type(uint120).max
) {
// Derive greatest common divisor using euclidean algorithm.
uint256 scaleDown = _greatestCommonDivisor(
numerator,
_greatestCommonDivisor(filledNumerator, denominator)
);
// Scale all fractional values down by gcd.
numerator = numerator / scaleDown;
filledNumerator = filledNumerator / scaleDown;
denominator = denominator / scaleDown;
// Perform the overflow check a second time.
uint256 maxOverhead = type(uint256).max - type(uint120).max;
((filledNumerator + maxOverhead) & (denominator + maxOverhead));
}
// 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, new numerator and denominator.
return (orderHash, uint120(numerator), uint120(denominator));
}
/**
* @dev Internal function to generate a contract order. When a
* collection-wide criteria-based item (criteria = 0) is provided as an
* input to a contract order, the contract offerer has full latitude to
* choose any identifier it wants mid-flight, which differs from the
* usual behavior. For regular criteria-based orders with
* identifierOrCriteria = 0, the fulfiller can pick which identifier to
* receive by providing a CriteriaResolver. For contract offers with
* identifierOrCriteria = 0, Seaport does not expect a corresponding
* CriteriaResolver, and will revert if one is provided.
*
* @param orderParameters The parameters for the order.
* @param context The context for generating the order.
* @param revertOnInvalid Whether to revert on invalid input.
*
* @return orderHash The order hash.
* @return numerator The numerator.
* @return denominator The denominator.
*/
function _getGeneratedOrder(
OrderParameters memory orderParameters,
bytes memory context,
bool revertOnInvalid
)
internal
returns (bytes32 orderHash, uint256 numerator, uint256 denominator)
{
// Ensure that consideration array length is equal to the total original
// consideration items value.
if (
orderParameters.consideration.length !=
orderParameters.totalOriginalConsiderationItems
) {
revert ConsiderationLengthNotEqualToTotalOriginal();
}
{
// Increment contract nonce and use it to derive order hash. Note:
// nonce will be incremented even for skipped orders, and even if
// generateOrder's return data does not satisfy all the constraints.
uint256 contractNonce = _contractNonces[orderParameters.offerer]++;
// Derive order hash from contract nonce and offerer address.
orderHash = bytes32(
contractNonce ^
(uint256(uint160(orderParameters.offerer)) << 96)
);
}
// Convert offer and consideration to spent and received items.
(
SpentItem[] memory originalOfferItems,
SpentItem[] memory originalConsiderationItems
) = _convertToSpent(
orderParameters.offer,
orderParameters.consideration
);
// Create arrays for returned offer and consideration items.
SpentItem[] memory offer;
ReceivedItem[] memory consideration;
{
// Do a low-level call to get success status and any return data.
(bool success, bytes memory returnData) = orderParameters
.offerer
.call(
abi.encodeWithSelector(
ContractOffererInterface.generateOrder.selector,
msg.sender,
originalOfferItems,
originalConsiderationItems,
context
)
);
// If call succeeds, try to decode offer and consideration items.
if (success) {
// Try to decode offer and consideration items from returndata.
try
(new ReferenceGenerateOrderReturndataDecoder()).decode(
returnData
)
returns (
SpentItem[] memory _offer,
ReceivedItem[] memory _consideration
) {
offer = _offer;
consideration = _consideration;
} catch {
// If decoding fails, revert.
revert InvalidContractOrder(orderHash);
}
} else {
// If the call fails, revert or return empty.
return _revertOrReturnEmpty(revertOnInvalid, orderHash);
}
}
{
// Designate lengths.
uint256 originalOfferLength = orderParameters.offer.length;
uint256 newOfferLength = offer.length;
// Explicitly specified offer items cannot be removed.
if (originalOfferLength > newOfferLength) {
revert InvalidContractOrder(orderHash);
} else if (newOfferLength > originalOfferLength) {
// If new offer items are added, extend the original offer.
OfferItem[] memory extendedOffer = new OfferItem[](
newOfferLength
);
// Copy original offer items to new array.
for (uint256 i = 0; i < originalOfferLength; ++i) {
extendedOffer[i] = orderParameters.offer[i];
}
// Update order parameters with extended offer.
orderParameters.offer = extendedOffer;
}
// Loop through each new offer and ensure the new amounts are at
// least as much as the respective original amounts.
for (uint256 i = 0; i < originalOfferLength; ++i) {
// Designate original and new offer items.
OfferItem memory originalOffer = orderParameters.offer[i];
SpentItem memory newOffer = offer[i];
// Set returned identifier for criteria-based items with
// criteria = 0. Note that this reset means that a contract
// offerer has full latitude to choose any identifier it wants
// mid-flight, in contrast to the normal behavior, where the
// fulfiller can pick which identifier to receive by providing a
// CriteriaResolver.
if (
uint256(originalOffer.itemType) > 3 &&
originalOffer.identifierOrCriteria == 0
) {
originalOffer.itemType = ItemType(
uint256(originalOffer.itemType) - 2
);
originalOffer.identifierOrCriteria = newOffer.identifier;
}
// Ensure the original and generated items are compatible.
if (
originalOffer.startAmount != originalOffer.endAmount ||
originalOffer.endAmount > newOffer.amount ||
originalOffer.itemType != newOffer.itemType ||
originalOffer.token != newOffer.token ||
originalOffer.identifierOrCriteria != newOffer.identifier
) {
revert InvalidContractOrder(orderHash);
}
// Update the original amounts to use the generated amounts.
originalOffer.startAmount = newOffer.amount;
originalOffer.endAmount = newOffer.amount;
}
// Add new offer items if there are more than original.
for (uint256 i = originalOfferLength; i < newOfferLength; ++i) {
OfferItem memory originalOffer = orderParameters.offer[i];
SpentItem memory newOffer = offer[i];
originalOffer.itemType = newOffer.itemType;
originalOffer.token = newOffer.token;
originalOffer.identifierOrCriteria = newOffer.identifier;
originalOffer.startAmount = newOffer.amount;
originalOffer.endAmount = newOffer.amount;
}
}
{
// Designate lengths & memory locations.
ConsiderationItem[] memory originalConsiderationArray = (
orderParameters.consideration
);
uint256 newConsiderationLength = consideration.length;
// New consideration items cannot be created.
if (newConsiderationLength > originalConsiderationArray.length) {
revert InvalidContractOrder(orderHash);
}
// Loop through and check consideration.
for (uint256 i = 0; i < newConsiderationLength; ++i) {
ReceivedItem memory newConsideration = consideration[i];
ConsiderationItem memory originalConsideration = (
originalConsiderationArray[i]
);
if (
uint256(originalConsideration.itemType) > 3 &&
originalConsideration.identifierOrCriteria == 0
) {
originalConsideration.itemType = ItemType(
uint256(originalConsideration.itemType) - 2
);
originalConsideration
.identifierOrCriteria = newConsideration.identifier;
}
// All fields must match the originally supplied fields except
// for the amount (which may be reduced by the contract offerer)
// and the recipient if not provided by the recipient.
if (
originalConsideration.startAmount !=
originalConsideration.endAmount ||
newConsideration.amount > originalConsideration.endAmount ||
originalConsideration.itemType !=
newConsideration.itemType ||
originalConsideration.token != newConsideration.token ||
originalConsideration.identifierOrCriteria !=
newConsideration.identifier ||
(originalConsideration.recipient != address(0) &&
originalConsideration.recipient !=
(newConsideration.recipient))
) {
revert InvalidContractOrder(orderHash);
}
// Update the original amounts to use the generated amounts.
originalConsideration.startAmount = newConsideration.amount;
originalConsideration.endAmount = newConsideration.amount;
originalConsideration.recipient = newConsideration.recipient;
}
// Shorten original consideration array if longer than new array.
ConsiderationItem[] memory shortenedConsiderationArray = (
new ConsiderationItem[](newConsiderationLength)
);
// Iterate over original consideration array and copy to new.
for (uint256 i = 0; i < newConsiderationLength; ++i) {
shortenedConsiderationArray[i] = originalConsiderationArray[i];
}
// Replace original consideration array with new shortend array.
orderParameters.consideration = shortenedConsiderationArray;
}
// Return the order hash, the numerator, and the denominator.
return (orderHash, 1, 1);
}
/**
* @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`.
* Also note that contract orders are not cancellable.
*
* @param orders The orders to cancel.
*
* @return A boolean indicating whether the supplied orders were
* successfully cancelled.
*/
function _cancel(
OrderComponents[] calldata orders
) internal returns (bool) {
// Declare variables outside of the loop.
OrderStatus storage orderStatus;
address offerer;
address zone;
// 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; ++i) {
// Retrieve the order.
OrderComponents calldata order = orders[i];
offerer = order.offerer;
zone = order.zone;
// Ensure caller is either offerer or zone of the order and that the
// order is not a contract order.
if (
order.orderType == OrderType.CONTRACT ||
(msg.sender != offerer && msg.sender != zone)
) {
revert CannotCancelOrder();
}
// 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);
}
return true;
}
/**
* @dev Internal function to validate an arbitrary number of orders, thereby
* registering them as valid and allowing the fulfiller to skip
* verification. 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 A boolean indicating whether the supplied orders were
* successfully validated.
*/
function _validate(Order[] calldata orders) internal returns (bool) {
// Declare variables outside of the loop.
OrderStatus storage orderStatus;
bytes32 orderHash;
address offerer;
// 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; ++i) {
// Retrieve the order.
Order calldata order = orders[i];
// Retrieve the order parameters.
OrderParameters calldata orderParameters = order.parameters;
// Skip contract orders.
if (orderParameters.orderType == OrderType.CONTRACT) {
continue;
}
// Move offerer from memory to the stack.
offerer = orderParameters.offerer;
// Get current counter and 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) {
// Ensure that consideration array length is equal to the total
// original consideration items value.
if (
orderParameters.consideration.length !=
orderParameters.totalOriginalConsiderationItems
) {
revert ConsiderationLengthNotEqualToTotalOriginal();
}
// 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, orderParameters);
}
}
return 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 either revert or return an empty tuple
* depending on the value of `revertOnInvalid`.
*
* @param revertOnInvalid Whether to revert on invalid input.
* @param contractOrderHash The contract order hash.
*
* @return orderHash The order hash.
* @return numerator The numerator.
* @return denominator The denominator.
*/
function _revertOrReturnEmpty(
bool revertOnInvalid,
bytes32 contractOrderHash
)
internal
pure
returns (bytes32 orderHash, uint256 numerator, uint256 denominator)
{
// If invalid input should not revert...
if (!revertOnInvalid) {
// Return the contract order hash and zero values for the numerator
// and denominator.
return (contractOrderHash, 0, 0);
}
// Otherwise, revert.
revert InvalidContractOrder(contractOrderHash);
}
/**
* @dev Internal pure function to convert both offer and consideration items
* to spent items.
*
* @param offer The offer items to convert.
* @param consideration The consideration items to convert.
*
* @return spentItems The converted spent items.
* @return receivedItems The converted received items.
*/
function _convertToSpent(
OfferItem[] memory offer,
ConsiderationItem[] memory consideration
)
internal
pure
returns (
SpentItem[] memory spentItems,
SpentItem[] memory receivedItems
)
{
// Create an array of spent items equal to the offer length.
spentItems = new SpentItem[](offer.length);
// Iterate over each offer item on the order.
for (uint256 i = 0; i < offer.length; ++i) {
// Retrieve the offer item.
OfferItem memory offerItem = offer[i];
// Create spent item for event based on the offer item.
SpentItem memory spentItem = SpentItem(
offerItem.itemType,
offerItem.token,
offerItem.identifierOrCriteria,
offerItem.startAmount
);
// Add to array of spent items.
spentItems[i] = spentItem;
}
// Create an array of received items equal to the consideration length.
receivedItems = new SpentItem[](consideration.length);
// Iterate over each consideration item on the order.
for (uint256 i = 0; i < consideration.length; ++i) {
// Retrieve the consideration item.
ConsiderationItem memory considerationItem = (consideration[i]);
// Create spent item for event based on the consideration item.
SpentItem memory receivedItem = SpentItem(
considerationItem.itemType,
considerationItem.token,
considerationItem.identifierOrCriteria,
considerationItem.startAmount
);
// Add to array of received items.
receivedItems[i] = receivedItem;
}
}
/**
* @dev Internal function to derive the greatest common divisor of two
* values using the classical euclidian algorithm.
*
* @param a The first value.
* @param b The second value.
*
* @return greatestCommonDivisor The greatest common divisor.
*/
function _greatestCommonDivisor(
uint256 a,
uint256 b
) internal pure returns (uint256 greatestCommonDivisor) {
while (b > 0) {
uint256 c = b;
b = a % c;
a = c;
}
greatestCommonDivisor = a;
}
/**
* @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.
isFullOrder = uint256(orderType) & 1 == 0;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
import {
ReceivedItem,
Schema,
SpentItem
} from "../lib/ConsiderationStructs.sol";
/**
* @title ContractOffererInterface
* @notice Contains the minimum interfaces needed to interact with a contract
* offerer.
*/
interface ContractOffererInterface {
/**
* @dev Generates an order with the specified minimum and maximum spent
* items, and optional context (supplied as extraData).
*
* @param fulfiller The address of the fulfiller.
* @param minimumReceived The minimum items that the caller is willing to
* receive.
* @param maximumSpent The maximum items the caller is willing to spend.
* @param context Additional context of the order.
*
* @return offer A tuple containing the offer items.
* @return consideration A tuple containing the consideration items.
*/
function generateOrder(
address fulfiller,
SpentItem[] calldata minimumReceived,
SpentItem[] calldata maximumSpent,
bytes calldata context // encoded based on the schemaID
)
external
returns (SpentItem[] memory offer, ReceivedItem[] memory consideration);
/**
* @dev Ratifies an order with the specified offer, consideration, and
* optional context (supplied as extraData).
*
* @param offer The offer items.
* @param consideration The consideration items.
* @param context Additional context of the order.
* @param orderHashes The hashes to ratify.
* @param contractNonce The nonce of the contract.
*
* @return ratifyOrderMagicValue The magic value returned by the contract
* offerer.
*/
function ratifyOrder(
SpentItem[] calldata offer,
ReceivedItem[] calldata consideration,
bytes calldata context, // encoded based on the schemaID
bytes32[] calldata orderHashes,
uint256 contractNonce
) external returns (bytes4 ratifyOrderMagicValue);
/**
* @dev View function to preview an order generated in response to a minimum
* set of received items, maximum set of spent items, and context
* (supplied as extraData).
*
* @param caller The address of the caller (e.g. Seaport).
* @param fulfiller The address of the fulfiller (e.g. the account
* calling Seaport).
* @param minimumReceived The minimum items that the caller is willing to
* receive.
* @param maximumSpent The maximum items the caller is willing to spend.
* @param context Additional context of the order.
*
* @return offer A tuple containing the offer items.
* @return consideration A tuple containing the consideration items.
*/
function previewOrder(
address caller,
address fulfiller,
SpentItem[] calldata minimumReceived,
SpentItem[] calldata maximumSpent,
bytes calldata context // encoded based on the schemaID
)
external
view
returns (SpentItem[] memory offer, ReceivedItem[] memory consideration);
/**
* @dev Gets the metadata for this contract offerer.
*
* @return name The name of the contract offerer.
* @return schemas The schemas supported by the contract offerer.
*/
function getSeaportMetadata()
external
view
returns (
string memory name,
Schema[] memory schemas // map to Seaport Improvement Proposal IDs
);
// Additional functions and/or events based on implemented schemaIDs
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
import {ReceivedItem, SpentItem} from "../../seaport-1.5/lib/ConsiderationStructs.sol";
contract ReferenceGenerateOrderReturndataDecoder {
function decode(
bytes calldata returnedBytes
) external pure returns (SpentItem[] memory, ReceivedItem[] memory) {
return abi.decode(returnedBytes, (SpentItem[], ReceivedItem[]));
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
import {ConduitItemType} from "../../seaport-1.5/conduit/lib/ConduitEnums.sol";
import {ConduitInterface} from "../../seaport-1.5/interfaces/ConduitInterface.sol";
import {ConduitTransfer} from "../../seaport-1.5/conduit/lib/ConduitStructs.sol";
import {ItemType} from "../../seaport-1.5/lib/ConsiderationEnums.sol";
import {ReceivedItem} from "../../seaport-1.5/lib/ConsiderationStructs.sol";
import {ReferenceVerifiers} from "./ReferenceVerifiers.sol";
import {ReferenceTokenTransferrer} from "./ReferenceTokenTransferrer.sol";
import {AccumulatorStruct} from "./ReferenceConsiderationStructs.sol";
/**
* @title Executor
* @author 0age
* @notice Executor contains functions related to processing executions (i.e.
* transferring items, either directly or via conduits).
*/
contract ReferenceExecutor is ReferenceVerifiers, ReferenceTokenTransferrer {
/**
* @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
) ReferenceVerifiers(conduitController) {}
/**
* @dev Internal function to transfer a given item.
*
* @param item The item to transfer including an amount
* and recipient.
* @param offerer The account offering the item, i.e. the
* from address.
* @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
* (and direct approvals set on Consideration)
* @param accumulatorStruct A struct containing conduit transfer data
* and its corresponding conduitKey.
*/
function _transfer(
ReceivedItem memory item,
address offerer,
bytes32 conduitKey,
AccumulatorStruct memory accumulatorStruct
) 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.
_transferNativeTokens(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 offerer to the recipient.
_transferERC20(
item.token,
offerer,
item.recipient,
item.amount,
conduitKey,
accumulatorStruct
);
} else if (item.itemType == ItemType.ERC721) {
// Transfer ERC721 token from the offerer to the recipient.
_transferERC721(
item.token,
offerer,
item.recipient,
item.identifier,
item.amount,
conduitKey,
accumulatorStruct
);
} else {
// Transfer ERC1155 token from the offerer to the recipient.
_transferERC1155(
item.token,
offerer,
item.recipient,
item.identifier,
item.amount,
conduitKey,
accumulatorStruct
);
}
}
/**
* @dev Internal function to transfer Ether or other native tokens to a
* given recipient. Note that this reference implementation deviates
* from the primary contract, which "bubbles up" revert data when
* present (the reference contract always throws a generic error).
*
* @param to The recipient of the transfer.
* @param amount The amount to transfer.
*/
function _transferNativeTokens(
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, ) = to.call{value: amount}("");
// If the call fails...
if (!success) {
// Revert with a generic error message.
revert NativeTokenTransferGenericFailure(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, the 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
* (and direct approvals set on Consideration)
* @param accumulatorStruct A struct containing conduit transfer data
* and its corresponding conduitKey.
*/
function _transferERC20(
address token,
address from,
address to,
uint256 amount,
bytes32 conduitKey,
AccumulatorStruct memory accumulatorStruct
) internal {
// Ensure that the supplied amount is non-zero.
_assertNonZeroAmount(amount);
// Trigger accumulated transfers if the conduits differ.
_triggerIfArmedAndNotAccumulatable(accumulatorStruct, 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,
accumulatorStruct,
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.
* @param amount The "amount" (this value must be equal
* to one).
* @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
* (and direct approvals set on Consideration)
* @param accumulatorStruct A struct containing conduit transfer data
* and its corresponding conduitKey.
*/
function _transferERC721(
address token,
address from,
address to,
uint256 identifier,
uint256 amount,
bytes32 conduitKey,
AccumulatorStruct memory accumulatorStruct
) internal {
// Trigger accumulated transfers if the conduits differ.
_triggerIfArmedAndNotAccumulatable(accumulatorStruct, 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(amount);
}
// Perform transfer via the token contract directly.
_performERC721Transfer(token, from, to, identifier);
} else {
// Insert the call to the conduit into the accumulator.
_insert(
conduitKey,
accumulatorStruct,
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 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
* (and direct approvals set on Consideration)
* @param accumulatorStruct A struct containing conduit transfer data
* and its corresponding conduitKey.
*/
function _transferERC1155(
address token,
address from,
address to,
uint256 identifier,
uint256 amount,
bytes32 conduitKey,
AccumulatorStruct memory accumulatorStruct
) internal {
// Ensure that the supplied amount is non-zero.
_assertNonZeroAmount(amount);
// Trigger accumulated transfers if the conduits differ.
_triggerIfArmedAndNotAccumulatable(accumulatorStruct, 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,
accumulatorStruct,
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 accumulatorStruct A struct containing conduit transfer data
* and its corresponding conduitKey.
* @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 (and direct approvals set on
* Consideration)
*/
function _triggerIfArmedAndNotAccumulatable(
AccumulatorStruct memory accumulatorStruct,
bytes32 conduitKey
) internal {
// Perform conduit call if the set key does not match the supplied key.
if (accumulatorStruct.conduitKey != conduitKey) {
_triggerIfArmed(accumulatorStruct);
}
}
/**
* @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 accumulatorStruct A struct containing conduit transfer data
* and its corresponding conduitKey.
*/
function _triggerIfArmed(
AccumulatorStruct memory accumulatorStruct
) internal {
// Exit if the accumulator is not "armed".
if (accumulatorStruct.transfers.length == 0) {
return;
}
// Perform conduit call.
_trigger(accumulatorStruct);
}
/**
* @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 accumulatorStruct A struct containing conduit transfer data
* and its corresponding conduitKey.
*/
function _trigger(AccumulatorStruct memory accumulatorStruct) internal {
// Call the conduit with all the accumulated transfers.
ConduitInterface(_getConduit(accumulatorStruct.conduitKey)).execute(
accumulatorStruct.transfers
);
// Reset accumulator length to signal that it is now "disarmed".
delete accumulatorStruct.transfers;
}
/**
* @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
* (and direct approvals set on Consideration)
* @param accumulatorStruct A struct containing conduit transfer data
* and its corresponding conduitKey.
* @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,
AccumulatorStruct memory accumulatorStruct,
ConduitItemType itemType,
address token,
address from,
address to,
uint256 identifier,
uint256 amount
) internal pure {
/**
* The following is highly inefficient, but written this way to
* simply demonstrate what is performed by the optimized contract.
*/
// Get the current length of the accumulator's transfers.
uint256 currentTransferLength = accumulatorStruct.transfers.length;
// Create a new array to "insert" the new transfer.
ConduitTransfer[] memory newTransfers = (
new ConduitTransfer[](currentTransferLength + 1)
);
// Fill new array with old transfers.
for (uint256 i = 0; i < currentTransferLength; ++i) {
// Get the old transfer.
ConduitTransfer memory oldTransfer = accumulatorStruct.transfers[i];
// Add the old transfer into the new array.
newTransfers[i] = ConduitTransfer(
oldTransfer.itemType,
oldTransfer.token,
oldTransfer.from,
oldTransfer.to,
oldTransfer.identifier,
oldTransfer.amount
);
}
// Insert new transfer into array.
newTransfers[currentTransferLength] = ConduitTransfer(
itemType,
token,
from,
to,
identifier,
amount
);
// Set accumulator struct transfers to new transfers.
accumulatorStruct.transfers = newTransfers;
// Set the conduitkey of the current transfers.
accumulatorStruct.conduitKey = conduitKey;
}
/**
* @dev Internal function get the conduit derived by the provided
* 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 _getConduit(
bytes32 conduitKey
) internal view returns (address conduit) {
// Derive the address of the conduit using the conduit key.
conduit = _deriveConduit(conduitKey);
// If the conduit does not have runtime code (i.e. is not deployed)...
if (conduit.code.length == 0) {
// Revert with an error indicating an invalid conduit.
revert InvalidConduit(conduitKey, conduit);
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
import {ZoneInterface} from "../../seaport-1.5/interfaces/ZoneInterface.sol";
import {ContractOffererInterface} from "../../seaport-1.5/interfaces/ContractOffererInterface.sol";
import {ItemType, OrderType} from "../../seaport-1.5/lib/ConsiderationEnums.sol";
import {AdditionalRecipient, AdvancedOrder, BasicOrderParameters, ReceivedItem, SpentItem, ZoneParameters} from "../../seaport-1.5/lib/ConsiderationStructs.sol";
import {OrderToExecute} from "./ReferenceConsiderationStructs.sol";
import {ZoneInteractionErrors} from "../../seaport-1.5/interfaces/ZoneInteractionErrors.sol";
/**
* @title ZoneInteraction
* @author 0age
* @notice ZoneInteraction contains logic related to interacting with zones.
*/
contract ReferenceZoneInteraction is ZoneInteractionErrors {
/**
* @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 basicOrderParameters The original basic order parameters.
* @param offeredItemType The type of the order.
* @param receivedItemType The offerer in question.
*/
function _assertRestrictedBasicOrderValidity(
bytes32 orderHash,
OrderType orderType,
BasicOrderParameters calldata basicOrderParameters,
ItemType offeredItemType,
ItemType receivedItemType
) internal {
// Create a new array for the hash.
bytes32[] memory orderHashes = new bytes32[](1);
orderHashes[0] = orderHash;
// Convert the order params and types to spent and received items.
(
SpentItem[] memory offer,
ReceivedItem[] memory consideration
) = _convertToSpentAndReceivedItems(
basicOrderParameters,
offeredItemType,
receivedItemType
);
// Order type 2-3 require zone or offerer be caller or zone to approve.
// Note that in cases where fulfiller == zone, the restricted order
// validation will be skipped.
if (
(orderType == OrderType.FULL_RESTRICTED ||
orderType == OrderType.PARTIAL_RESTRICTED) &&
msg.sender != basicOrderParameters.zone
) {
// Validate the order with the zone.
if (
ZoneInterface(basicOrderParameters.zone).validateOrder(
ZoneParameters({
orderHash: orderHash,
fulfiller: msg.sender,
offerer: basicOrderParameters.offerer,
offer: offer,
consideration: consideration,
extraData: "",
orderHashes: orderHashes,
startTime: basicOrderParameters.startTime,
endTime: basicOrderParameters.endTime,
zoneHash: basicOrderParameters.zoneHash
})
) != ZoneInterface.validateOrder.selector
) {
revert InvalidRestrictedOrder(orderHash);
}
}
}
/**
* @dev Internal view function to determine if a proxy should be utilized
* for a given order and to ensure that the submitter is allowed by the
* order type.
*
* @param advancedOrder The order in question.
* @param orderHashes The order hashes of each order supplied alongside
* the current order as part of a "match" or "fulfill
* available" variety of order fulfillment.
* @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,
OrderToExecute memory orderToExecute,
bytes32[] memory orderHashes,
bytes32 orderHash,
bytes32 zoneHash,
OrderType orderType,
address offerer,
address zone
) internal {
// Order type 2-3 require zone or offerer be caller or zone to approve.
if (
(orderType == OrderType.FULL_RESTRICTED ||
orderType == OrderType.PARTIAL_RESTRICTED) && msg.sender != zone
) {
// Validate the order.
if (
ZoneInterface(zone).validateOrder(
ZoneParameters({
orderHash: orderHash,
fulfiller: msg.sender,
offerer: offerer,
offer: orderToExecute.spentItems,
consideration: orderToExecute.receivedItems,
extraData: advancedOrder.extraData,
orderHashes: orderHashes,
startTime: advancedOrder.parameters.startTime,
endTime: advancedOrder.parameters.endTime,
zoneHash: zoneHash
})
) != ZoneInterface.validateOrder.selector
) {
revert InvalidRestrictedOrder(orderHash);
}
} else if (orderType == OrderType.CONTRACT) {
// Ratify the contract order.
if (
ContractOffererInterface(offerer).ratifyOrder(
orderToExecute.spentItems,
orderToExecute.receivedItems,
advancedOrder.extraData,
orderHashes,
uint96(uint256(orderHash))
) != ContractOffererInterface.ratifyOrder.selector
) {
revert InvalidContractOrder(orderHash);
}
}
}
/**
* @dev Converts the offer and consideration parameters from a
* BasicOrderParameters object into an array of SpentItem and
* ReceivedItem objects.
*
* @param parameters The BasicOrderParameters object containing
* the offer and consideration parameters to be
* converted.
* @param offerItemType The item type of the offer.
* @param considerationItemType The item type of the consideration.
*
* @return spentItems The converted offer parameters as an array
* of SpentItem objects.
* @return receivedItems The converted consideration parameters as an
* array of ReceivedItem objects.
*/
function _convertToSpentAndReceivedItems(
BasicOrderParameters calldata parameters,
ItemType offerItemType,
ItemType considerationItemType
) internal pure returns (SpentItem[] memory, ReceivedItem[] memory) {
// Create the spent item.
SpentItem[] memory spentItems = new SpentItem[](1);
spentItems[0] = SpentItem({
itemType: offerItemType,
token: parameters.offerToken,
amount: parameters.offerAmount,
identifier: parameters.offerIdentifier
});
// Create the received item.
ReceivedItem[] memory receivedItems = new ReceivedItem[](
1 + parameters.additionalRecipients.length
);
address token = parameters.considerationToken;
uint256 amount = parameters.considerationAmount;
uint256 identifier = parameters.considerationIdentifier;
receivedItems[0] = ReceivedItem({
itemType: considerationItemType,
token: token,
amount: amount,
identifier: identifier,
recipient: parameters.offerer
});
// Iterate through the additional recipients and create the received
// items.
for (uint256 i = 0; i < parameters.additionalRecipients.length; i++) {
AdditionalRecipient calldata additionalRecipient = parameters
.additionalRecipients[i];
amount = additionalRecipient.amount;
receivedItems[i + 1] = ReceivedItem({
itemType: considerationItemType,
token: token,
amount: amount,
identifier: identifier,
recipient: additionalRecipient.recipient
});
}
// Return the spent and received items.
return (spentItems, receivedItems);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
import { ZoneParameters, Schema } from "../lib/ConsiderationStructs.sol";
/**
* @title ZoneInterface
* @notice Contains functions exposed by a zone.
*/
interface ZoneInterface {
/**
* @dev Validates an order.
*
* @param zoneParameters The context about the order fulfillment and any
* supplied extraData.
*
* @return validOrderMagicValue The magic value that indicates a valid
* order.
*/
function validateOrder(
ZoneParameters calldata zoneParameters
) external returns (bytes4 validOrderMagicValue);
/**
* @dev Returns the metadata for this zone.
*
* @return name The name of the zone.
* @return schemas The schemas that the zone implements.
*/
function getSeaportMetadata()
external
view
returns (
string memory name,
Schema[] memory schemas // map to Seaport Improvement Proposal IDs
);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
import {
ConduitBatch1155Transfer,
ConduitTransfer
} from "../conduit/lib/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.13;
/**
* @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 call to `isValidOrder`.
*
* @param orderHash The order hash for the invalid restricted order.
*/
error InvalidRestrictedOrder(bytes32 orderHash);
/**
* @dev Revert with an error when attempting to fill a contract order that
* fails to generate an order successfully, that does not adhere to the
* requirements for minimum spent or maximum received supplied by the
* fulfiller, or that fails the post-execution `ratifyOrder` check..
*
* @param orderHash The order hash for the invalid contract order.
*/
error InvalidContractOrder(bytes32 orderHash);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
import {OrderStatus} from "../../seaport-1.5/lib/ConsiderationStructs.sol";
import {ReferenceAssertions} from "./ReferenceAssertions.sol";
import {ReferenceSignatureVerification} from "./ReferenceSignatureVerification.sol";
/**
* @title Verifiers
* @author 0age
* @notice Verifiers contains functions for performing verifications.
*/
contract ReferenceVerifiers is
ReferenceAssertions,
ReferenceSignatureVerification
{
/**
* @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
) ReferenceAssertions(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(startTime, endTime);
}
// 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 64 or 65 bytes or if the recovered signer does not match the
* supplied offerer. Note that in cases where a 64 or 65 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;
}
bytes32 domainSeparator = _domainSeparator();
// Derive original EIP-712 digest using domain separator and order hash.
bytes32 originalDigest = _deriveEIP712Digest(
domainSeparator,
orderHash
);
bytes32 digest;
bytes memory extractedSignature;
if (_isValidBulkOrderSize(signature)) {
// Rederive order hash and digest using bulk order proof.
(orderHash, extractedSignature) = _computeBulkOrderProof(
signature,
orderHash
);
digest = _deriveEIP712Digest(domainSeparator, orderHash);
} else {
digest = originalDigest;
extractedSignature = signature;
}
// Ensure that the signature for the digest is valid for the offerer.
_assertValidSignature(
offerer,
digest,
originalDigest,
signature,
extractedSignature
);
}
/**
* @dev Determines whether the specified bulk order size is valid.
*
* @param signature The signature of the bulk order to check.
*
* @return validLength True if bulk order size is valid, false otherwise.
*/
function _isValidBulkOrderSize(
bytes memory signature
) internal pure returns (bool validLength) {
validLength =
signature.length < 837 &&
signature.length > 98 &&
((signature.length - 67) % 32) < 2;
}
/**
* @dev Computes the bulk order hash for the specified proof and leaf. Note
* that if an index that exceeds the number of orders in the bulk order
* payload will instead "wrap around" and refer to an earlier index.
*
* @param proofAndSignature The proof and signature of the bulk order.
* @param leaf The leaf of the bulk order tree.
*
* @return bulkOrderHash The bulk order hash.
* @return signature The signature of the bulk order.
*/
function _computeBulkOrderProof(
bytes memory proofAndSignature,
bytes32 leaf
) internal view returns (bytes32 bulkOrderHash, bytes memory signature) {
bytes32 root = leaf;
// proofAndSignature with odd length is a compact signature (64 bytes).
uint256 length = proofAndSignature.length % 2 == 0 ? 65 : 64;
// Create a new array of bytes equal to the length of the signature.
signature = new bytes(length);
// Iterate over each byte in the signature.
for (uint256 i = 0; i < length; ++i) {
// Assign the byte from the proofAndSignature to the signature.
signature[i] = proofAndSignature[i];
}
// Compute the key by extracting the next three bytes from the
// proofAndSignature.
uint256 key = (((uint256(uint8(proofAndSignature[length])) << 16) |
((uint256(uint8(proofAndSignature[length + 1]))) << 8)) |
(uint256(uint8(proofAndSignature[length + 2]))));
uint256 height = (proofAndSignature.length - length) / 32;
// Create an array of bytes32 to hold the proof elements.
bytes32[] memory proofElements = new bytes32[](height);
// Iterate over each proof element.
for (uint256 elementIndex = 0; elementIndex < height; ++elementIndex) {
// Compute the starting index for the current proof element.
uint256 start = (length + 3) + (elementIndex * 32);
// Create a new array of bytes to hold the current proof element.
bytes memory buffer = new bytes(32);
// Iterate over each byte in the proof element.
for (uint256 i = 0; i < 32; ++i) {
// Assign the byte from the proofAndSignature to the buffer.
buffer[i] = proofAndSignature[start + i];
}
// Decode the current proof element from the buffer and assign it to
// the proofElements array.
proofElements[elementIndex] = abi.decode(buffer, (bytes32));
}
// Iterate over each proof element.
for (uint256 i = 0; i < proofElements.length; ++i) {
// Retrieve the proof element.
bytes32 proofElement = proofElements[i];
// Check if the current bit of the key is set.
if ((key >> i) % 2 == 0) {
// If the current bit is not set, then concatenate the root and
// the proof element, and compute the keccak256 hash of the
// concatenation to assign it to the root.
root = keccak256(abi.encodePacked(root, proofElement));
} else {
// If the current bit is set, then concatenate the proof element
// and the root, and compute the keccak256 hash of the
// concatenation to assign it to the root.
root = keccak256(abi.encodePacked(proofElement, root));
}
}
// Compute the bulk order hash and return it.
bulkOrderHash = keccak256(
abi.encodePacked(_bulkOrderTypehashes[height], root)
);
// Return the signature.
return (bulkOrderHash, 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.13;
import {ERC20Interface, ERC721Interface, ERC1155Interface} from "../../seaport-1.5/interfaces/AbridgedTokenInterfaces.sol";
import {TokenTransferrerErrors} from "../../seaport-1.5/interfaces/TokenTransferrerErrors.sol";
contract ReferenceTokenTransferrer 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 {
// If the provided token is not a contract, revert.
if (token.code.length == 0) {
revert NoContract(token);
}
// Attempt to transfer the tokens.
(bool ok, bytes memory data) = token.call(
abi.encodeWithSelector(
ERC20Interface.transferFrom.selector,
from,
to,
amount
)
);
// NOTE: revert reasons are not "bubbled up" at the moment
if (!ok) {
revert TokenTransferGenericFailure(token, from, to, 0, amount);
}
// If the token does not return a boolean, revert.
if (data.length != 0 && data.length >= 32) {
if (!abi.decode(data, (bool))) {
revert BadReturnValueFromERC20OnTransfer(
token,
from,
to,
amount
);
}
}
}
/**
* @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.
*
* @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 {
// If the provided token is not a contract, revert.
if (token.code.length == 0) {
revert NoContract(token);
}
ERC721Interface(token).transferFrom(from, to, identifier);
}
/**
* @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 onReceived 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 {
// If the provided token is not a contract, revert.
if (token.code.length == 0) {
revert NoContract(token);
}
ERC1155Interface(token).safeTransferFrom(
from,
to,
identifier,
amount,
""
);
}
/**
* @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 onReceived to indicate that they are willing to accept the
* transfer.
*
* @param token The ERC1155 token to transfer in batch.
* @param from The originator of the transfer batch.
* @param to The recipient of the transfer batch.
* @param identifiers The ids to transfer.
* @param amounts The amounts to transfer.
*/
function _performERC1155BatchTransfer(
address token,
address from,
address to,
uint256[] memory identifiers,
uint256[] memory amounts
) internal {
// If the provided token is not a contract, revert.
if (token.code.length == 0) {
revert NoContract(token);
}
ERC1155Interface(token).safeBatchTransferFrom(
from,
to,
identifiers,
amounts,
""
);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
import {OrderParameters} from "../../seaport-1.5/lib/ConsiderationStructs.sol";
import {ReferenceGettersAndDerivers} from "./ReferenceGettersAndDerivers.sol";
import {TokenTransferrerErrors} from "../../seaport-1.5/interfaces/TokenTransferrerErrors.sol";
import {ReferenceCounterManager} from "./ReferenceCounterManager.sol";
/**
* @title Assertions
* @author 0age
* @notice Assertions contains logic for making various assertions that do not
* fit neatly within a dedicated semantic scope.
*/
contract ReferenceAssertions is
ReferenceGettersAndDerivers,
ReferenceCounterManager,
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
) ReferenceGettersAndDerivers(conduitController) {}
/**
* @dev Internal view function to 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 orderHash The order hash.
*/
function _assertConsiderationLengthAndGetOrderHash(
OrderParameters memory orderParameters
) internal view returns (bytes32 orderHash) {
// 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.
orderHash = _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 in not
* zero.
*
* @param amount The amount to check.
*/
function _assertNonZeroAmount(uint256 amount) internal pure {
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 {
/*
* Checks:
* 1. Order parameters struct offset == 0x20
* 2. Additional recipients arr offset == 0x200
* 3. Signature offset == 0x240 + (recipients.length * 0x40)
* 4. BasicOrderType between 0 and 23 (i.e. < 24)
*/
// Declare a boolean designating basic order parameter offset validity.
bool validOffsets = (abi.decode(msg.data[4:36], (uint256)) == 32 &&
abi.decode(msg.data[548:580], (uint256)) == 576 &&
abi.decode(msg.data[580:612], (uint256)) ==
608 + 64 * abi.decode(msg.data[612:644], (uint256))) &&
abi.decode(msg.data[292:324], (uint256)) < 24;
// Revert with an error if basic order parameter offsets are invalid.
if (!validOffsets) {
revert InvalidBasicOrderParameterEncoding();
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
/**
* @title ERC20Interface
* @notice Contains the minimum interfaces needed to interact with ERC20s.
*/
interface ERC20Interface {
/**
* @dev Allows an operator to transfer tokens on behalf of an owner.
*
* @param from The address of the owner.
* @param to The address of the recipient.
* @param value The amount of tokens to transfer.
*
* @return success True if the transfer was successful.
*/
function transferFrom(
address from,
address to,
uint256 value
) external returns (bool success);
/**
* @dev Allows an operator to approve a spender to transfer tokens on behalf
* of a user.
*
* @param spender The address of the spender.
* @param value The amount of tokens to approve.
*
* @return success True if the approval was successful.
*/
function approve(
address spender,
uint256 value
) external returns (bool success);
/**
* @dev Returns the amount of tokens owned by `account`.
*
* @param account The address of the account to check the balance of.
*
* @return balance The amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
}
/**
* @title ERC721Interface
* @notice Contains the minimum interfaces needed to interact with ERC721s.
*/
interface ERC721Interface {
/**
* @dev Allows an operator to transfer tokens on behalf of an owner.
*
* @param from The address of the owner.
* @param to The address of the recipient.
* @param tokenId The ID of the token to transfer.
*/
function transferFrom(address from, address to, uint256 tokenId) external;
/**
* @dev Allows an owner to approve an operator to transfer all tokens on a
* contract on behalf of the owner.
*
* @param to The address of the operator.
* @param approved Whether the operator is approved.
*/
function setApprovalForAll(address to, bool approved) external;
/**
* @dev Returns the owner of a given token ID.
*
* @param tokenId The token ID.
*
* @return owner The owner of the token.
*/
function ownerOf(uint256 tokenId) external view returns (address owner);
}
/**
* @title ERC1155Interface
* @notice Contains the minimum interfaces needed to interact with ERC1155s.
*/
interface ERC1155Interface {
/**
* @dev Allows an operator to transfer tokens on behalf of an owner.
*
* @param from The address of the owner.
* @param to The address of the recipient.
* @param id The ID of the token(s) to transfer.
* @param amount The amount of tokens to transfer.
* @param data Additional data.
*/
function safeTransferFrom(
address from,
address to,
uint256 id,
uint256 amount,
bytes calldata data
) external;
/**
* @dev Allows an operator to transfer tokens on behalf of an owner.
*
* @param from The address of the owner.
* @param to The address of the recipient.
* @param ids The IDs of the token(s) to transfer.
* @param amounts The amounts of tokens to transfer.
* @param data Additional data.
*/
function safeBatchTransferFrom(
address from,
address to,
uint256[] calldata ids,
uint256[] calldata amounts,
bytes calldata data
) external;
/**
* @dev Allows an owner to approve an operator to transfer all tokens on a
* contract on behalf of the owner.
*
* @param to The address of the operator.
* @param approved Whether the operator is approved.
*/
function setApprovalForAll(address to, bool approved) external;
/**
* @dev Returns the owner of a given token ID.
*
* @param account The address of the account to check the balance of.
* @param id The token ID.
*
* @return balance The balance of the token.
*/
function balanceOf(
address account,
uint256 id
) external view returns (uint256);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
import {EIP1271Interface} from "../../seaport-1.5/interfaces/EIP1271Interface.sol";
import {SignatureVerificationErrors} from "../../seaport-1.5/interfaces/SignatureVerificationErrors.sol";
import {EIP2098_allButHighestBitMask} from "../../seaport-1.5/lib/ConsiderationConstants.sol";
/**
* @title SignatureVerification
* @author 0age
* @notice SignatureVerification contains logic for verifying signatures.
*/
contract ReferenceSignatureVerification is SignatureVerificationErrors {
/**
* @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. Note that in cases where a 64 or 65 byte signature
* is supplied, only standard ECDSA signatures that recover to a
* non-zero address are supported.
*
* @param signer The signer for the order.
* @param digest The digest to verify signature against.
* @param originalDigest The original digest to verify signature against.
* @param originalSignature The original signature.
* @param signature A signature from the signer indicating that the
* order has been approved.
*/
function _assertValidSignature(
address signer,
bytes32 digest,
bytes32 originalDigest,
bytes memory originalSignature,
bytes memory signature
) internal view {
// Declare r, s, and v signature parameters.
bytes32 r;
bytes32 s;
uint8 v;
if (signer.code.length > 0) {
// If signer is a contract, try verification via EIP-1271.
_assertValidEIP1271Signature(
signer,
originalDigest,
originalSignature
);
// Return early if the ERC-1271 signature check succeeded.
return;
} else if (signature.length == 64) {
// If signature contains 64 bytes, parse as EIP-2098 sig. (r+s&v)
// Declare temporary vs that will be decomposed into s and v.
bytes32 vs;
// Decode signature into r, vs.
(r, vs) = abi.decode(signature, (bytes32, bytes32));
// Decompose vs into s and v.
s = vs & EIP2098_allButHighestBitMask;
// If the highest bit is set, v = 28, otherwise v = 27.
v = uint8(uint256(vs >> 255)) + 27;
} else if (signature.length == 65) {
(r, s) = abi.decode(signature, (bytes32, bytes32));
v = uint8(signature[64]);
// Ensure v value is properly formatted.
if (v != 27 && v != 28) {
revert BadSignatureV(v);
}
} else {
revert InvalidSignature();
}
// Attempt to recover signer using the digest and signature parameters.
address recoveredSigner = ecrecover(digest, v, r, s);
// Disallow invalid signers.
if (recoveredSigner == address(0) || recoveredSigner != signer) {
revert InvalidSigner();
// Should a signer be recovered, but it doesn't match the signer...
}
}
/**
* @dev Internal view function to verify the signature of an order using
* ERC-1271 (i.e. contract signatures via `isValidSignature`).
*
* @param signer The signer for the order.
* @param digest The signature digest, derived from the domain separator
* and the order hash.
* @param signature A signature (or other data) used to validate the digest.
*/
function _assertValidEIP1271Signature(
address signer,
bytes32 digest,
bytes memory signature
) internal view {
if (
EIP1271Interface(signer).isValidSignature(digest, signature) !=
EIP1271Interface.isValidSignature.selector
) {
revert BadContractSignature();
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
/**
* @title EIP1271Interface
* @notice Interface for the EIP-1271 standard signature validation method for
* contracts.
*/
interface EIP1271Interface {
/**
* @dev Validates a smart contract signature
*
* @param digest bytes32 The digest of the data to be signed.
* @param signature bytes The signature of the data to be validated.
*
* @return bytes4 The magic value, if the signature is valid.
*/
function isValidSignature(
bytes32 digest,
bytes calldata signature
) external view returns (bytes4);
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
/**
* @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.13;
import {ConsiderationItem, OfferItem, OrderParameters} from "../../seaport-1.5/lib/ConsiderationStructs.sol";
import {ReferenceConsiderationBase} from "./ReferenceConsiderationBase.sol";
/**
* @title GettersAndDerivers
* @author 0age
* @notice ConsiderationInternal contains pure and internal view functions
* related to getting or deriving various values.
*/
contract ReferenceGettersAndDerivers is ReferenceConsiderationBase {
/**
* @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
) ReferenceConsiderationBase(conduitController) {}
/**
* @dev Internal view function to derive the EIP-712 hash for an offer item.
*
* @param offerItem The offered item to hash.
*
* @return The hash.
*/
function _hashOfferItem(
OfferItem memory offerItem
) internal view returns (bytes32) {
return
keccak256(
abi.encode(
_OFFER_ITEM_TYPEHASH,
offerItem.itemType,
offerItem.token,
offerItem.identifierOrCriteria,
offerItem.startAmount,
offerItem.endAmount
)
);
}
/**
* @dev Internal view function to derive the EIP-712 hash for a
* consideration item.
*
* @param considerationItem The consideration item to hash.
*
* @return The hash.
*/
function _hashConsiderationItem(
ConsiderationItem memory considerationItem
) internal view returns (bytes32) {
return
keccak256(
abi.encode(
_CONSIDERATION_ITEM_TYPEHASH,
considerationItem.itemType,
considerationItem.token,
considerationItem.identifierOrCriteria,
considerationItem.startAmount,
considerationItem.endAmount,
considerationItem.recipient
)
);
}
/**
* @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) {
// Designate new memory regions for offer and consideration item hashes.
bytes32[] memory offerHashes = new bytes32[](
orderParameters.offer.length
);
bytes32[] memory considerationHashes = new bytes32[](
orderParameters.totalOriginalConsiderationItems
);
// Iterate over each offer on the order.
for (uint256 i = 0; i < orderParameters.offer.length; ++i) {
// Hash the offer and place the result into memory.
offerHashes[i] = _hashOfferItem(orderParameters.offer[i]);
}
// Iterate over each consideration on the order.
for (
uint256 i = 0;
i < orderParameters.totalOriginalConsiderationItems;
++i
) {
// Hash the consideration and place the result into memory.
considerationHashes[i] = _hashConsiderationItem(
orderParameters.consideration[i]
);
}
// Derive and return the order hash as specified by EIP-712.
return
keccak256(
abi.encode(
_ORDER_TYPEHASH,
orderParameters.offerer,
orderParameters.zone,
keccak256(abi.encodePacked(offerHashes)),
keccak256(abi.encodePacked(considerationHashes)),
orderParameters.orderType,
orderParameters.startTime,
orderParameters.endTime,
orderParameters.zoneHash,
orderParameters.salt,
orderParameters.conduitKey,
counter
)
);
}
/**
* @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) {
value = keccak256(
abi.encodePacked(uint16(0x1901), domainSeparator, orderHash)
);
}
/**
* @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) {
// Derive the conduit address
bytes32 hash = keccak256(
bytes.concat(
keccak256("zksyncCreate2"),
bytes32(uint256(uint160(address(_CONDUIT_CONTROLLER)))),
conduitKey,
_CONDUIT_RUNTIME_CODE_HASH,
keccak256("")
)
);
conduit = address(uint160(uint256(hash)));
}
/**
* @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.
*/
function _domainSeparator() internal view returns (bytes32) {
return
block.chainid == _CHAIN_ID
? _DOMAIN_SEPARATOR
: _deriveDomainSeparator(
_EIP_712_DOMAIN_TYPEHASH,
_NAME_HASH,
_VERSION_HASH
);
}
/**
* @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()
internal
view
returns (
string memory version,
bytes32 domainSeparator,
address conduitController
)
{
version = _VERSION;
domainSeparator = _domainSeparator();
conduitController = address(_CONDUIT_CONTROLLER);
}
/**
* @notice Retrieve the name of this contract.
*
* @return The name of this contract.
*/
function _name() internal pure returns (string memory) {
// Return the name of the contract.
return _NAME;
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
/*
* -------------------------- 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.17/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 = 0x4D;
uint256 constant NameWithLength = 0x0d436F6E73696465726174696F6E;
uint256 constant information_version_offset = 0;
uint256 constant information_version_cd_offset = 0x60;
uint256 constant information_domainSeparator_offset = 0x20;
uint256 constant information_conduitController_offset = 0x40;
uint256 constant information_versionLengthPtr = 0x63;
uint256 constant information_versionWithLength = 0x03312e35; // 1.5
uint256 constant information_length = 0xa0;
uint256 constant _NOT_ENTERED = 1;
uint256 constant _ENTERED = 2;
uint256 constant _ENTERED_AND_ACCEPTING_NATIVE_TOKENS = 3;
uint256 constant Offset_fulfillAdvancedOrder_criteriaResolvers = 0x20;
uint256 constant Offset_fulfillAvailableOrders_offerFulfillments = 0x20;
uint256 constant Offset_fulfillAvailableOrders_considerationFulfillments = 0x40;
uint256 constant Offset_fulfillAvailableAdvancedOrders_criteriaResolvers = 0x20;
uint256 constant Offset_fulfillAvailableAdvancedOrders_offerFulfillments = 0x40;
uint256 constant Offset_fulfillAvailableAdvancedOrders_cnsdrationFlflmnts = (
0x60
);
uint256 constant Offset_matchOrders_fulfillments = 0x20;
uint256 constant Offset_matchAdvancedOrders_criteriaResolvers = 0x20;
uint256 constant Offset_matchAdvancedOrders_fulfillments = 0x40;
// Common Offsets
// Offsets for identically positioned fields shared by:
// OfferItem, ConsiderationItem, SpentItem, ReceivedItem
uint256 constant Selector_length = 0x4;
uint256 constant Common_token_offset = 0x20;
uint256 constant Common_identifier_offset = 0x40;
uint256 constant Common_amount_offset = 0x60;
uint256 constant Common_endAmount_offset = 0x80;
uint256 constant SpentItem_size = 0x80;
uint256 constant SpentItem_size_shift = 0x7;
uint256 constant OfferItem_size = 0xa0;
uint256 constant OfferItem_size_with_length = 0xc0;
uint256 constant ReceivedItem_size_excluding_recipient = 0x80;
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_size = 0xc0;
uint256 constant ConsiderationItem_size_with_length = 0xe0;
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 OrderParameters_offerer_offset = 0x00;
uint256 constant OrderParameters_zone_offset = 0x20;
uint256 constant OrderParameters_offer_head_offset = 0x40;
uint256 constant OrderParameters_consideration_head_offset = 0x60;
// uint256 constant OrderParameters_orderType_offset = 0x80;
uint256 constant OrderParameters_startTime_offset = 0xa0;
uint256 constant OrderParameters_endTime_offset = 0xc0;
uint256 constant OrderParameters_zoneHash_offset = 0xe0;
// uint256 constant OrderParameters_salt_offset = 0x100;
uint256 constant OrderParameters_conduit_offset = 0x120;
uint256 constant OrderParameters_counter_offset = 0x140;
uint256 constant Fulfillment_itemIndex_offset = 0x20;
uint256 constant AdvancedOrder_head_size = 0xa0;
uint256 constant AdvancedOrder_numerator_offset = 0x20;
uint256 constant AdvancedOrder_denominator_offset = 0x40;
uint256 constant AdvancedOrder_signature_offset = 0x60;
uint256 constant AdvancedOrder_extraData_offset = 0x80;
uint256 constant OrderStatus_ValidatedAndNotCancelled = 1;
uint256 constant OrderStatus_filledNumerator_offset = 0x10;
uint256 constant OrderStatus_filledDenominator_offset = 0x88;
uint256 constant ThirtyOneBytes = 0x1f;
uint256 constant OneWord = 0x20;
uint256 constant TwoWords = 0x40;
uint256 constant ThreeWords = 0x60;
uint256 constant FourWords = 0x80;
uint256 constant FiveWords = 0xa0;
uint256 constant OneWordShift = 0x5;
uint256 constant TwoWordsShift = 0x6;
uint256 constant SixtyThreeBytes = 0x3f;
uint256 constant OnlyFullWordMask = 0xffffffe0;
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 BasicOrder_receivedItemByteMap = (
0x0000010102030000000000000000000000000000000000000000000000000000
);
uint256 constant BasicOrder_offeredItemByteMap = (
0x0203020301010000000000000000000000000000000000000000000000000000
);
bytes32 constant OrdersMatchedTopic0 = (
0x4b9f2d36e1b4c93de62cc077b00b1a91d84b6c31b4a14e012718dcca230689e7
);
uint256 constant EIP712_Order_size = 0x180;
uint256 constant EIP712_OfferItem_size = 0xc0;
uint256 constant EIP712_ConsiderationItem_size = 0xe0;
uint256 constant AdditionalRecipient_size = 0x40;
uint256 constant AdditionalRecipient_size_shift = 0x6;
uint256 constant EIP712_DomainSeparator_offset = 0x02;
uint256 constant EIP712_OrderHash_offset = 0x22;
uint256 constant EIP712_DigestPayload_size = 0x42;
uint256 constant EIP712_domainData_nameHash_offset = 0x20;
uint256 constant EIP712_domainData_versionHash_offset = 0x40;
uint256 constant EIP712_domainData_chainId_offset = 0x60;
uint256 constant EIP712_domainData_verifyingContract_offset = 0x80;
uint256 constant EIP712_domainData_size = 0xa0;
// Minimum BulkOrder proof size: 64 bytes for signature + 3 for key + 32 for 1
// sibling. Maximum BulkOrder proof size: 65 bytes for signature + 3 for key +
// 768 for 24 siblings.
uint256 constant BulkOrderProof_minSize = 0x63;
uint256 constant BulkOrderProof_rangeSize = 0x2e2;
uint256 constant BulkOrderProof_lengthAdjustmentBeforeMask = 0x1d;
uint256 constant BulkOrderProof_lengthRangeAfterMask = 0x2;
uint256 constant BulkOrderProof_keyShift = 0xe8;
uint256 constant BulkOrderProof_keySize = 0x3;
uint256 constant BulkOrder_Typehash_Height_One = (
0x3ca2711d29384747a8f61d60aad3c450405f7aaff5613541dee28df2d6986d32
);
uint256 constant BulkOrder_Typehash_Height_Two = (
0xbf8e29b89f29ed9b529c154a63038ffca562f8d7cd1e2545dda53a1b582dde30
);
uint256 constant BulkOrder_Typehash_Height_Three = (
0x53c6f6856e13104584dd0797ca2b2779202dc2597c6066a42e0d8fe990b0024d
);
uint256 constant BulkOrder_Typehash_Height_Four = (
0xa02eb7ff164c884e5e2c336dc85f81c6a93329d8e9adf214b32729b894de2af1
);
uint256 constant BulkOrder_Typehash_Height_Five = (
0x39c9d33c18e050dda0aeb9a8086fb16fc12d5d64536780e1da7405a800b0b9f6
);
uint256 constant BulkOrder_Typehash_Height_Six = (
0x1c19f71958cdd8f081b4c31f7caf5c010b29d12950be2fa1c95070dc47e30b55
);
uint256 constant BulkOrder_Typehash_Height_Seven = (
0xca74fab2fece9a1d58234a274220ad05ca096a92ef6a1ca1750b9d90c948955c
);
uint256 constant BulkOrder_Typehash_Height_Eight = (
0x7ff98d9d4e55d876c5cfac10b43c04039522f3ddfb0ea9bfe70c68cfb5c7cc14
);
uint256 constant BulkOrder_Typehash_Height_Nine = (
0xbed7be92d41c56f9e59ac7a6272185299b815ddfabc3f25deb51fe55fe2f9e8a
);
uint256 constant BulkOrder_Typehash_Height_Ten = (
0xd1d97d1ef5eaa37a4ee5fbf234e6f6d64eb511eb562221cd7edfbdde0848da05
);
uint256 constant BulkOrder_Typehash_Height_Eleven = (
0x896c3f349c4da741c19b37fec49ed2e44d738e775a21d9c9860a69d67a3dae53
);
uint256 constant BulkOrder_Typehash_Height_Twelve = (
0xbb98d87cc12922b83759626c5f07d72266da9702d19ffad6a514c73a89002f5f
);
uint256 constant BulkOrder_Typehash_Height_Thirteen = (
0xe6ae19322608dd1f8a8d56aab48ed9c28be489b689f4b6c91268563efc85f20e
);
uint256 constant BulkOrder_Typehash_Height_Fourteen = (
0x6b5b04cbae4fcb1a9d78e7b2dfc51a36933d023cf6e347e03d517b472a852590
);
uint256 constant BulkOrder_Typehash_Height_Fifteen = (
0xd1eb68309202b7106b891e109739dbbd334a1817fe5d6202c939e75cf5e35ca9
);
uint256 constant BulkOrder_Typehash_Height_Sixteen = (
0x1da3eed3ecef6ebaa6e5023c057ec2c75150693fd0dac5c90f4a142f9879fde8
);
uint256 constant BulkOrder_Typehash_Height_Seventeen = (
0xeee9a1392aa395c7002308119a58f2582777a75e54e0c1d5d5437bd2e8bf6222
);
uint256 constant BulkOrder_Typehash_Height_Eighteen = (
0xc3939feff011e53ab8c35ca3370aad54c5df1fc2938cd62543174fa6e7d85877
);
uint256 constant BulkOrder_Typehash_Height_Nineteen = (
0x0efca7572ac20f5ae84db0e2940674f7eca0a4726fa1060ffc2d18cef54b203d
);
uint256 constant BulkOrder_Typehash_Height_Twenty = (
0x5a4f867d3d458dabecad65f6201ceeaba0096df2d0c491cc32e6ea4e64350017
);
uint256 constant BulkOrder_Typehash_Height_TwentyOne = (
0x80987079d291feebf21c2230e69add0f283cee0b8be492ca8050b4185a2ff719
);
uint256 constant BulkOrder_Typehash_Height_TwentyTwo = (
0x3bd8cff538aba49a9c374c806d277181e9651624b3e31111bc0624574f8bca1d
);
uint256 constant BulkOrder_Typehash_Height_TwentyThree = (
0x5d6a3f098a0bc373f808c619b1bb4028208721b3c4f8d6bc8a874d659814eb76
);
uint256 constant BulkOrder_Typehash_Height_TwentyFour = (
0x1d51df90cba8de7637ca3e8fe1e3511d1dc2f23487d05dbdecb781860c21ac1c
);
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;
// Related constants used for restricted order checks on basic orders.
uint256 constant OrderFulfilled_baseDataSize = 0x160;
// uint256 constant ValidateOrder_offerDataOffset = 0x184;
// uint256 constant RatifyOrder_offerDataOffset = 0xc4;
// 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 = 0x80;
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;
uint256 constant BasicOrder_startTimeThroughZoneHash_size = 0x60;
uint256 constant ContractOrder_orderHash_offerer_shift = 0x60;
uint256 constant Counter_blockhash_shift = 0x80;
// 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_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;
uint256 constant EIP_712_PREFIX = (
0x1901000000000000000000000000000000000000000000000000000000000000
);
uint256 constant ExtraGasBuffer = 0x20;
uint256 constant CostPerWord = 0x3;
uint256 constant MemoryExpansionCoefficientShift = 0x9;
uint256 constant Create2AddressDerivation_ptr = 0x0b;
uint256 constant Create2AddressDerivation_length = 0x55;
uint256 constant MaskOverByteTwelve = (
0x0000000000000000000000ff0000000000000000000000000000000000000000
);
uint256 constant MaskOverLastTwentyBytes = (
0x000000000000000000000000ffffffffffffffffffffffffffffffffffffffff
);
uint256 constant AddressDirtyUpperBitThreshold = (
0x0000000000000000000000010000000000000000000000000000000000000000
);
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;
uint256 constant Ecrecover_precompile = 0x1;
uint256 constant Ecrecover_args_size = 0x80;
uint256 constant Signature_lower_v = 27;
// Bitmask that only gives a non-zero value if masked with a non-match selector.
uint256 constant NonMatchSelector_MagicMask = (
0x4000000000000000000000000000000000000000000000000000000000
);
// First bit indicates that a NATIVE offer items has been used and the 231st bit
// indicates that a non match selector has been called.
uint256 constant NonMatchSelector_InvalidErrorValue = (
0x4000000000000000000000000000000000000000000000000000000001
);
/**
* @dev Selector and offsets for generateOrder
*
* function generateOrder(
* address fulfiller,
* SpentItem[] calldata minimumReceived,
* SpentItem[] calldata maximumSpent,
* bytes calldata context
* )
*/
uint256 constant generateOrder_selector = 0x98919765;
uint256 constant generateOrder_selector_offset = 0x1c;
uint256 constant generateOrder_head_offset = 0x04;
uint256 constant generateOrder_minimumReceived_head_offset = 0x20;
uint256 constant generateOrder_maximumSpent_head_offset = 0x40;
uint256 constant generateOrder_context_head_offset = 0x60;
uint256 constant generateOrder_base_tail_offset = 0x80;
uint256 constant generateOrder_maximum_returndatasize = 0xffff;
uint256 constant ratifyOrder_selector = 0xf4dd92ce;
uint256 constant ratifyOrder_selector_offset = 0x1c;
uint256 constant ratifyOrder_head_offset = 0x04;
// uint256 constant ratifyOrder_offer_head_offset = 0x00;
uint256 constant ratifyOrder_consideration_head_offset = 0x20;
uint256 constant ratifyOrder_context_head_offset = 0x40;
uint256 constant ratifyOrder_orderHashes_head_offset = 0x60;
uint256 constant ratifyOrder_contractNonce_offset = 0x80;
uint256 constant ratifyOrder_base_tail_offset = 0xa0;
uint256 constant validateOrder_selector = 0x17b1f942;
uint256 constant validateOrder_selector_offset = 0x1c;
uint256 constant validateOrder_head_offset = 0x04;
uint256 constant validateOrder_zoneParameters_offset = 0x20;
// uint256 constant ZoneParameters_orderHash_offset = 0x00;
uint256 constant ZoneParameters_fulfiller_offset = 0x20;
uint256 constant ZoneParameters_offerer_offset = 0x40;
uint256 constant ZoneParameters_offer_head_offset = 0x60;
uint256 constant ZoneParameters_consideration_head_offset = 0x80;
uint256 constant ZoneParameters_extraData_head_offset = 0xa0;
uint256 constant ZoneParameters_orderHashes_head_offset = 0xc0;
uint256 constant ZoneParameters_startTime_offset = 0xe0;
uint256 constant ZoneParameters_endTime_offset = 0x100;
uint256 constant ZoneParameters_zoneHash_offset = 0x120;
uint256 constant ZoneParameters_base_tail_offset = 0x140;
uint256 constant ZoneParameters_selectorAndPointer_length = 0x24;
uint256 constant ZoneParameters_basicOrderFixedElements_length = 0x64;
// ConsiderationDecoder Constants
uint256 constant OrderParameters_head_size = 0x0160;
uint256 constant OrderParameters_totalOriginalConsiderationItems_offset = (
0x0140
);
uint256 constant AdvancedOrderPlusOrderParameters_head_size = 0x0200;
uint256 constant Order_signature_offset = 0x20;
uint256 constant Order_head_size = 0x40;
uint256 constant AdvancedOrder_fixed_segment_0 = 0x40;
uint256 constant CriteriaResolver_head_size = 0xa0;
uint256 constant CriteriaResolver_fixed_segment_0 = 0x80;
uint256 constant CriteriaResolver_criteriaProof_offset = 0x80;
uint256 constant FulfillmentComponent_mem_tail_size = 0x40;
uint256 constant FulfillmentComponent_mem_tail_size_shift = 0x6;
uint256 constant Fulfillment_head_size = 0x40;
uint256 constant Fulfillment_considerationComponents_offset = 0x20;
uint256 constant OrderComponents_OrderParameters_common_head_size = 0x0140;// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
import {ConsiderationEventsAndErrors} from "../../seaport-1.5/interfaces/ConsiderationEventsAndErrors.sol";
import {ReferenceReentrancyGuard} from "./ReferenceReentrancyGuard.sol";
/**
* @title CounterManager
* @author 0age
* @notice CounterManager contains a storage mapping and related functionality
* for retrieving and incrementing a per-offerer counter.
*/
contract ReferenceCounterManager is
ConsiderationEventsAndErrors,
ReferenceReentrancyGuard
{
// 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 in bulk
* by incrementing a counter. Note that only the offerer may increment
* the counter. Note that the counter is incremented by a large,
* quasi-random interval, which makes it infeasible to "activate"
* signed orders by incrementing the counter. This activation
* functionality can be achieved instead with restricted orders or
* contract orders.
*
* @return newCounter The new counter.
*/
function _incrementCounter() internal returns (uint256 newCounter) {
// Use second half of the previous block hash as a quasi-random number.
uint256 quasiRandomNumber = uint256(blockhash(block.number - 1)) >> 128;
// Retrieve the original counter value.
uint256 originalCounter = _counters[msg.sender];
// Increment current counter for the supplied offerer.
newCounter = quasiRandomNumber + originalCounter;
// Update the counter with the new value.
_counters[msg.sender] = newCounter;
// 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,
ReceivedItem,
SpentItem
} from "../lib/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 orderParameters The parameters of the validated order.
*/
event OrderValidated(bytes32 orderHash, OrderParameters orderParameters);
/**
* @dev Emit an event whenever one or more orders are matched using either
* matchOrders or matchAdvancedOrders.
*
* @param orderHashes The order hashes of the matched orders.
*/
event OrdersMatched(bytes32[] orderHashes);
/**
* @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.
*
* @param startTime The time at which the order becomes active.
* @param endTime The time at which the order becomes inactive.
*/
error InvalidTime(uint256 startTime, uint256 endTime);
/**
* @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 an order is validated and the length of
* the consideration array is not equal to the supplied total original
* consideration items value. This error is also thrown when contract
* orders supply a total original consideration items value that does
* not match the supplied consideration array length.
*/
error ConsiderationLengthNotEqualToTotalOriginal();
/**
* @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 native tokens are supplied as
* part of msg.value when fulfilling orders.
*/
error InsufficientNativeTokensSupplied();
/**
* @dev Revert with an error when a native token transfer reverts.
*/
error NativeTokenTransferGenericFailure(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 or when attempting to
* cancel a contract order.
*/
error CannotCancelOrder();
/**
* @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 a native token outside of matching orders.
*/
error InvalidNativeOfferItem();
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
import {ConsiderationEventsAndErrors} from "../../seaport-1.5/interfaces/ConsiderationEventsAndErrors.sol";
import {ReentrancyErrors} from "../../seaport-1.5/interfaces/ReentrancyErrors.sol";
import {_ENTERED_AND_ACCEPTING_NATIVE_TOKENS, _ENTERED, _NOT_ENTERED} from "../../seaport-1.5/lib/ConsiderationConstants.sol";
/**
* @title ReentrancyGuard
* @author 0age
* @notice ReentrancyGuard contains a storage variable and related functionality
* for protecting against reentrancy.
*/
contract ReferenceReentrancyGuard is
ConsiderationEventsAndErrors,
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 Modifier to check that the sentinel value for the reentrancy guard
* is not currently set by a previous call.
*/
modifier notEntered() {
if (_reentrancyGuard != _NOT_ENTERED) {
revert NoReentrantCalls();
}
_;
}
/**
* @dev Modifier to set the reentrancy guard sentinel value for the duration
* of the call and check if it is already set by a previous call.
*
* @param acceptNativeTokens A boolean indicating whether native tokens may
* be received during execution or not.
*/
modifier nonReentrant(bool acceptNativeTokens) {
if (_reentrancyGuard != _NOT_ENTERED) {
revert NoReentrantCalls();
}
if (acceptNativeTokens) {
_reentrancyGuard = _ENTERED_AND_ACCEPTING_NATIVE_TOKENS;
} else {
_reentrancyGuard = _ENTERED;
}
_;
_reentrancyGuard = _NOT_ENTERED;
}
/**
* @dev Internal view function to ensure that the sentinel value indicating
* native tokens may be received during execution is currently set.
*/
function _assertAcceptingNativeTokens() internal view {
// Ensure that the reentrancy guard is not currently set.
if (_reentrancyGuard != _ENTERED_AND_ACCEPTING_NATIVE_TOKENS) {
revert InvalidMsgValue(msg.value);
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
import {ConduitControllerInterface} from "../../seaport-1.5/interfaces/ConduitControllerInterface.sol";
import {ConsiderationEventsAndErrors} from "../../seaport-1.5/interfaces/ConsiderationEventsAndErrors.sol";
import {ReentrancyErrors} from "../../seaport-1.5/interfaces/ReentrancyErrors.sol";
/**
* @title ConsiderationBase
* @author 0age
* @notice ConsiderationBase contains all storage, constants, and constructor
* logic.
*/
contract ReferenceConsiderationBase is
ConsiderationEventsAndErrors,
ReentrancyErrors
{
// Declare constants for name, version, and reentrancy sentinel values.
string internal constant _NAME = "Seaport";
string internal constant _VERSION = "1.5";
uint256 internal constant _NOT_ENTERED = 1;
uint256 internal constant _ENTERED = 2;
// 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;
bytes32 internal immutable _BULK_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;
bytes32 internal immutable _CONDUIT_RUNTIME_CODE_HASH;
// Map bulk order tree height to its respective EIP-712 typehash.
mapping(uint256 => bytes32) internal _bulkOrderTypehashes;
/**
* @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,
_BULK_ORDER_TYPEHASH,
_DOMAIN_SEPARATOR
) = _deriveTypehashes();
// Store the current chainId and derive the current domain separator.
_CHAIN_ID = block.chainid;
// Set supplied conduit controller to an in-memory controller interface.
ConduitControllerInterface tempController = ConduitControllerInterface(
conduitController
);
// Assign the in-memory interface as an immutable.
_CONDUIT_CONTROLLER = tempController;
// Retrieve the conduit creation code hash from the supplied controller.
(_CONDUIT_CREATION_CODE_HASH, _CONDUIT_RUNTIME_CODE_HASH) = (
tempController.getConduitCodeHashes()
);
_bulkOrderTypehashes[1] = bytes32(
0x3ca2711d29384747a8f61d60aad3c450405f7aaff5613541dee28df2d6986d32
);
_bulkOrderTypehashes[2] = bytes32(
0xbf8e29b89f29ed9b529c154a63038ffca562f8d7cd1e2545dda53a1b582dde30
);
_bulkOrderTypehashes[3] = bytes32(
0x53c6f6856e13104584dd0797ca2b2779202dc2597c6066a42e0d8fe990b0024d
);
_bulkOrderTypehashes[4] = bytes32(
0xa02eb7ff164c884e5e2c336dc85f81c6a93329d8e9adf214b32729b894de2af1
);
_bulkOrderTypehashes[5] = bytes32(
0x39c9d33c18e050dda0aeb9a8086fb16fc12d5d64536780e1da7405a800b0b9f6
);
_bulkOrderTypehashes[6] = bytes32(
0x1c19f71958cdd8f081b4c31f7caf5c010b29d12950be2fa1c95070dc47e30b55
);
_bulkOrderTypehashes[7] = bytes32(
0xca74fab2fece9a1d58234a274220ad05ca096a92ef6a1ca1750b9d90c948955c
);
_bulkOrderTypehashes[8] = bytes32(
0x7ff98d9d4e55d876c5cfac10b43c04039522f3ddfb0ea9bfe70c68cfb5c7cc14
);
_bulkOrderTypehashes[9] = bytes32(
0xbed7be92d41c56f9e59ac7a6272185299b815ddfabc3f25deb51fe55fe2f9e8a
);
_bulkOrderTypehashes[10] = bytes32(
0xd1d97d1ef5eaa37a4ee5fbf234e6f6d64eb511eb562221cd7edfbdde0848da05
);
_bulkOrderTypehashes[11] = bytes32(
0x896c3f349c4da741c19b37fec49ed2e44d738e775a21d9c9860a69d67a3dae53
);
_bulkOrderTypehashes[12] = bytes32(
0xbb98d87cc12922b83759626c5f07d72266da9702d19ffad6a514c73a89002f5f
);
_bulkOrderTypehashes[13] = bytes32(
0xe6ae19322608dd1f8a8d56aab48ed9c28be489b689f4b6c91268563efc85f20e
);
_bulkOrderTypehashes[14] = bytes32(
0x6b5b04cbae4fcb1a9d78e7b2dfc51a36933d023cf6e347e03d517b472a852590
);
_bulkOrderTypehashes[15] = bytes32(
0xd1eb68309202b7106b891e109739dbbd334a1817fe5d6202c939e75cf5e35ca9
);
_bulkOrderTypehashes[16] = bytes32(
0x1da3eed3ecef6ebaa6e5023c057ec2c75150693fd0dac5c90f4a142f9879fde8
);
_bulkOrderTypehashes[17] = bytes32(
0xeee9a1392aa395c7002308119a58f2582777a75e54e0c1d5d5437bd2e8bf6222
);
_bulkOrderTypehashes[18] = bytes32(
0xc3939feff011e53ab8c35ca3370aad54c5df1fc2938cd62543174fa6e7d85877
);
_bulkOrderTypehashes[19] = bytes32(
0x0efca7572ac20f5ae84db0e2940674f7eca0a4726fa1060ffc2d18cef54b203d
);
_bulkOrderTypehashes[20] = bytes32(
0x5a4f867d3d458dabecad65f6201ceeaba0096df2d0c491cc32e6ea4e64350017
);
_bulkOrderTypehashes[21] = bytes32(
0x80987079d291feebf21c2230e69add0f283cee0b8be492ca8050b4185a2ff719
);
_bulkOrderTypehashes[22] = bytes32(
0x3bd8cff538aba49a9c374c806d277181e9651624b3e31111bc0624574f8bca1d
);
_bulkOrderTypehashes[23] = bytes32(
0x5d6a3f098a0bc373f808c619b1bb4028208721b3c4f8d6bc8a874d659814eb76
);
_bulkOrderTypehashes[24] = bytes32(
0x1d51df90cba8de7637ca3e8fe1e3511d1dc2f23487d05dbdecb781860c21ac1c
);
}
/**
* @dev Internal view function to derive the initial EIP-712 domain
* separator.
*
* @param _eip712DomainTypeHash The primary EIP-712 domain typehash.
* @param _nameHash The hash of the name of the contract.
* @param _versionHash The hash of the version string of the
* contract.
*
* @return domainSeparator The derived domain separator.
*/
function _deriveInitialDomainSeparator(
bytes32 _eip712DomainTypeHash,
bytes32 _nameHash,
bytes32 _versionHash
) internal view virtual returns (bytes32 domainSeparator) {
return
_deriveDomainSeparator(
_eip712DomainTypeHash,
_nameHash,
_versionHash
);
}
/**
* @dev Internal view function to derive the EIP-712 domain separator.
*
* @return The derived domain separator.
*/
function _deriveDomainSeparator(
bytes32 _eip712DomainTypeHash,
bytes32 _nameHash,
bytes32 _versionHash
) internal view virtual returns (bytes32) {
return
keccak256(
abi.encode(
_eip712DomainTypeHash,
_nameHash,
_versionHash,
block.chainid,
address(this)
)
);
}
/**
* @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.
* @return bulkOrderTypeHash
* @return domainSeparator The domain separator.
*/
function _deriveTypehashes()
internal
view
returns (
bytes32 nameHash,
bytes32 versionHash,
bytes32 eip712DomainTypehash,
bytes32 offerItemTypehash,
bytes32 considerationItemTypehash,
bytes32 orderTypehash,
bytes32 bulkOrderTypeHash,
bytes32 domainSeparator
)
{
// Derive hash of the name of the contract.
nameHash = keccak256(bytes(_NAME));
// Derive hash of the version string of the contract.
versionHash = keccak256(bytes(_VERSION));
// Construct the OfferItem type string.
bytes memory offerItemTypeString = abi.encodePacked(
"OfferItem(",
"uint8 itemType,",
"address token,",
"uint256 identifierOrCriteria,",
"uint256 startAmount,",
"uint256 endAmount",
")"
);
// Construct the ConsiderationItem type string.
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.
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.
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
)
);
// Encode the type string for the BulkOrder struct.
bytes memory bulkOrderPartialTypeString = abi.encodePacked(
"BulkOrder(OrderComponents[2][2][2][2][2][2][2] tree)"
);
// Generate the keccak256 hash of the concatenated type strings for the
// BulkOrder, considerationItem, offerItem, and orderComponents.
bulkOrderTypeHash = keccak256(
abi.encodePacked(
bulkOrderPartialTypeString,
considerationItemTypeString,
offerItemTypeString,
orderComponentsPartialTypeString
)
);
// Derive the initial domain separator using the domain typehash, the
// name hash, and the version hash.
domainSeparator = _deriveInitialDomainSeparator(
eip712DomainTypehash,
nameHash,
versionHash
);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
/**
* @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.13;
/**
* @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);
}{
"viaIR": true,
"evmVersion": "cancun",
"optimizer": {
"enabled": true,
"mode": "3"
},
"outputSelection": {
"*": {
"*": [
"abi"
]
}
},
"detectMissingLibraries": false,
"forceEVMLA": false,
"enableEraVMExtensions": true,
"libraries": {
"contracts/usdc/util/SignatureChecker.sol": {
"SignatureChecker": "0xbBB5d95A805b48E24f369127ECcDDF81e87f1A0F"
}
}
}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":"CannotCancelOrder","type":"error"},{"inputs":[],"name":"ConsiderationCriteriaResolverOutOfRange","type":"error"},{"inputs":[],"name":"ConsiderationLengthNotEqualToTotalOriginal","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":[],"name":"InexactFraction","type":"error"},{"inputs":[],"name":"InsufficientNativeTokensSupplied","type":"error"},{"inputs":[],"name":"Invalid1155BatchTransferEncoding","type":"error"},{"inputs":[],"name":"InvalidBasicOrderParameterEncoding","type":"error"},{"inputs":[{"internalType":"address","name":"conduit","type":"address"}],"name":"InvalidCallToConduit","type":"error"},{"inputs":[{"internalType":"bytes32","name":"conduitKey","type":"bytes32"},{"internalType":"address","name":"conduit","type":"address"}],"name":"InvalidConduit","type":"error"},{"inputs":[{"internalType":"bytes32","name":"orderHash","type":"bytes32"}],"name":"InvalidContractOrder","type":"error"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"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":[{"internalType":"uint256","name":"startTime","type":"uint256"},{"internalType":"uint256","name":"endTime","type":"uint256"}],"name":"InvalidTime","type":"error"},{"inputs":[{"internalType":"uint256","name":"fulfillmentIndex","type":"uint256"}],"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"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"NativeTokenTransferGenericFailure","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":[{"internalType":"enum Side","name":"side","type":"uint8"}],"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":[{"internalType":"uint256","name":"orderIndex","type":"uint256"},{"internalType":"uint256","name":"considerationIndex","type":"uint256"}],"name":"UnresolvedConsiderationCriteria","type":"error"},{"inputs":[{"internalType":"uint256","name":"orderIndex","type":"uint256"},{"internalType":"uint256","name":"offerIndex","type":"uint256"}],"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"},{"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"}],"indexed":false,"internalType":"struct OrderParameters","name":"orderParameters","type":"tuple"}],"name":"OrderValidated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32[]","name":"orderHashes","type":"bytes32[]"}],"name":"OrdersMatched","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":[{"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_efficient_6GL6yc","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":"contractOfferer","type":"address"}],"name":"getContractOffererNonce","outputs":[{"internalType":"uint256","name":"nonce","type":"uint256"}],"stateMutability":"view","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[]"},{"internalType":"address","name":"recipient","type":"address"}],"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"},{"stateMutability":"payable","type":"receive"}]Contract Creation Code
3cda3351000000000000000000000000000000000000000000000000000000000000000001001b81c1e93d27bfd46b5fd711a4bc8824d77ea0e6c61a8b3e4bb8418ec53c000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000200000000000000000000000001972ddfa941670a9f5fa2a0094f4490347b99d7b
Deployed Bytecode
0x000400000000000200220000000000020000000003010019000000600330027000001a98043001970003000000410355000200000001035500001a980030019d0000000100200190000000400000c13d000003a002000039000000400020043f000000040040008c000001130000413d000000000301043b000000e00330027000001aea0030009c0000011b0000a13d00001aeb0030009c0000013d0000a13d00001aec0030009c000002140000a13d00001aed0030009c000003570000613d00001aee0030009c0000034c0000613d00001aef0030009c00000ca20000c13d000000240040008c00000ca20000413d0000000003000416000000000003004b00000ca20000c13d0000000403100370000000000303043b000200000003001d00001ac20030009c00000ca20000213d00000002030000290000002303300039000000000043004b00000ca20000813d00000002030000290000000403300039000000000131034f000000000101043b000100000001001d00001ac20010009c00000ca20000213d0000000201000029000c00240010003d000000010100002900000005011002100000000c01100029000000000041004b00000ca20000213d0000000103000039000000000103041a000000010010008c000004f00000c13d000000010000006b000006a80000c13d0000000000320435000003520000013d0000020003000039000000400030043f0000000002000416000000000002004b00000ca20000c13d0000001f0240003900001a99022001970000020002200039000000400020043f0000001f0540018f00001a9a064001980000020002600039000000520000613d000000000701034f000000007807043c0000000003830436000000000023004b0000004e0000c13d000000000005004b0000005f0000613d000000000161034f0000000303500210000000000502043300000000053501cf000000000535022f000000000101043b0000010003300089000000000131022f00000000013101cf000000000151019f0000000000120435000000200040008c00000ca20000413d000002000300043d00001a9b0030009c00000ca20000213d000000400100043d00001a9c0010009c0000010d0000213d0000004002100039000000400020043f0000000702000039000000000121043600001a9d02000041000000000021043500001a980010009c00001a98010080410000004001100210000000000200041400001a980020009c00001a9802008041000000c002200210000000000121019f00001a9e011001c70000801002000039001900000003001d6a5a6a550000040f000000010020019000000ca20000613d000000000201043b000000400100043d00001a9c0010009c0000010d0000213d001800000002001d0000004002100039000000400020043f0000000302000039000000000121043600001a9f02000041000000000021043500001a980010009c00001a98010080410000004001100210000000000200041400001a980020009c00001a9802008041000000c002200210000000000121019f00001aa0011001c700008010020000396a5a6a550000040f000000010020019000000ca20000613d000000000701043b000000400900043d000000200890003900001aa10100004100000000001804350000002a0290003900001aa2010000410000000000120435000000390390003900001aa3020000410000000000230435000000470390003900001aa4040000410000000000430435000000640390003900001aa5050000410000000000530435000000780390003900001aa6060000410000000000630435000000890690003900001aa70300004100000000003604350000006a06000039000000000069043500001aa80090009c0000010d0000213d000000a00b9000390000004000b0043f000000c00a90003900001aa90600004100000000006a0435000000d2069000390000000000160435000000e1019000390000000000210435000000ef0190003900000000004104350000010c019000390000000000510435000001200190003900001aaa020000410000000000210435000001320190003900001aab02000041000000000021043500000143019000390000000000310435000000840100003900000000001b043500001aac0090009c0000010d0000213d0000016006900039000000400060043f000001df0190003900001aad020000410000000000210435000001e10190003900001aae020000410000000000210435000001f10190003900001aaf020000410000000000210435000002030190003900001ab0020000410000000000210435000002130190003900001ab1020000410000000000210435000001800590003900001ab2010000410000000000150435000001900190003900001ab3020000410000000000210435000002240190003900001ab4020000410000000000210435000001a00190003900001ab5020000410000000000210435000002310190003900001ab6020000410000000000210435000001ad0190003900001ab7020000410000000000210435000002440190003900001ab8020000410000000000210435000001bf0190003900001ab9020000410000000000210435000002530190003900001aa7020000410000000000210435000000d401000039000000000016043500001aba0090009c0000010d0000213d000002800190003900001abb0300004100000000003104350000028d0390003900001abc040000410000000000430435000002990390003900001abd040000410000000000430435000002a80390003900001abe040000410000000000430435000002b80390003900001abf040000410000000000430435000002d103900039000000000023043500000260029000390000005203000039000000000032043500001ac00090009c000005440000a13d00001b0801000041000000000010043f0000004101000039000000040010043f00001b090100004100006a5c00010430000000000004004b00000ca20000c13d0000000101000039000000000101041a000000030010008c000001370000c13d000000000100001900006a5b0001042e00001af70030009c0000017f0000213d00001afd0030009c0000027a0000213d000000000003004b0000034c0000613d00001b000030009c00000ca20000c13d0000000001000416000000000001004b00000ca20000c13d000003e001000039000000400010043f0000000701000039000003a00010043f00001a9d01000041000003c00010043f0000002001000039000003e00010043f000003a00100003900000400020000396a5a0fc00000040f000003e00110008a00001a980010009c00001a9801008041000000600110021000001b1e011001c700006a5b0001042e00001ae801000041000003a00010043f0000000001000416000003a40010043f00001ae90100004100006a5c0001043000001af20030009c000002990000213d00001af50030009c000003850000613d00001af60030009c00000ca20000c13d000000440040008c00000ca20000413d0000000402100370000000000302043b00001ac20030009c00000ca20000213d000000000534004900001b030050009c00000ca20000213d000000440050008c00000ca20000413d0000000402300039000000000421034f000000000404043b000001630550008a00001b010640019700001b0107500197000000000876013f000000000076004b000000000600001900001b0106004041000000000054004b000000000500001900001b010500804100001b010080009c000000000605c019000000000006004b00000ca20000c13d00000000034300190000008403300039000000000131034f000000000101043b000000040010008c00000ca20000213d0000000104000039000000000304041a000000010030008c000004f00000c13d000000040010008c00000002010000390000000301006039000000000014041b00000000010200196a5a43100000040f001900000001001d000000400100043d001800000001001d6a5a0fdd0000040f0000001802000029000000000002043500000024010000390000000201100367000000000301043b000000000400041100000019010000296a5a44b10000040f0000000102000039000000000022041b000000400100043d0000053e0000013d00001af80030009c000002fe0000213d00001afb0030009c000003980000613d00001afc0030009c00000ca20000c13d000000e40040008c00000ca20000413d0000000401100370000000000101043b00001ac20010009c00000ca20000213d000000040110003900000000020400196a5a12300000040f001900000001001d00000002010003670000002402100370000000000402043b00001ac20040009c00000ca20000213d0000002305400039000000000200003100001b010320019700001b0106500197000000000736013f000000000036004b000000000600001900001b0106004041000000000025004b000000000500001900001b010500804100001b010070009c000000000605c019000000000006004b00000ca20000c13d0000000405400039000000000551034f000000000505043b001800000005001d00001ac20050009c00000ca20000213d001700240040003d000000180400002900000005044002100000001704400029000000000024004b00000ca20000213d0000004404100370000000000404043b00001ac20040009c00000ca20000213d0000002305400039000000000025004b000000000600001900001b010600804100001b0105500197000000000735013f000000000035004b000000000500001900001b010500404100001b010070009c000000000506c019000000000005004b00000ca20000c13d0000000405400039000000000551034f000000000505043b001600000005001d00001ac20050009c00000ca20000213d001500240040003d000000160400002900000005044002100000001504400029000000000024004b00000ca20000213d0000006404100370000000000404043b00001ac20040009c00000ca20000213d0000002305400039000000000025004b000000000600001900001b010600804100001b0105500197000000000735013f000000000035004b000000000300001900001b010300404100001b010070009c000000000306c019000000000003004b00000ca20000c13d0000000403400039000000000331034f000000000303043b001400000003001d00001ac20030009c00000ca20000213d001300240040003d000000140300002900000005033002100000001303300029000000000023004b00000ca20000213d000000a401100370000000000101043b001200000001001d00001a9b0010009c00000ca20000213d0000000101000039000000000101041a000000010010008c00000cb00000c13d000000120100002900101a9b0010019b00000003010000390000000102000039000000000012041b00000019010000296a5a25230000040f001100000001001d000000100000006b000001fe0000c13d0000000001000411001200000001001d00000002010003670000008402100370000000000202043b001000000002001d000000c401100370000000000101043b000f00000001001d0000000003000031000000170100002900000018020000296a5a22a30000040f0000000003010019000000190100002900000011020000290000001504000029000000160500002900000013060000290000001407000029000000100800002900000012090000290000000f0a000029000002f30000013d00001af00030009c0000044a0000613d00001af10030009c00000ca20000c13d000000840040008c00000ca20000413d0000000401100370000000000101043b00001ac20010009c00000ca20000213d000000040110003900000000020400196a5a12300000040f001900000001001d00000002040003670000002401400370000000000101043b00001ac20010009c00000ca20000213d0000002302100039000000000300003100001b010530019700001b0106200197000000000756013f000000000056004b000000000600001900001b0106004041000000000032004b000000000200001900001b010200804100001b010070009c000000000602c019000000000006004b00000ca20000c13d0000000402100039000000000224034f000000000202043b00001ac20020009c00000ca20000213d000000240110003900000005062002100000000006160019000000000036004b00000ca20000213d0000004406400370000000000606043b00001ac20060009c00000ca20000213d0000002307600039000000000037004b000000000800001900001b010800804100001b0107700197000000000957013f000000000057004b000000000500001900001b010500404100001b010090009c000000000508c019000000000005004b00000ca20000c13d0000000405600039000000000554034f000000000505043b001800000005001d00001ac20050009c00000ca20000213d001700240060003d000000180500002900000005055002100000001705500029000000000035004b00000ca20000213d0000006404400370000000000404043b001600000004001d00001a9b0040009c00000ca20000213d0000000104000039000000000404041a000000010040008c00000cb00000c13d00000003040000390000000105000039000000000045041b000000160000006b0000026d0000c13d0000000004000411001600000004001d6a5a22a30000040f000000000201001900000019010000290000001703000029000000180400002900000016050000296a5a35750000040f0000000102000039000000000022041b000000400300043d001900000003001d0000002002000039000003400000013d00001afe0030009c000004550000613d00001aff0030009c00000ca20000c13d0000000001000416000000000001004b00000ca20000c13d0000000101000039000000000101041a000000010010008c000004f00000c13d00001b19010000410000000000100443000000000100041400001a980010009c00001a9801008041000000c00110021000001ac7011001c70000800b020000396a5a6a550000040f0000000100200190000009e00000613d000000000101043b000000000001004b000004f40000c13d00001b0801000041000000000010043f0000001101000039000000040010043f00001b090100004100006a5c0001043000001af30030009c000004720000613d00001af40030009c00000ca20000c13d000000a40040008c00000ca20000413d0000000402100370000000000302043b00001ac20030009c00000ca20000213d0000002302300039000000000042004b00000ca20000813d0000000402300039000000000221034f000000000202043b00001ac20020009c00000ca20000213d000000240330003900000005052002100000000005350019000000000045004b00000ca20000213d0000002405100370000000000505043b00001ac20050009c00000ca20000213d0000002306500039000000000046004b00000ca20000813d0000000406500039000000000661034f000000000606043b001900000006001d00001ac20060009c00000ca20000213d001800240050003d000000190500002900000005055002100000001805500029000000000045004b00000ca20000213d0000004405100370000000000505043b00001ac20050009c00000ca20000213d0000002306500039000000000046004b00000ca20000813d0000000406500039000000000161034f000000000101043b001700000001001d00001ac20010009c00000ca20000213d001600240050003d000000170100002900000005011002100000001601100029000000000041004b00000ca20000213d00000001010000390000000004010019000000000101041a000000010010008c000004f00000c13d0000000301000039000000000014041b00000000010300196a5a33630000040f001500000001001d6a5a25230000040f001400000001001d000000400100043d001300000001001d6a5a0fdd0000040f0000001303000029000000000003043500000002010003670000006402100370000000000802043b0000008401100370000000000a01043b00000000090004110000001501000029000000140200002900000018040000290000001905000029000000160600002900000017070000296a5a26ad0000040f0000000103000039000000000033041b00000000030100190000000004020019000000400100043d001900000001001d000000000203001900000000030400196a5a14400000040f000003420000013d00001af90030009c000004cc0000613d00001afa0030009c00000ca20000c13d000000440040008c00000ca20000413d0000000402100370000000000302043b00001ac20030009c00000ca20000213d0000002302300039000000000042004b00000ca20000813d0000000402300039000000000221034f000000000202043b00001ac20020009c00000ca20000213d000000240330003900000005052002100000000005350019000000000045004b00000ca20000213d0000002405100370000000000505043b00001ac20050009c00000ca20000213d0000002306500039000000000046004b00000ca20000813d0000000406500039000000000161034f000000000101043b001900000001001d00001ac20010009c00000ca20000213d001800240050003d000000190100002900000005011002100000001801100029000000000041004b00000ca20000213d0000000104000039000000000104041a000000010010008c000004f00000c13d0000000301000039000000000014041b00000000010300196a5a33630000040f001700000001001d000000400100043d001600000001001d6a5a0fdd0000040f0000001602000029000000000002043500000000050004110000001701000029000000180300002900000019040000296a5a35750000040f0000000102000039000000000022041b0000002002000039000000400300043d001900000003001d00000000022304366a5a14100000040f0000001902000029000000000121004900001a980010009c00001a9801008041000000600110021000001a980020009c00001a98020080410000004002200210000000000121019f00006a5b0001042e00000000010400196a5a0fae0000040f6a5a14830000040f0000000101000039000000400200043d000000000012043500001a980020009c00001a9802008041000000400120021000001b10011001c700006a5b0001042e0000000001000416000000000001004b00000ca20000c13d000003e001000039000000400010043f0000000301000039000003a00010043f00001a9f01000041000003c00010043f6a5a5b730000040f0000006002000039000000400300043d001900000003001d0000000002230436001800000002001d001700000001001d000003a00100003900000060023000396a5a0fc00000040f0000001802000029000000170300002900000000003204350000000002000412001b00000002001d001a01200000003d001800000001001d0000800501000039000000440300003900000000040004150000001b0440008a000000050440021000001b04020000416a5a6a320000040f00001a9b01100197000000190300002900000040023000390000000000120435000000180130006900001a980010009c00001a9801008041000000600110021000001a980030009c00001a98030080410000004002300210000000000121019f00006a5b0001042e000000240040008c00000ca20000413d0000000002000416000000000002004b00000ca20000c13d0000000401100370000000000101043b00001a9b0010009c00000ca20000213d000000000010043f0000000401000039000000200010043f000000400200003900000000010000196a5a6a1d0000040f000000000101041a000003a00010043f00001b110100004100006a5b0001042e000000240040008c00000ca20000413d0000000002000416000000000002004b00000ca20000c13d0000000402100370000000000202043b00001ac20020009c00000ca20000213d000000000324004900001b030030009c00000ca20000213d000001640030008c00000ca20000413d0000000403200039000000000531034f000000000505043b001900000005001d00001a9b0050009c00000ca20000213d0000002005300039000000000651034f000000000606043b001800000006001d00001a9b0060009c00000ca20000213d00000000063400490000002007500039000000000571034f000000000805043b0000001f0560008a00001b010650019700001b0109800197000000000a69013f000000000069004b000000000900001900001b0109004041000000000058004b000000000b00001900001b010b00804100001b0100a0009c00000000090bc019000000000009004b00000ca20000c13d0000000008380019000000000981034f000000000909043b001700000009001d00001ac20090009c00000ca20000213d000000a00900008a00000017099000b90000000009490019000000200c80003900001b010890019700001b010ac00197000000000b8a013f00000000008a004b000000000800001900001b010800404100160000000c001d00000000009c004b000000000900001900001b010900204100001b0100b0009c000000000809c019000000000008004b00000ca20000c13d0000002007700039000000000871034f000000000808043b00001b0109800197000000000a69013f000000000069004b000000000600001900001b0106004041000000000058004b000000000500001900001b010500804100001b0100a0009c000000000605c019000000000006004b00000ca20000c13d0000000005380019000000000651034f000000000606043b001500000006001d00001ac20060009c00000ca20000213d000000c00600008a00000015066000b90000000004460019000000200950003900001b010540019700001b0106900197000000000856013f000000000056004b000000000500001900001b0105004041001400000009001d000000000049004b000000000400001900001b010400204100001b010080009c000000000504c019000000000005004b00000ca20000c13d001200200070003d0000001201100360000000000101043b001100000001001d000000040010008c00000ca20000213d000000640220003900000000010300196a5a22780000040f001000000001001d000000400100043d001300000001001d6a5a0fd20000040f0000001303000029000000200130003900000018020000290000000000210435000000190100002900000000001304350000000003000031000000160100002900000017020000296a5a0fe80000040f0000001302000029000000400220003900000000001204350000000003000031000000140100002900000015020000296a5a10330000040f000000130500002900000080025000390000001103000029000000000032043500000060025000390000000000120435000000120400002900000020014000390000000201100367000000000101043b000000a003500039000000000013043500000040014000390000000201100367000000000101043b000000c003500039000000000013043500000060014000390000000201100367000000000101043b000000e003500039000000000013043500000080014000390000000201100367000000000101043b00000100035000390000000000130435000000a0014000390000000201100367000000000101043b000001200350003900000000001304350000014003500039000000000105001900000010050000290000000000530435000000c0034000390000000202300367000000000202043b6a5a23360000040f000003500000013d000000240040008c00000ca20000413d0000000002000416000000000002004b00000ca20000c13d0000000401100370000000000101043b00001a9b0010009c00000ca20000213d6a5a23240000040f000003500000013d000000240040008c00000ca20000413d0000000002000416000000000002004b00000ca20000c13d0000000401100370000000000101043b000000000010043f0000000301000039000000200010043f000000400200003900000000010000196a5a6a1d0000040f000000000101041a000000ff001001900000000002000039000000010200c039000003a00020043f0000ff00001001900000000002000039000000010200c039000003c00020043f000000100210027000001b1302200197000003e00020043f0000008801100270000004000010043f00001b1d0100004100006a5b0001042e000000840040008c00000ca20000413d0000000402100370000000000302043b00001ac20030009c00000ca20000213d000000000534004900001b030050009c00000ca20000213d000000a40050008c00000ca20000413d0000002402100370000000000202043b00001ac20020009c00000ca20000213d0000002306200039000000000046004b00000ca20000813d0000000406200039000000000661034f000000000606043b001900000006001d00001ac20060009c00000ca20000213d001800240020003d000000190200002900000005022002100000001802200029000000000042004b00000ca20000213d0000006402100370000000000202043b001700000002001d00001a9b0020009c00000ca20000213d0000000402300039000000000621034f000000000606043b000001630550008a00001b010760019700001b0108500197000000000987013f000000000087004b000000000700001900001b0107004041000000000056004b000000000500001900001b010500804100001b010090009c000000000705c019000000000007004b00000ca20000c13d00000000036300190000008403300039000000000131034f000000000101043b000000040010008c00000ca20000213d0000000103000039000000000303041a000000010030008c000004f00000c13d000000040010008c000000020100003900000003010060390000000103000039000000000013041b000000170000006b000004b90000c13d0000000001000411001700000001001d000000000102001900000000020400196a5a10850000040f00000044020000390000000202200367000000000202043b001600000002001d001500000001001d0000000003000031000000180100002900000019020000296a5a22a30000040f00000000020100190000001501000029000000160300002900000017040000296a5a44b10000040f00000001020000390000017c0000013d000000240040008c00000ca20000413d0000000002000416000000000002004b00000ca20000c13d0000000402100370000000000202043b001400000002001d00001ac20020009c00000ca20000213d00000014020000290000002302200039000000000042004b00000ca20000813d00000014020000290000000402200039000000000121034f000000000101043b001300000001001d00001ac20010009c00000ca20000213d0000001401000029000000240e100039000000130100002900000005011002100000000001e10019000000000041004b00000ca20000213d0000000102000039000000000102041a000000010010008c000004f00000c13d000000130000006b000009e10000c13d000003a0010000390000053e0000013d00001b1701000041000003a00010043f00001b180100004100006a5c00010430001900000001001d0000000001000411000000000010043f0000000201000039000000200010043f000000000100041400001a980010009c00001a9801008041000000c00110021000001b0b011001c700008010020000396a5a6a550000040f000000010020019000000ca20000613d0000001902000029000000010220008a000000000101043b000000000101041a001900000001001d00001b1a0100004100000000001004430000000400200443000000000100041400001a980010009c00001a9801008041000000c00110021000001b1b011001c70000800b020000396a5a6a550000040f0000000100200190000009e00000613d000000000101043b0000008001100270001800000001001d000000190010002a000002930000413d0000000001000411000000000010043f0000000201000039000000200010043f000000000100041400001a980010009c00001a9801008041000000c00110021000001b0b011001c700008010020000396a5a6a550000040f000000010020019000000ca20000613d00000018030000290000001902300029000000000101043b000000000021041b000000400100043d001900000002001d000000000021043500001a980010009c00001a98010080410000004001100210000000000200041400001a980020009c00001a9802008041000000c002200210000000000112019f00001b0d011001c70000800d02000039000000020300003900001b1c0400004100000000050004116a5a6a500000040f000000010020019000000ca20000613d000000400100043d0000001902000029000000000021043500001a980010009c00001a9801008041000000400110021000001b10011001c700006a5b0001042e00140000000b001d001300000006001d001100000005001d00150000000a001d001600000008001d001000000007001d001700000009001d000002e003900039001200000003001d000000400030043f00001a980010009c00001a98010080410000004001100210000000000202043300001a980020009c00001a98020080410000006002200210000000000112019f000000000200041400001a980020009c00001a9802008041000000c002200210000000000112019f00001ac1011001c700008010020000396a5a6a550000040f000000010020019000000ca20000613d000000160200002900001a980020009c00001a980200804100000040022002100000001703000029000000000303043300001a980030009c00001a98030080410000006003300210000000000223019f000000000101043b000f00000001001d000000000100041400001a980010009c00001a9801008041000000c001100210000000000121019f00001ac1011001c700008010020000396a5a6a550000040f000000010020019000000ca20000613d000000150200002900001a980020009c00001a980200804100000040022002100000001403000029000000000303043300001a980030009c00001a98030080410000006003300210000000000223019f000000000101043b000e00000001001d000000000100041400001a980010009c00001a9801008041000000c001100210000000000121019f00001ac1011001c700008010020000396a5a6a550000040f000000010020019000000ca20000613d00000017020000290000030002200039000000000101043b000d00000001001d00000013010000290000000001010433000000000001004b00000011060000290000059d0000613d000000000300001900000000042300190000000005630019000000000505043300000000005404350000002003300039000000000013004b000005960000413d0000000001210019000000000001043500000014030000290000000003030433000000000003004b0000001507000029000005ac0000613d000000000400001900000000051400190000000006740019000000000606043300000000006504350000002004400039000000000034004b000005a50000413d0000000001130019000000000001043500000017030000290000000003030433000000000003004b0000001607000029000005bb0000613d000000000400001900000000051400190000000006740019000000000606043300000000006504350000002004400039000000000034004b000005b40000413d00000000011300190000000000010435000000130110006a000001a00310008a00000012040000290000000000340435000001610110008a00001b1f031001970000000001430019000000000031004b0000000003000039000000010300403900001ac20010009c0000010d0000213d00000001003001900000010d0000c13d000000400010043f00001a980020009c00001a980200804100000040012002100000001202000029000000000202043300001a980020009c00001a98020080410000006002200210000000000112019f000000000200041400001a980020009c00001a9802008041000000c002200210000000000112019f00001ac1011001c700008010020000396a5a6a550000040f000000010020019000000ca20000613d000000000101043b001200000001001d000000400300043d000000400130003900001ac3020000410000000000210435000000200430003900001ac40100004100000000001404350000003401000039000000000013043500001ac50030009c0000010d0000213d0000006001300039000000400010043f00000080023000390000000005030433000000000005004b000005fa0000613d000000000600001900000000072600190000000008460019000000000808043300000000008704350000002006600039000000000056004b000005f30000413d0000000004250019000000000004043500000014050000290000000005050433000000000005004b0000001509000029000006090000613d000000000600001900000000074600190000000008960019000000000808043300000000008704350000002006600039000000000056004b000006020000413d0000000004450019000000000004043500000017050000290000000005050433000000000005004b0000001609000029000006180000613d000000000600001900000000074600190000000008960019000000000808043300000000008704350000002006600039000000000056004b000006110000413d0000000004450019000000000004043500000013050000290000000005050433000000000005004b0000001109000029000006270000613d000000000600001900000000074600190000000008960019000000000808043300000000008704350000002006600039000000000056004b000006200000413d000000000445001900000000000404350000000003340049000000800430008a0000000000410435000000410330008a00001b1f043001970000000003140019000000000043004b0000000004000039000000010400403900001ac20030009c0000010d0000213d00000001004001900000010d0000c13d000000400030043f00001a980020009c00001a98020080410000004002200210000000000101043300001a980010009c00001a98010080410000006001100210000000000121019f000000000200041400001a980020009c00001a9802008041000000c002200210000000000112019f00001ac1011001c700008010020000396a5a6a550000040f000000010020019000000ca20000613d000000000101043b001500000001001d000000400300043d000000600130003900000010020000290000000000210435000000400130003900000018020000290000000000210435001700000003001d00000020023000390000000f01000029001600000002001d000000000012043500001ac6010000410000000000100443000000000100041400001a980010009c00001a9801008041000000c00110021000001ac7011001c70000800b020000396a5a6a550000040f0000000100200190000009e00000613d000000000301043b0000001704000029000000a001400039000000000200041000000000002104350000008001400039001400000003001d0000000000310435000000a001000039000000000014043500001ac80040009c0000010d0000213d0000001702000029000000c001200039000000400010043f000000160100002900001a980010009c00001a98010080410000004001100210000000000202043300001a980020009c00001a98020080410000006002200210000000000112019f000000000200041400001a980020009c00001a9802008041000000c002200210000000000112019f00001ac1011001c700008010020000396a5a6a550000040f0000001903000029000000010020019000000ca20000613d00001a9b02300197000000000101043b000001800010043f002201400000003d0000001501000029000001400010043f0000001201000029000001200010043f0000000d01000029000001000010043f0000000e01000029000000e00010043f0000000f01000029000000c00010043f0000001001000029000000a00010043f0000001801000029000000800010043f002101600000003d0000001401000029000001600010043f000001a00020043f00001ac901000041000000400300043d001900000003001d0000000001130436001800000001001d0000000001000414000000040020008c00000ccf0000c13d0000000103000031000000400030008c0000004004000039000000000403401900000cfa0000013d0000000002000019000b00000002001d00000005012002100000000c021000290000000201000367000000000221034f000000000302043b0000000002000031000000020420006a000001830440008a00001b010540019700001b0106300197000000000756013f000000000056004b000000000500001900001b0105004041000000000043004b000000000400001900001b010400804100001b010070009c000000000504c019000000000005004b00000ca20000c13d0000000c03300029000000000431034f000000000404043b000e00000004001d00001a9b0040009c00000ca20000213d0000002004300039000000000541034f000000000505043b000d00000005001d00001a9b0050009c00000ca20000213d0000006005400039000000000451034f000000000404043b000000050040008c00000ca20000813d000000040040008c00000cbb0000613d00000000060004110000000e0060006c000006d70000613d0000000d0060006c00000cbb0000c13d0000000006320049000000400950008a000000000591034f000000000705043b0000001f0560008a00001b010650019700001b0108700197000000000a68013f000000000068004b000000000800001900001b0108004041000000000057004b000000000b00001900001b010b00804100001b0100a0009c00000000080bc019000000000008004b00000ca20000c13d0000000007370019000000000871034f000000000808043b00001ac20080009c00000ca20000213d00001b200a8000d1000000000a2a0019000000200770003900001b010ba0019700001b010c700197000000000dbc013f0000000000bc004b000000000b00001900001b010b0040410000000000a7004b000000000a00001900001b010a00204100001b0100d0009c000000000b0ac01900000000000b004b00000ca20000c13d0000002009900039000000000991034f000000000909043b00001b010a900197000000000b6a013f00000000006a004b000000000600001900001b0106004041000000000059004b000000000500001900001b010500804100001b0100b0009c000000000605c019000000000006004b00000ca20000c13d0000000006390019000000000561034f000000000505043b00001ac20050009c00000ca20000213d00001b21095000d10000000009290019000000200660003900001b010a90019700001b010b600197000000000cab013f0000000000ab004b000000000a00001900001b010a004041000000000096004b000000000900001900001b010900204100001b0100c0009c000000000a09c01900000000000a004b00000ca20000c13d000000400900043d000f00000009001d00001aac0090009c0000010d0000213d0000000f0a0000290000016009a00039000000400090043f0000000e09000029000000000a9a04360000000d09000029000a0000000a001d00000000009a043500000005098002100000003f0990003900001b020a900197000000400900043d000000000aa9001900000000009a004b000000000b000039000000010b00403900001ac200a0009c0000010d0000213d0000000100b001900000010d0000c13d0000004000a0043f0000000000890435000000a0088000c90000000008780019000000000028004b00000ca20000213d000000000078004b0000076c0000a13d000000000a090019000000000b72004900001b0300b0009c00000ca20000213d000000a000b0008c00000ca20000413d000000400b00043d00001aa800b0009c0000010d0000213d000000a00cb000390000004000c0043f000000000c71034f000000000c0c043b0000000500c0008c00000ca20000213d000000000dcb0436000000200c700039000000000ec1034f000000000e0e043b00001a9b00e0009c00000ca20000213d000000200aa000390000000000ed0435000000200dc00039000000000dd1034f000000000d0d043b000000400eb000390000000000de0435000000400dc00039000000000dd1034f000000000d0d043b000000600eb000390000000000de0435000000600cc00039000000000cc1034f000000000c0c043b000000800db000390000000000cd04350000000000ba0435000000a007700039000000000087004b000007430000413d0000000f070000290000004007700039001600000007001d000000000097043500000005075002100000003f0770003900001b0208700197000000400700043d0000000008870019000000000078004b0000000009000039000000010900403900001ac20080009c0000010d0000213d00000001009001900000010d0000c13d000000400080043f0000000000570435000000c0085000c90000000008680019000000000028004b00000ca20000213d000000000068004b000007b50000a13d0000000009070019000000000a62004900001b0300a0009c00000ca20000213d000000c000a0008c00000ca20000413d000000400a00043d00001ac800a0009c0000010d0000213d000000c00ba000390000004000b0043f000000000b61034f000000000b0b043b0000000500b0008c00000ca20000213d000000000cba0436000000200b600039000000000db1034f000000000d0d043b00001a9b00d0009c00000ca20000213d0000000000dc0435000000200cb00039000000000cc1034f000000000c0c043b000000400da000390000000000cd0435000000400cb00039000000000cc1034f000000000c0c043b000000600da000390000000000cd0435000000600cb00039000000000cc1034f000000000c0c043b000000800da000390000000000cd0435000000800bb00039000000000bb1034f000000000b0b043b00001a9b00b0009c00000ca20000213d0000002009900039000000a00ca000390000000000bc04350000000000a90435000000c006600039000000000086004b000007850000413d0000000f060000290000006006600039001000000006001d0000000000760435000000040040008c00000caa0000213d0000000f070000290000008006700039000900000006001d0000000000460435000000a004300039000000000441034f000000000404043b000000a006700039000800000006001d0000000000460435000000c004300039000000000441034f000000000404043b000000c006700039000700000006001d0000000000460435000000e004300039000000000441034f000000000404043b000000e006700039000600000006001d00000000004604350000012004300039000000000441034f0000010006300039000000000661034f0000014003300039000000000331034f000000000606043b0000010008700039000500000008001d0000000000680435000000000404043b0000014006700039001500000006001d00000000005604350000012005700039000400000005001d0000000000450435000000000303043b000300000003001d00000016030000290000000003030433000000000403043300001ac20040009c0000010d0000213d00000005034002100000003f0530003900001b0205500197000000400700043d0000000005570019000000000075004b0000000006000039000000010600403900001ac20050009c0000010d0000213d00000001006001900000010d0000c13d000000400050043f0000000004470436001300000004001d000000000121034f000000000003004b000008020000613d00000013050000290000000002350019000000000401034f000000004604043c0000000005650436000000000025004b000007fe0000c13d0000001f003001900000001502000029000000000302043300001ac20030009c0000010d0000213d00000005023002100000003f0420003900001b0204400197000000400600043d0000000004460019000000000064004b0000000005000039000000010500403900001ac20040009c0000010d0000213d00000001005001900000010d0000c13d000000400040043f0000000003360436001200000003001d000000000002004b0000081e0000613d00000012040000290000000003240019000000001501043c0000000004540436000000000034004b0000081a0000c13d001900000007001d001400000006001d0000001f0020019000001b040100004100000000001004430000000001000412000000040010044300000060010000390000002400100443000000000100041400001a980010009c00001a9801008041000000c00110021000001b05011001c700008005020000396a5a6a550000040f0000000100200190000009e00000613d000000000101043b001100000001001d000000160100002900000000010104330000000002010433000000000002004b0000087e0000613d000000000400001900000005054002100000000001510019000000200110003900000000010104330000000032010434000000050020008c00000caa0000213d001700000005001d001800000004001d0000000003030433000000400410003900000000040404330000006005100039000000000505043300000080011000390000000006010433000000400100043d000000c0071000390000000000670435000000a0061000390000000000560435000000800510003900000000004504350000004004100039000000000024043500001a9b0230019700000060031000390000000000230435000000200210003900000011030000290000000000320435000000c003000039000000000031043500001b060010009c0000010d0000213d000000e003100039000000400030043f00001a980020009c00001a98020080410000004002200210000000000101043300001a980010009c00001a98010080410000006001100210000000000121019f000000000200041400001a980020009c00001a9802008041000000c002200210000000000112019f00001ac1011001c700008010020000396a5a6a550000040f000000010020019000000ca20000613d000000190200002900000000020204330000001804000029000000000042004b00000ca40000a13d00000017030000290000001302300029000000000101043b00000000001204350000000104400039000000160100002900000000010104330000000002010433000000000024004b000008380000413d00001b040100004100000000001004430000000001000412000000040010044300000080010000390000002400100443000000000100041400001a980010009c00001a9801008041000000c00110021000001b05011001c700008005020000396a5a6a550000040f0000000100200190000009e00000613d000000000101043b001600000001001d00000015010000290000000001010433000000000001004b0000001907000029000008e50000613d0000000004000019000000100100002900000000010104330000000002010433000000000042004b00000ca40000a13d00000005054002100000000001150019000000200110003900000000010104330000000032010434000000050020008c00000caa0000213d001700000005001d001800000004001d0000000003030433000000a0041000390000000004040433000000400510003900000000050504330000006006100039000000000606043300000080011000390000000007010433000000400100043d000000c0081000390000000000780435000000a0071000390000000000670435000000800610003900000000005604350000004005100039000000000025043500001a9b02400197000000e004100039000000000024043500001a9b0230019700000060031000390000000000230435000000200210003900000016030000290000000000320435000000e003000039000000000031043500001b070010009c0000010d0000213d0000010003100039000000400030043f00001a980020009c00001a98020080410000004002200210000000000101043300001a980010009c00001a98010080410000006001100210000000000121019f000000000200041400001a980020009c00001a9802008041000000c002200210000000000112019f00001ac1011001c700008010020000396a5a6a550000040f000000010020019000000ca20000613d000000140200002900000000020204330000001804000029000000000042004b000000190700002900000ca40000a13d00000017030000290000001202300029000000000101043b0000000000120435000000010440003900000015010000290000000001010433000000000014004b000008950000413d000000400100043d00000020021000390000000a030000290000000003030433001900000003001d0000000f030000290000000003030433001800000003001d0000000003070433000000000003004b0000000004020019000008f90000613d000000000500001900000000040200190000002007700039000000000607043300000000046404360000000105500039000000000035004b000008f30000413d0000000003140049000000200430008a00000000004104350000001f0330003900001b1f043001970000000003140019000000000043004b0000000004000039000000010400403900001ac20030009c0000010d0000213d00000001004001900000010d0000c13d000000400030043f00001a980020009c00001a98020080410000004002200210000000000101043300001a980010009c00001a98010080410000006001100210000000000121019f000000000200041400001a980020009c00001a9802008041000000c002200210000000000112019f00001ac1011001c700008010020000396a5a6a550000040f000000010020019000000ca20000613d000000400200043d0000002003200039000000000101043b001700000001001d00000014070000290000000001070433000000000001004b00000000040300190000092a0000613d000000000500001900000000040300190000002007700039000000000607043300000000046404360000000105500039000000000015004b000009240000413d0000000001240049000000200410008a00000000004204350000001f0110003900001b1f041001970000000001240019000000000041004b0000000004000039000000010400403900001ac20010009c0000010d0000213d00000001004001900000010d0000c13d000000400010043f00001a980030009c00001a98030080410000004001300210000000000202043300001a980020009c00001a98020080410000006002200210000000000112019f000000000200041400001a980020009c00001a9802008041000000c002200210000000000112019f00001ac1011001c700008010020000396a5a6a550000040f000000010020019000000ca20000613d000000000101043b001600000001001d00000009010000290000000001010433001500000001001d000000040010008c00000caa0000213d00000004010000290000000001010433000f00000001001d00000005010000290000000001010433001000000001001d00000006010000290000000001010433001100000001001d00000007010000290000000001010433001200000001001d00000008010000290000000001010433001300000001001d000000400100043d001400000001001d00001b0401000041000000000010044300000000010004120000000400100443000000a0010000390000002400100443000000000100041400001a980010009c00001a9801008041000000c00110021000001b05011001c700008005020000396a5a6a550000040f0000000100200190000009e00000613d000000190200002900001a9b02200197000000180300002900001a9b03300197000000000401043b000000140600002900000180016000390000000305000029000000000051043500000160016000390000000f050000290000000000510435000001400160003900000010050000290000000000510435000001200160003900000011050000290000000000510435000001000160003900000012050000290000000000510435000000e00160003900000013050000290000000000510435000000c00160003900000015050000290000000000510435000000a001600039000000160500002900000000005104350000008001600039000000170500002900000000005104350000006001600039000000000021043500000040016000390000000000310435000000200160003900000000004104350000018002000039000000000026043500001b0a0060009c0000010d0000213d000001a002600039000000400020043f00001a980010009c00001a98010080410000004001100210000000000206043300001a980020009c00001a98020080410000006002200210000000000112019f000000000200041400001a980020009c00001a9802008041000000c002200210000000000112019f00001ac1011001c700008010020000396a5a6a550000040f000000010020019000000ca20000613d000000000101043b001900000001001d000000000010043f0000000301000039000000200010043f000000000100041400001a980010009c00001a9801008041000000c00110021000001b0b011001c700008010020000396a5a6a550000040f000000010020019000000ca20000613d000000000101043b000000000201041a00001b0c0220019700000100022001bf000000000021041b000000400100043d0000001902000029000000000021043500001a980010009c00001a98010080410000004001100210000000000200041400001a980020009c00001a9802008041000000c002200210000000000112019f0000000e0200002900001a9b052001970000000d0200002900001a9b0620019700001b0d011001c70000800d02000039000000030300003900001b0e040000416a5a6a500000040f000000010020019000000ca20000613d0000000b020000290000000102200039000000010020006c000006a90000413d000000400200043d00000001030000390000003e0000013d000000000001042f000000000f000019000f0000000e001d000009e90000013d000000ff00a0019000000b280000613d000000010ff000390000001300f0006c00000cb80000813d0000000501f002100000000001e100190000000202000367000000000112034f000000000101043b0000000003000031000000140430006a000000630440008a00001b010540019700001b0106100197000000000756013f000000000056004b000000000500001900001b0105004041000000000041004b000000000400001900001b010400804100001b010070009c000000000504c019000000000005004b00000ca20000c13d0018000000e1001d0000001801200360000000000101043b000000180430006a0000015f0440008a00001b010540019700001b0106100197000000000756013f000000000056004b000000000500001900001b0105004041000000000041004b000000000400001900001b010400804100001b010070009c000000000504c019000000000005004b00000ca20000c13d0000001801100029001900000001001d0000008001100039000000000112034f000000000401043b000000040040008c00000ca20000213d000009e60000613d000000190130006a0000001905200360000000000505043b001700000005001d00001b030010009c00000ca20000213d000001600010008c00000ca20000413d000000170100002900001a9b0010009c00000ca20000213d000000400100043d00001aac0010009c0000010d0000213d0000016005100039000000400050043f000000170500002900000000055104360000001906000029001600200060003d0000001606200360000000000606043b00001a9b0060009c00000ca20000213d00000000006504350000001605000029001200200050003d0000001205200360000000000505043b00001ac20050009c00000ca20000213d00000019075000290000001f05700039000000000035004b000000000600001900001b010600804100001b010850019700001b0105300197000000000958013f000000000058004b000000000800001900001b010800404100001b010090009c000000000806c019000000000008004b00000ca20000c13d000000000672034f000000000806043b00001ac20080009c0000010d0000213d00000005068002100000003f0660003900001b0209600197000000400600043d0000000009960019000000000069004b000000000a000039000000010a00403900001ac20090009c0000010d0000213d0000000100a001900000010d0000c13d0000002007700039000000400090043f0000000000860435000000a0088000c90000000008780019000000000038004b00000ca20000213d000000000078004b00000a890000a13d0000000009060019000000000a73004900001b0300a0009c00000ca20000213d000000a000a0008c00000ca20000413d000000400a00043d00001aa800a0009c0000010d0000213d000000a00ba000390000004000b0043f000000000b72034f000000000b0b043b0000000500b0008c00000ca20000213d000000000cba0436000000200b700039000000000db2034f000000000d0d043b00001a9b00d0009c00000ca20000213d00000020099000390000000000dc0435000000200cb00039000000000cc2034f000000000c0c043b000000400da000390000000000cd0435000000400cb00039000000000cc2034f000000000c0c043b000000600da000390000000000cd0435000000600bb00039000000000bb2034f000000000b0b043b000000800ca000390000000000bc04350000000000a90435000000a007700039000000000087004b00000a600000413d0000004007100039000000000067043500000019060000290000006006600039000000000662034f000000000606043b00001ac20060009c00000ca20000213d00000019066000290000001f07600039000000000037004b000000000800001900001b010800804100001b0107700197000000000957013f000000000057004b000000000500001900001b010500404100001b010090009c000000000508c019000000000005004b00000ca20000c13d000000000562034f000000000705043b00001ac20070009c0000010d0000213d00000005057002100000003f0550003900001b0208500197000000400500043d0000000008850019000000000058004b0000000009000039000000010900403900001ac20080009c0000010d0000213d00000001009001900000010d0000c13d0000002006600039000000400080043f0000000000750435000000c0077000c90000000007670019000000000037004b00000ca20000213d000000000067004b00000ae90000a13d0000000008050019000000000963004900001b030090009c00000ca20000213d000000c00090008c00000ca20000413d000000400900043d00001ac80090009c0000010d0000213d000000c00a9000390000004000a0043f000000000a62034f000000000a0a043b0000000500a0008c00000ca20000213d000000000ba90436000000200a600039000000000ca2034f000000000c0c043b00001a9b00c0009c00000ca20000213d0000000000cb0435000000200ba00039000000000bb2034f000000000b0b043b000000400c9000390000000000bc0435000000400ba00039000000000bb2034f000000000b0b043b000000600c9000390000000000bc0435000000600ba00039000000000bb2034f000000000b0b043b000000800c9000390000000000bc0435000000800aa00039000000000aa2034f000000000a0a043b00001a9b00a0009c00000ca20000213d0000002008800039000000a00b9000390000000000ab04350000000000980435000000c006600039000000000076004b00000ab90000413d00000080031000390000000000430435000000600310003900000000005304350000001905000029000000a003500039000000000332034f000000000303043b000000a0041000390000000000340435000000c003500039000000000332034f000000000303043b000000c0041000390000000000340435000000e003500039000000000332034f000000000303043b000000e00410003900000000003404350000010003500039000000000332034f000000000303043b000001000410003900000000003404350000012003500039000000000332034f000000000303043b00000120041000390000000000340435001101400050003d0000001102200360000000000202043b0000014003100039000000000023043500150000000f001d6a5a563f0000040f001000000001001d000000000010043f0000000301000039000000200010043f000000000100041400001a980010009c00001a9801008041000000c00110021000001b0b011001c700008010020000396a5a6a550000040f000000150f0000290000000f0e000029000000010020019000000ca20000613d000000000901043b000000000a09041a0000ff0000a0019000000cbe0000c13d0000001001a0027000001b1301100198000009e40000613d0000008802a00270000000000021004b000009e40000413d00000cc10000013d0000001101000029000000e00210008a0000000201000367000000000221034f000000000302043b0000000002000031000000190420006a0000001f0440008a00001b010540019700001b0106300197000000000756013f000000000056004b000000000500001900001b0105004041000000000043004b000000000400001900001b010400804100001b010070009c000000000504c019000000000005004b00000ca20000c13d0000001904300029000000000341034f000000000303043b00001ac20030009c00000ca20000213d00001b21053000d100000000052500190000002004400039000000000054004b000000000600001900001b010600204100001b010550019700001b0104400197000000000754013f000000000054004b000000000400001900001b010400404100001b010070009c000000000406c019000000000004004b00000ca20000c13d0000001104100360000000000404043b000000000043004b00000ccc0000c13d000000180300002900000000043200490000002003300039000000000331034f000000000303043b0000001f0440008a00001b010540019700001b0106300197000000000756013f000000000056004b000000000500001900001b0105004041000000000043004b000000000400001900001b010400804100001b010070009c000000000504c019000000000005004b00000ca20000c13d0000001803300029000000000431034f000000000404043b00001ac20040009c00000ca20000213d0000000005420049000000200630003900001b010350019700001b0107600197000000000837013f000000000037004b000000000300001900001b0103004041000000000056004b000000000500001900001b010500204100001b010080009c000000000305c019000000000003004b00000ca20000c13d0000001f0340003900001b1f033001970000003f0330003900001b1f05300197000000400300043d0000000005530019000000000035004b0000000007000039000000010700403900001ac20050009c0000010d0000213d00000001007001900000010d0000c13d000000400050043f00000000054304360000000007640019000000000027004b00000ca20000213d001800000009001d000000000261034f00001b1f06400198000000000165001900000b9a0000613d000000000702034f0000000008050019000000007907043c0000000008980436000000000018004b00000b960000c13d00110000000a001d0000001f0740019000000ba80000613d000000000262034f0000000306700210000000000701043300000000076701cf000000000767022f000000000202043b0000010006600089000000000262022f00000000026201cf000000000272019f000000000021043500000000014500190000000000010435000000170100002900000010020000296a5a584c0000040f000001000100008a000000110110017f00000001011001bf0000001802000029000000000012041b000000400100043d0000002002100039000000400300003900000000003204350000001002000029000000000021043500000002020003670000001903200360000000000303043b00001a9b0030009c00000ca20000213d000000400410003900000000003404350000001603200360000000000303043b00001a9b0030009c00000ca20000213d0000006004100039000000000034043500000012042003600000000003000031000000190530006a0000001f0550008a000000000404043b00001b010740019700001b0106500197000000000867013f000000000067004b000000000700001900001b0107004041000000000054004b000000000900001900001b010900804100001b010080009c000000000709c019000000000007004b00000ca20000c13d0000001907400029000000000472034f000000000404043b00001ac20040009c00000ca20000213d00001b20084000d10000000009380019000000200870003900001b010790019700001b010a800197000000000b7a013f00000000007a004b000000000700001900001b0107004041000000000098004b000000000900001900001b010900204100001b0100b0009c000000000709c019000000000007004b00000ca20000c13d000000800710003900000160090000390000000000970435000001a0071000390000000000470435000001c007100039000000000004004b00000c140000613d0000000009000019000000000a82034f000000000a0a043b0000000500a0008c00000ca20000213d000000000ba70436000000200a800039000000000ca2034f000000000c0c043b00001a9b00c0009c00000ca20000213d0000000000cb0435000000200ba00039000000000bb2034f000000000b0b043b000000400c7000390000000000bc0435000000400ba00039000000000bb2034f000000000b0b043b000000600c7000390000000000bc0435000000600aa00039000000000aa2034f000000000a0a043b000000800b7000390000000000ab0435000000a008800039000000a0077000390000000109900039000000000049004b00000bf50000413d00000012040000290000002004400039000000000842034f000000000808043b00001b0109800197000000000a69013f000000000069004b000000000600001900001b0106002041000000000058004b000000000500001900001b010500404100001b0100a0009c000000000605c019000000000006004b00000ca20000613d0000001906800029000000000562034f000000000505043b00001ac20050009c00000ca20000213d000000200660003900001b21085000d10000000003380019000000000036004b000000000800001900001b010800204100001b010330019700001b0109600197000000000a39013f000000000039004b000000000300001900001b010300404100001b0100a0009c000000000308c019000000000003004b00000ca20000c13d0000000003170049000000400330008a000000a00810003900000000003804350000000003570436000000000005004b00000c670000613d0000000007000019000000000862034f000000000808043b000000050080008c00000ca20000213d00000000098304360000002008600039000000000a82034f000000000a0a043b00001a9b00a0009c00000ca20000213d0000000000a904350000002009800039000000000992034f000000000909043b000000400a30003900000000009a04350000004009800039000000000992034f000000000909043b000000600a30003900000000009a04350000006009800039000000000992034f000000000909043b000000800a30003900000000009a04350000008008800039000000000882034f000000000808043b00001a9b0080009c00000ca20000213d000000a0093000390000000000890435000000c006600039000000c0033000390000000107700039000000000057004b00000c410000413d0000002004400039000000000542034f000000000505043b000000050050008c00000caa0000813d000000c00610003900000000005604350000002005400039000000000552034f000000000505043b000000e00610003900000000005604350000004005400039000000000552034f000000000505043b000001000610003900000000005604350000006005400039000000000552034f000000000505043b000001200610003900000000005604350000008005400039000000000552034f000000000505043b00000140061000390000000000560435000000a005400039000000000552034f000000000505043b00000160061000390000000000560435000000c004400039000000000242034f000000000202043b00000180041000390000000000240435000000000213004900001a980020009c00001a9802008041000000600220021000001a980010009c00001a98010080410000004001100210000000000112019f000000000200041400001a980020009c00001a9802008041000000c002200210000000000112019f00001ac1011001c70000800d02000039000000010300003900001b16040000416a5a6a500000040f00000001002001900000000f0e000029000000150f000029000009e60000c13d000000000100001900006a5c0001043000001b0801000041000000000010043f0000003201000039000000040010043f00001b090100004100006a5c0001043000001b0801000041000000000010043f0000002101000039000000040010043f00001b090100004100006a5c00010430000000400100043d00001b1702000041000000000021043500001a980010009c00001a9801008041000000400110021000001aca011001c700006a5c00010430000000400100043d00000001020000390000053e0000013d000000400100043d00001b0f0200004100000cb20000013d000000400100043d00001b120200004100000cc30000013d000000400100043d00001b1402000041000000000021043500000004021000390000001003000029000000000032043500001a980010009c00001a9801008041000000400110021000001b09011001c700006a5c00010430000000400100043d00001b150200004100000cb20000013d000000190300002900001a980030009c00001a9803008041000000400330021000001a980010009c00001a9801008041000000c001100210000000000131019f00001aca011001c76a5a6a550000040f0000000003010019000000600330027000001a9803300197000000400030008c000000400400003900000000040340190000001f0640018f0000006007400190000000190570002900000ce90000613d000000000801034f0000001909000029000000008a08043c0000000009a90436000000000059004b00000ce50000c13d000000000006004b00000cf60000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000100000003001f0003000000010355000000010020019000000f900000613d0000001f01400039000000e00210018f0000001901200029000000000021004b0000000002000039000000010200403900001ac20010009c0000010d0000213d00000001002001900000010d0000c13d000000400010043f000000400030008c00000ca20000413d0000001901000029000000000101043300000018020000290000000002020433002001e00000003d000001e00020043f001f01c00000003d000001c00010043f001e00010000003d000000200000043f00001acb0100004100001acc02000041000000000012041b001d00020000003d00001acd0100004100001ace02000041000000000012041b00001acf0100004100001ad002000041000000000012041b0000000401000039000000000010043f000000400200003900000000010000196a5a6a1d0000040f00001ad102000041000000000021041b001c00050000003d0000000501000039000000000010043f000000000100001900000040020000396a5a6a1d0000040f00001ad202000041000000000021041b0000000601000039000000000010043f000000000100001900000040020000396a5a6a1d0000040f00001ad302000041000000000021041b0000000701000039000000000010043f000000000100001900000040020000396a5a6a1d0000040f00001ad402000041000000000021041b0000000801000039000000000010043f000000000100001900000040020000396a5a6a1d0000040f00001ad502000041000000000021041b0000000901000039000000000010043f000000000100001900000040020000396a5a6a1d0000040f00001ad602000041000000000021041b0000000a01000039000000000010043f000000000100001900000040020000396a5a6a1d0000040f00001ad702000041000000000021041b0000000b01000039000000000010043f000000000100001900000040020000396a5a6a1d0000040f00001ad802000041000000000021041b0000000c01000039000000000010043f000000000100001900000040020000396a5a6a1d0000040f00001ad902000041000000000021041b0000000d01000039000000000010043f000000000100001900000040020000396a5a6a1d0000040f00001ada02000041000000000021041b0000000e01000039000000000010043f000000000100001900000040020000396a5a6a1d0000040f00001adb02000041000000000021041b0000000f01000039000000000010043f000000000100001900000040020000396a5a6a1d0000040f00001adc02000041000000000021041b0000001001000039000000000010043f000000000100001900000040020000396a5a6a1d0000040f00001add02000041000000000021041b0000001101000039000000000010043f000000000100001900000040020000396a5a6a1d0000040f00001ade02000041000000000021041b0000001201000039000000000010043f000000000100001900000040020000396a5a6a1d0000040f00001adf02000041000000000021041b0000001301000039000000000010043f000000000100001900000040020000396a5a6a1d0000040f00001ae002000041000000000021041b0000001401000039000000000010043f000000000100001900000040020000396a5a6a1d0000040f00001ae102000041000000000021041b0000001501000039000000000010043f000000000100001900000040020000396a5a6a1d0000040f00001ae202000041000000000021041b0000001601000039000000000010043f000000000100001900000040020000396a5a6a1d0000040f00001ae302000041000000000021041b0000001701000039000000000010043f000000000100001900000040020000396a5a6a1d0000040f00001ae402000041000000000021041b0000001801000039000000000010043f000000000100001900000040020000396a5a6a1d0000040f00001ae502000041000000000021041b0000000101000039000000000011041b000000000000043f0000000501000039000000200010043f000000000100001900000040020000396a5a6a1d0000040f000000000201041a00001b2202200197000000000021041b0000000101000039000000000010043f000000000100001900000040020000396a5a6a1d0000040f000000000201041a00001b2202200197000000000021041b0000000201000039000000000010043f000000000100001900000040020000396a5a6a1d0000040f000000000201041a00001b2202200197000000000021041b0000000301000039000000000010043f000000000100001900000040020000396a5a6a1d0000040f000000000201041a00001b2202200197000000000021041b0000000401000039000000000010043f000000000100001900000040020000396a5a6a1d0000040f000000000201041a00001b220220019700000001022001bf000000000021041b0000000501000039000000000010043f000000000100001900000040020000396a5a6a1d0000040f000000000201041a00001b220220019700000001022001bf000000000021041b0000000601000039000000000010043f000000000100001900000040020000396a5a6a1d0000040f000000000201041a00001b220220019700000001022001bf000000000021041b0000000701000039000000000010043f000000000100001900000040020000396a5a6a1d0000040f000000000201041a00001b220220019700000001022001bf000000000021041b0000000801000039000000000010043f000000000100001900000040020000396a5a6a1d0000040f000000000201041a00001b220220019700000002022001bf000000000021041b0000000901000039000000000010043f000000000100001900000040020000396a5a6a1d0000040f000000000201041a00001b220220019700000002022001bf000000000021041b0000000a01000039000000000010043f000000000100001900000040020000396a5a6a1d0000040f000000000201041a00001b220220019700000002022001bf000000000021041b0000000b01000039000000000010043f000000000100001900000040020000396a5a6a1d0000040f000000000201041a00001b220220019700000002022001bf000000000021041b0000000c01000039000000000010043f000000000100001900000040020000396a5a6a1d0000040f000000000201041a00001b220220019700000003022001bf000000000021041b0000000d01000039000000000010043f000000000100001900000040020000396a5a6a1d0000040f000000000201041a00001b220220019700000003022001bf000000000021041b0000000e01000039000000000010043f000000000100001900000040020000396a5a6a1d0000040f000000000201041a00001b220220019700000003022001bf000000000021041b0000000f01000039000000000010043f000000000100001900000040020000396a5a6a1d0000040f000000000201041a00001b220220019700000003022001bf000000000021041b0000001001000039000000000010043f000000000100001900000040020000396a5a6a1d0000040f000000000201041a00001b220220019700000004022001bf000000000021041b0000001101000039000000000010043f000000000100001900000040020000396a5a6a1d0000040f000000000201041a00001b220220019700000004022001bf000000000021041b0000001201000039000000000010043f000000000100001900000040020000396a5a6a1d0000040f000000000201041a00001b220220019700000004022001bf000000000021041b0000001301000039000000000010043f000000000100001900000040020000396a5a6a1d0000040f000000000201041a00001b220220019700000004022001bf000000000021041b0000001401000039000000000010043f000000000100001900000040020000396a5a6a1d0000040f000000000201041a00001b220220019700000005022001bf000000000021041b0000001501000039000000000010043f000000000100001900000040020000396a5a6a1d0000040f000000000201041a00001b220220019700000005022001bf000000000021041b0000001601000039000000000010043f000000000100001900000040020000396a5a6a1d0000040f000000000201041a00001b220220019700000005022001bf000000000021041b0000001701000039000000000010043f000000000100001900000040020000396a5a6a1d0000040f000000000201041a00001b220220019700000005022001bf000000000021041b0000000601000039000000200010043f00001ae601000041000000000201041a00001b2202200197000000000021041b0000000401000039000000000010043f000000000100001900000040020000396a5a6a1d0000040f000000000201041a00001b2202200197000000000021041b0000000801000039000000000010043f000000000100001900000040020000396a5a6a1d0000040f000000000201041a00001b2202200197000000000021041b0000000c01000039000000000010043f000000000100001900000040020000396a5a6a1d0000040f000000000201041a00001b2202200197000000000021041b0000001001000039000000000010043f000000000100001900000040020000396a5a6a1d0000040f000000000201041a00001b2202200197000000000021041b0000001401000039000000000010043f000000000100001900000040020000396a5a6a1d0000040f000000000201041a00001b2202200197000000000021041b0000001e01000029001900000001001d000000000010043f000000000100001900000040020000396a5a6a1d0000040f000000000201041a00001b220220019700000019022001af000000000021041b0000001c01000029000000000010043f000000000100001900000040020000396a5a6a1d0000040f000000000201041a00001b220220019700000019022001af000000000021041b0000000901000039000000000010043f000000000100001900000040020000396a5a6a1d0000040f000000000201041a00001b220220019700000019022001af000000000021041b0000000d01000039000000000010043f000000000100001900000040020000396a5a6a1d0000040f000000000201041a00001b220220019700000019022001af000000000021041b0000001101000039000000000010043f000000000100001900000040020000396a5a6a1d0000040f000000000201041a00001b220220019700000019022001af000000000021041b0000001501000039000000000010043f000000000100001900000040020000396a5a6a1d0000040f000000000201041a00001b220220019700000019022001af000000000021041b0000001d01000029001900000001001d000000000010043f000000000100001900000040020000396a5a6a1d0000040f000000000201041a00001b220220019700000019022001af000000000021041b0000000601000039000000000010043f000000000100001900000040020000396a5a6a1d0000040f000000000201041a00001b220220019700000019022001af000000000021041b0000000a01000039000000000010043f000000000100001900000040020000396a5a6a1d0000040f000000000201041a00001b220220019700000019022001af000000000021041b0000000e01000039000000000010043f000000000100001900000040020000396a5a6a1d0000040f000000000201041a00001b220220019700000019022001af000000000021041b0000001201000039000000000010043f000000000100001900000040020000396a5a6a1d0000040f000000000201041a00001b220220019700000019022001af000000000021041b0000001601000039000000000010043f000000000100001900000040020000396a5a6a1d0000040f000000000201041a00001b220220019700000019022001af000000000021041b0000000301000039000000000010043f000000000100001900000040020000396a5a6a1d0000040f000000000201041a00001b220220019700000003022001bf000000000021041b0000000701000039000000000010043f000000000100001900000040020000396a5a6a1d0000040f000000000201041a00001b220220019700000003022001bf000000000021041b0000000b01000039000000000010043f000000000100001900000040020000396a5a6a1d0000040f000000000201041a00001b220220019700000003022001bf000000000021041b0000000f01000039000000000010043f000000000100001900000040020000396a5a6a1d0000040f000000000201041a00001b220220019700000003022001bf000000000021041b0000001301000039000000000010043f000000000100001900000040020000396a5a6a1d0000040f000000000201041a00001b220220019700000003022001bf000000000021041b0000001701000039000000000010043f000000000100001900000040020000396a5a6a1d0000040f000000000201041a00001b220220019700000003022001bf000000000021041b000000800100043d000001400000044300000160001004430000002001000039000000a00200043d0000018000100443000001a000200443000000c00200043d0000004003000039000001c000300443000001e0002004430000006002000039000000e00300043d000002000020044300000220003004430000008002000039000001000300043d00000240002004430000026000300443000001200200043d000000a0030000390000028000300443000002a00020044300000022020000290000000002020433000000c003000039000002c000300443000002e00020044300000021020000290000000002020433000000e003000039000003000030044300000320002004430000010002000039000001800300043d000003400020044300000360003004430000012002000039000001a00300043d0000038000200443000003a0003004430000001f0200002900000000020204330000014003000039000003c000300443000003e0002004430000002002000029000000000202043300000160030000390000040000300443000004200020044300000100001004430000000c01000039000001200010044300001ae70100004100006a5b0001042e0000001f0530018f00001a9a06300198000000400200043d000000000462001900000f9b0000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00000f970000c13d000000000005004b00000fa80000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f0000000000140435000000600130021000001a980020009c00001a98020080410000004002200210000000000112019f00006a5c0001043000001b030010009c00000fbe0000213d000000230010008c00000fbe0000a13d00000004020000390000000202200367000000000202043b00001ac20020009c00000fbe0000213d000000000121004900001b030010009c00000fbe0000213d000002440010008c00000fbe0000413d0000000401200039000000000001042d000000000100001900006a5c0001043000000000430104340000000001320436000000000003004b00000fcc0000613d000000000200001900000000052100190000000006240019000000000606043300000000006504350000002002200039000000000032004b00000fc50000413d000000000231001900000000000204350000001f0230003900001b1f022001970000000001210019000000000001042d00001b230010009c00000fd70000813d0000016001100039000000400010043f000000000001042d00001b0801000041000000000010043f0000004101000039000000040010043f00001b090100004100006a5c0001043000001b240010009c00000fe20000813d0000002001100039000000400010043f000000000001042d00001b0801000041000000000010043f0000004101000039000000040010043f00001b090100004100006a5c0001043000001b250020009c0000102d0000813d00000005042002100000003f0440003900001b0205400197000000400400043d0000000005540019000000000045004b0000000006000039000000010600403900001ac20050009c0000102d0000213d00000001006001900000102d0000c13d000000400050043f0000000000240435000000a0022000c90000000002120019000000000032004b0000102b0000213d000000000012004b000010290000a13d00000002050003670000000006040019000000000713004900001b030070009c0000102b0000213d000000a00070008c0000102b0000413d000000400700043d00001aa80070009c0000102d0000213d000000a008700039000000400080043f000000000815034f000000000808043b000000050080008c0000102b0000213d00000000098704360000002008100039000000000a85034f000000000a0a043b00001a9b00a0009c0000102b0000213d00000020066000390000000000a904350000002009800039000000000995034f000000000909043b000000400a70003900000000009a04350000004009800039000000000995034f000000000909043b000000600a70003900000000009a04350000006008800039000000000885034f000000000808043b000000800970003900000000008904350000000000760435000000a001100039000000000021004b000010000000413d0000000001040019000000000001042d000000000100001900006a5c0001043000001b0801000041000000000010043f0000004101000039000000040010043f00001b090100004100006a5c0001043000001b250020009c0000107f0000813d00000005042002100000003f0440003900001b0205400197000000400400043d0000000005540019000000000045004b0000000006000039000000010600403900001ac20050009c0000107f0000213d00000001006001900000107f0000c13d000000400050043f0000000000240435000000c0022000c90000000002120019000000000032004b0000107d0000213d000000000012004b0000107b0000a13d00000002050003670000000006040019000000000713004900001b030070009c0000107d0000213d000000c00070008c0000107d0000413d000000400700043d00001ac80070009c0000107f0000213d000000c008700039000000400080043f000000000815034f000000000808043b000000050080008c0000107d0000213d00000000098704360000002008100039000000000a85034f000000000a0a043b00001a9b00a0009c0000107d0000213d0000000000a904350000002009800039000000000995034f000000000909043b000000400a70003900000000009a04350000004009800039000000000995034f000000000909043b000000600a70003900000000009a04350000006009800039000000000995034f000000000909043b000000800a70003900000000009a04350000008008800039000000000885034f000000000808043b00001a9b0080009c0000107d0000213d0000002006600039000000a00970003900000000008904350000000000760435000000c001100039000000000021004b0000104b0000413d0000000001040019000000000001042d000000000100001900006a5c0001043000001b0801000041000000000010043f0000004101000039000000040010043f00001b090100004100006a5c000104300001000000000002000000000f0100190000000001f2004900001b030010009c000012280000213d0000009f0010008c000012280000a13d000000400100043d00001b260010009c0000122a0000813d000000a006100039000000400060043f00000002040003670000000003f4034f000000000303043b00001ac20030009c000012280000213d0000000007f30019000000000372004900001b030030009c000012280000213d000001600030008c000012280000413d00001b270010009c0000122a0000213d0000020003100039000000400030043f000000000374034f000000000303043b00001a9b0030009c000012280000213d00000000003604350000002003700039000000000534034f000000000505043b00001a9b0050009c000012280000213d000000c00810003900000000005804350000002003300039000000000334034f000000000303043b00001ac20030009c000012280000213d00000000097300190000001f03900039000000000023004b000000000800001900001b010800804100001b010330019700001b0105200197000000000a53013f000000000053004b000000000300001900001b010300404100001b0100a0009c000000000308c019000000000003004b000012280000c13d000000000394034f000000000a03043b00001ac200a0009c0000122a0000213d0000000503a002100000003f0330003900001b0203300197000000400800043d000000000b38001900000000008b004b0000000003000039000000010300403900001ac200b0009c0000122a0000213d00000001003001900000122a0000c13d00000020099000390000004000b0043f0000000000a80435000000a003a000c9000000000a93001900000000002a004b000012280000213d00000000009a004b000011030000a13d000000000b080019000000000392004900001b030030009c000012280000213d000000a00030008c000012280000413d000000400c00043d00001aa800c0009c0000122a0000213d000000a003c00039000000400030043f000000000394034f000000000303043b000000050030008c000012280000213d00000000033c0436000000200d900039000000000ed4034f000000000e0e043b00001a9b00e0009c000012280000213d000000200bb000390000000000e304350000002003d00039000000000334034f000000000303043b000000400ec0003900000000003e04350000004003d00039000000000334034f000000000303043b000000600ec0003900000000003e04350000006003d00039000000000334034f000000000303043b000000800dc0003900000000003d04350000000000cb0435000000a0099000390000000000a9004b000010da0000413d000000e00310003900000000008304350000006003700039000000000334034f000000000303043b00001ac20030009c000012280000213d00000000097300190000001f03900039000000000023004b000000000800001900001b010800804100001b0103300197000000000a53013f000000000053004b000000000300001900001b010300404100001b0100a0009c000000000308c019000000000003004b000012280000c13d000000000394034f000000000a03043b00001ac200a0009c0000122a0000213d0000000503a002100000003f0330003900001b0203300197000000400800043d000000000b38001900000000008b004b0000000003000039000000010300403900001ac200b0009c0000122a0000213d00000001003001900000122a0000c13d00000020099000390000004000b0043f0000000000a80435000000c003a000c9000000000a93001900000000002a004b000012280000213d00000000009a004b000011620000a13d000000000b080019000000000392004900001b030030009c000012280000213d000000c00030008c000012280000413d000000400c00043d00001ac800c0009c0000122a0000213d000000c003c00039000000400030043f000000000394034f000000000303043b000000050030008c000012280000213d00000000033c0436000000200d900039000000000ed4034f000000000e0e043b00001a9b00e0009c000012280000213d0000000000e304350000002003d00039000000000334034f000000000303043b000000400ec0003900000000003e04350000004003d00039000000000334034f000000000303043b000000600ec0003900000000003e04350000006003d00039000000000334034f000000000303043b000000800ec0003900000000003e04350000008003d00039000000000334034f000000000303043b00001a9b0030009c000012280000213d000000200bb00039000000a00dc0003900000000003d04350000000000cb0435000000c0099000390000000000a9004b000011320000413d000001000310003900000000008304350000008007700039000000000374034f000000000303043b000000040030008c000012280000213d000001200810003900000000003804350000002003700039000000000334034f000000000303043b000001400810003900000000003804350000004003700039000000000334034f000000000303043b000001600810003900000000003804350000006003700039000000000334034f000000000303043b000001800810003900000000003804350000008003700039000000000334034f000000000303043b000001a0081000390000000000380435000000a003700039000000000334034f000000000303043b000001c0081000390000000000380435000000c003700039000000000334034f000000000703043b0000000003610436000001e00610003900000000007604350000002006f00039000000000764034f000000000707043b00001b130070009c000012280000213d00000000007304350000002003600039000000000634034f000000000606043b00001b130060009c000012280000213d000000400710003900000000006704350000002007300039000000000374034f000000000303043b00001ac20030009c000012280000213d000000000af300190000001f03a00039000000000023004b000000000600001900001b010600804100001b0103300197000000000853013f000000000053004b000000000300001900001b010300404100001b010080009c000000000306c019000000000003004b000012280000c13d0000000003a4034f000000000803043b00001ac20080009c0000122a0000213d0000001f0380003900001b1f033001970000003f0330003900001b1f03300197000000400900043d000000000b39001900000000009b004b0000000003000039000000010300403900001ac200b0009c0000122a0000213d00000001003001900000122a0000c13d000000200aa000390000004000b0043f0000000003890436000000000ba8001900000000002b004b000012280000213d000100000005001d00000000060f0019000000000ca4034f00001b1f0d8001980000001f0e80018f000000000bd30019000011ce0000613d000000000f0c034f000000000a03001900000000f50f043c000000000a5a04360000000000ba004b000011ca0000c13d00000000000e004b000011db0000613d0000000005dc034f000000030ae00210000000000c0b0433000000000cac01cf000000000cac022f000000000505043b000001000aa000890000000005a5022f0000000005a501cf0000000005c5019f00000000005b043500000000038300190000000000030435000000600310003900000000009304350000002003700039000000000334034f000000000303043b00001ac20030009c0000000105000029000012280000213d00000000076300190000001f03700039000000000023004b0000000006050019000000000500001900001b010500804100001b0103300197000000000863013f000000000063004b000000000300001900001b010300404100001b010080009c000000000305c019000000000003004b000012280000c13d000000000374034f000000000303043b00001ac20030009c0000122a0000213d0000001f0530003900001b1f055001970000003f0550003900001b1f08500197000000400500043d0000000008850019000000000058004b0000000009000039000000010900403900001ac20080009c0000122a0000213d00000001009001900000122a0000c13d0000002009700039000000400080043f00000000073504360000000008930019000000000028004b000012280000213d000000000494034f00001b1f063001980000001f0830018f0000000002670019000012160000613d000000000904034f000000000a070019000000009b09043c000000000aba043600000000002a004b000012120000c13d000000000008004b000012230000613d000000000464034f0000000306800210000000000802043300000000086801cf000000000868022f000000000404043b0000010006600089000000000464022f00000000046401cf000000000484019f00000000004204350000000002370019000000000002043500000080021000390000000000520435000000000001042d000000000100001900006a5c0001043000001b0801000041000000000010043f0000004101000039000000040010043f00001b090100004100006a5c000104300006000000000002000300000001001d0000001f01100039000000000021004b000000000300001900001b010300404100061b010020019b00001b0101100197000000060410014f000000060010006c000000000100001900001b010100204100001b010040009c000000000103c019000000000001004b000014080000613d00000002050003670000000301500360000000000101043b00001b250010009c0000140a0000813d00000005031002100000003f0430003900001b0204400197000000400700043d0000000006470019000100000007001d000000000076004b0000000004000039000000010400403900001ac20060009c0000140a0000213d00000001004001900000140a0000c13d000000400060043f0000000104000029000000000014043500000003010000290000002006100039000200000036001d000000020020006b000014080000213d000000020060006c000014060000813d0000000104000029000012680000013d00000004040000290000002004400039000000000117001900000000000104350000008001a0003900000000003104350000000000a404350000002006600039000000020060006c000014060000813d000400000004001d000000000165034f000000000101043b00001ac20010009c000014080000213d0000000301100029000500000001001d000000200b1000390000000001b2004900001b030010009c000014080000213d000000a00010008c000014080000413d000000400a00043d00001aa800a0009c0000140a0000213d0000000001b5034f000000a00da000390000004000d0043f000000000101043b00001ac20010009c000014080000213d000000000eb100190000000001e2004900001b030010009c000014080000213d000001600010008c000014080000413d00001b2700a0009c0000140a0000213d0000020001a00039000000400010043f0000000001e5034f000000000101043b00001a9b0010009c000014080000213d00000000001d04350000002001e00039000000000315034f000000000303043b00001a9b0030009c000014080000213d000000c004a0003900000000003404350000002001100039000000000115034f000000000101043b00001ac20010009c000014080000213d0000000001e100190000001f03100039000000000023004b000000000400001900001b010400804100001b0103300197000000060730014f000000060030006c000000000300001900001b010300404100001b010070009c000000000304c019000000000003004b000014080000c13d000000000315034f000000000703043b00001ac20070009c0000140a0000213d00000005037002100000003f0330003900001b0203300197000000400f00043d00000000083f00190000000000f8004b0000000003000039000000010300403900001ac20080009c0000140a0000213d00000001003001900000140a0000c13d0000002003100039000000400080043f00000000007f0435000000a0017000c90000000007310019000000000027004b000014080000213d000000000037004b000012ea0000a13d00000000010f0019000000000432004900001b030040009c000014080000213d000000a00040008c000014080000413d000000400800043d00001aa80080009c0000140a0000213d000000a004800039000000400040043f000000000435034f000000000404043b000000050040008c000014080000213d00000000044804360000002009300039000000000c95034f000000000c0c043b00001a9b00c0009c000014080000213d00000020011000390000000000c404350000002004900039000000000445034f000000000404043b000000400c80003900000000004c04350000004004900039000000000445034f000000000404043b000000600c80003900000000004c04350000006004900039000000000445034f000000000404043b000000800980003900000000004904350000000000810435000000a003300039000000000073004b000012c10000413d000000e001a000390000000000f104350000006001e00039000000000115034f000000000101043b00001ac20010009c000014080000213d0000000003e100190000001f01300039000000000021004b000000000400001900001b010400804100001b0101100197000000060710014f000000060010006c000000000100001900001b010100404100001b010070009c000000000104c019000000000001004b000014080000c13d000000000135034f000000000701043b00001ac20070009c0000140a0000213d00000005017002100000003f0110003900001b0204100197000000400100043d0000000008410019000000000018004b0000000004000039000000010400403900001ac20080009c0000140a0000213d00000001004001900000140a0000c13d0000002003300039000000400080043f0000000000710435000000c0047000c90000000007340019000000000027004b000014080000213d000000000037004b000013490000a13d000000000f010019000000000432004900001b030040009c000014080000213d000000c00040008c000014080000413d000000400800043d00001ac80080009c0000140a0000213d000000c004800039000000400040043f000000000435034f000000000404043b000000050040008c000014080000213d00000000044804360000002009300039000000000c95034f000000000c0c043b00001a9b00c0009c000014080000213d0000000000c404350000002004900039000000000445034f000000000404043b000000400c80003900000000004c04350000004004900039000000000445034f000000000404043b000000600c80003900000000004c04350000006004900039000000000445034f000000000404043b000000800c80003900000000004c04350000008004900039000000000445034f000000000404043b00001a9b0040009c000014080000213d000000200ff00039000000a009800039000000000049043500000000008f0435000000c003300039000000000073004b000013190000413d0000010003a0003900000000001304350000008001e00039000000000315034f000000000303043b000000040030008c000014080000213d0000012004a0003900000000003404350000002003100039000000000335034f000000000303043b0000014004a0003900000000003404350000004003100039000000000335034f000000000303043b0000016004a0003900000000003404350000006003100039000000000335034f000000000303043b0000018004a0003900000000003404350000008003100039000000000335034f000000000303043b000001a004a000390000000000340435000000a003100039000000000335034f000000000303043b000001c004a000390000000000340435000000c001100039000000000115034f000000000301043b0000000001da0436000001e004a00039000000000034043500000005030000290000004003300039000000000435034f000000000404043b00001b130040009c000014080000213d00000000004104350000002001300039000000000315034f000000000303043b00001b130030009c000014080000213d0000004004a000390000000000340435000000200c1000390000000001c5034f000000000101043b00001ac20010009c000014080000213d0000000007b100190000001f01700039000000000021004b000000000300001900001b010300804100001b0101100197000000060410014f000000060010006c000000000100001900001b010100404100001b010040009c000000000103c019000000000001004b000014080000c13d000000000175034f000000000101043b00001ac20010009c0000140a0000213d0000001f0310003900001b1f033001970000003f0330003900001b1f04300197000000400300043d0000000008430019000000000038004b0000000004000039000000010400403900001ac20080009c0000140a0000213d00000001004001900000140a0000c13d0000002004700039000000400080043f00000000071304360000000008410019000000000028004b000014080000213d000000000d45034f00001b1f091001980000000008970019000013b30000613d000000000e0d034f000000000f07001900000000e40e043c000000000f4f043600000000008f004b000013af0000c13d0000001f04100190000013c00000613d00000000099d034f0000000304400210000000000d080433000000000d4d01cf000000000d4d022f000000000909043b0000010004400089000000000949022f00000000044901cf0000000004d4019f0000000000480435000000000117001900000000000104350000006001a0003900000000003104350000002001c00039000000000115034f000000000101043b00001ac20010009c000014080000213d0000000007b100190000001f01700039000000000021004b000000000300001900001b010300804100001b0101100197000000060410014f000000060010006c000000000100001900001b010100404100001b010040009c000000000103c019000000000001004b000014080000c13d000000000175034f000000000101043b00001ac20010009c0000140a0000213d0000001f0310003900001b1f033001970000003f0330003900001b1f04300197000000400300043d0000000008430019000000000038004b0000000004000039000000010400403900001ac20080009c0000140a0000213d00000001004001900000140a0000c13d0000002004700039000000400080043f00000000071304360000000008410019000000000028004b000014080000213d000000000b45034f00001b1f091001980000000008970019000013f80000613d000000000c0b034f000000000d07001900000000c40c043c000000000d4d043600000000008d004b000013f40000c13d0000001f041001900000125e0000613d00000000099b034f0000000304400210000000000b080433000000000b4b01cf000000000b4b022f000000000909043b0000010004400089000000000949022f00000000044901cf0000000004b4019f00000000004804350000125e0000013d0000000101000029000000000001042d000000000100001900006a5c0001043000001b0801000041000000000010043f0000004101000039000000040010043f00001b090100004100006a5c00010430000000000301001900000000040304330000000001420436000000000004004b000014390000613d00000000020000190000002003300039000000000503043300000000670504340000000089070434000000060090008c0000143a0000813d0000000009910436000000000808043300001a9b088001970000000000890435000000400870003900000000080804330000004009100039000000000089043500000060087000390000000008080433000000600910003900000000008904350000008007700039000000000707043300001a9b0770019700000080081000390000000000780435000000000606043300001a9b06600197000000a007100039000000000067043500000040055000390000000005050433000000c0061000390000000000560435000000e0011000390000000102200039000000000042004b000014160000413d000000000001042d00001b0801000041000000000010043f0000002101000039000000040010043f00001b090100004100006a5c00010430000000400400003900000000044104360000000006020433000000400510003900000000006504350000006005100039000000000006004b000014520000613d000000000700001900000020022000390000000008020433000000000008004b0000000008000039000000010800c03900000000058504360000000107700039000000000067004b000014490000413d0000000001150049000000000014043500000000020304330000000001250436000000000002004b0000147c0000613d00000000040000190000002003300039000000000503043300000000670504340000000089070434000000060090008c0000147d0000813d0000000009910436000000000808043300001a9b088001970000000000890435000000400870003900000000080804330000004009100039000000000089043500000060087000390000000008080433000000600910003900000000008904350000008007700039000000000707043300001a9b0770019700000080081000390000000000780435000000000606043300001a9b06600197000000a007100039000000000067043500000040055000390000000005050433000000c0061000390000000000560435000000e0011000390000000104400039000000000024004b000014590000413d000000000001042d00001b0801000041000000000010043f0000002101000039000000040010043f00001b090100004100006a5c00010430002800000000000200000000030100190000000102000039000000000102041a000000010010008c000021fe0000c13d0000000201000039001600000002001d001900000001001d000000000012041b0000010001300039001800000001001d0000000201100367000000000101043b000000180010008c000021cd0000813d000000000010043f0000000501000039000000200010043f000000000100041400001a980010009c00001a9801008041000000c00110021000001b0b011001c70000801002000039001a00000003001d6a5a6a550000040f0000000100200190000021cd0000613d000000000101043b000000000101041a001500000001001d0000000601000039000000200010043f000000000100041400001a980010009c00001a9801008041000000c00110021000001b0b011001c700008010020000396a5a6a550000040f00000015060000290000001a030000290000000100200190000021cd0000613d000000ff0260018f000000000101043b000000000501041a002800ff00500193000f00000002001d000000060020008c000021d50000813d0000000f02000029000000010020008c000000000400003900000001040020390000000001000416001700000001001d000000000001004b000014c70000613d000000020020008c000014c90000413d000000400100043d00001ae802000041000000000021043500000004021000390000000003000416000022170000013d000000010020008c000022310000a13d001400000005001d001200000004001d0000000201000367000000fe0260018f000700000002001d000000040020008c000014d40000c13d0000001802000029000000600220008a000000000121034f000014d50000013d000000000131034f000000000101043b001100000001001d00001a9b0010009c000021cd0000213d0000000f02000029000000020020008c0000000001000019000014e50000813d002700000001001d0000000003000415000000260330008a0000000503300210000000050020008c000014f10000c13d001900000001001d000015000000013d0000000701000029000000020010008c000014fa0000c13d0000000003000415000000250330008a0000000503300210002700010000003d000000040020008c001900010000003d0000001901000029000014e10000c13d000015000000013d00000002026001bf000000ff0220018f000000020020008c000100000003001d0000000502300270000015040000c13d000000020200003f0000000202000039000015060000013d000000040020008c00001db60000c13d0000000003000415000000240330008a0000000503300210002700020000003d000100000003001d0000000501300270000000010100003f000015080000013d000000030200003f0000000302000039001600000002001d001900000001001d00001b28010000410000000000100443000000000100041400001a980010009c00001a9801008041000000c00110021000001ac7011001c70000800b020000396a5a6a550000040f0000000100200190000021fa0000613d000000180400002900000020034000390000000202000367000000000332034f0000004004400039000000000542034f000000000505043b000000000303043b000000000101043b000000000013004b000022010000213d000000000015004b000022010000a13d0000000003000031000000240030008c0000001a09000029000021cd0000413d0000000401200370000000000101043b000000200010008c000021fb0000c13d000002440030008c000021cd0000413d0000022401200370000000000101043b000002400010008c000021fb0000c13d000002840030008c000021cd0000413d0000026401200370000000000101043b00001b2b0010009c000021f40000813d000000060110021000000260011000390000024405200370000000000505043b000000000015004b000021fb0000c13d0000012401200370000000000101043b000000180010008c000021fb0000813d000000c004400039000000000142034f000000000101043b00000000059300490000001f0550008a00001b010650019700001b0107100197000000000867013f000000000067004b000000000600001900001b0106004041000000000051004b000000000500001900001b010500804100001b010080009c000000000605c019000000000006004b000021cd0000c13d0000000005910019000000000152034f000000000101043b00001ac20010009c000021cd0000213d000000060610021000000000036300490000002005500039000000000035004b000000000600001900001b010600204100001b010330019700001b0105500197000000000735013f000000000035004b000000000300001900001b010300404100001b010070009c000000000306c019000000000003004b000021cd0000c13d000000200340008a000000000232034f000000400300043d000000000202043b000000000021004b000022080000413d001500000003001d00001b2c0030009c000021cf0000813d0000001503000029000000e002300039000000400020043f00000060043000390000006002000039001300000004001d0000000000240435000000c0023000390000000000020435000000a00230003900000000000204350000008002300039000a00000002001d00000000000204350000004002300039000900000002001d00000000000204350000000002030436000c00000002001d0000000000020435000000400200043d000e00000002001d00001aa80020009c000021cf0000213d0000001402000029000000ff0220018f0000000e03000029000000a003300039000000400030043f000000040020008c000021d50000213d0000000e0300002900000000052304360000008002300039000200000002001d000000160400002900000000004204350000006006300039000000110200002900000000002604350000004007300039000000120200002900000000002704350000001902000029001800000005001d000000000025043500001b2d0010009c000021cf0000213d000000010210003900000005012002100000003f0310003900001b0203300197000000400500043d0000000003350019000000000053004b0000000004000039000000010400403900001ac20030009c000021cf0000213d0000000100400190000021cf0000c13d001602000090003d001401e00090003d000000400030043f00000000082504360000000002000019000000400300043d00001aa80030009c000021cf0000213d000000a004300039000000400040043f000000800430003900000000000404350000006004300039000000000004043500000040043000390000000000040435000000200430003900000000000404350000000000030435000000000428001900000000003404350000002002200039000000000012004b000015b00000413d000b00000008001d001000000007001d001100000006001d001200000005001d00001b040100004100000000001004430000000001000412000000040010044300000080010000390000002400100443000000000100041400001a980010009c00001a9801008041000000c00110021000001b05011001c700008005020000396a5a6a550000040f0000000100200190000021fa0000613d000000000101043b0000001502000029000000000012043500000018010000290000000003010433000000050030008c0000001a04000029000021d50000213d0000000202000367000000000142034f000000000501043b00001a9b0050009c000021cd0000213d000d00600040003d0000000d01200360000000000401043b00001a9b0040009c000021cd0000213d000000400100043d00001ac80010009c000021cf0000213d000000c006100039000000400060043f000000200a10003900000000005a043500000000003104350000000d0600002900060040006000920000000603200360000000000303043b000000400b10003900000000003b043500080020006000920000000803200360000000000503043b000000a00c10003900000000004c04350000006003100039000000800d10003900000000005d043500000000005304350000018004600039000000000442034f000000000404043b000000010540003a000021f40000613d00001b2d0040009c000021cf0000213d00000005065002100000003f0460003900001b0207400197000000400400043d0000000007740019000000000047004b0000000008000039000000010800403900001ac20070009c000021cf0000213d0000000100800190000021cf0000c13d000000400070043f00000000075404360000001f0560018f000000000006004b0000161d0000613d00000000066700190000000002200368000000002802043c0000000007870436000000000067004b000016190000c13d000000000005004b000000130200002900000000004204350000000002010433000000050020008c000021d50000213d0000001501000029000000000401043300000000050a043300000000060c043300000000070b0433000000000303043300000000080d0433000000400100043d000000c0091000390000000000890435000000a0081000390000000000380435000000800310003900000000007304350000004003100039000000000023043500001a9b02600197000000e003100039000000000023043500001a9b025001970000006003100039000000000023043500000020021000390000000000420435000000e003000039000000000031043500001b070010009c000021cf0000213d00030000000d001d00040000000c001d00050000000b001d00190000000a001d0000010003100039000000400030043f00001a980020009c00001a98020080410000004002200210000000000101043300001a980010009c00001a98010080410000006001100210000000000121019f000000000200041400001a980020009c00001a9802008041000000c002200210000000000112019f00001ac1011001c700008010020000396a5a6a550000040f0000000b0c000029000000100b000029000000110a00002900000012090000290000001a080000290000000100200190000021cd0000613d000000130200002900000000020204330000000023020434000000000003004b0000202c0000613d000000000101043b0000000000120435000000400100043d00001aa80010009c0000001903000029000000050400002900000004060000290000000305000029000021cf0000213d000000a002100039000000400020043f000000800210003900000000000204350000006002100039000000000002043500000040021000390000000000020435000000200210003900000000000204350000000000010435000000400100043d00001ac80010009c000021cf0000213d000000c002100039000000400020043f000000a002100039000000000002043500000080021000390000000000020435000000600210003900000000000204350000004002100039000000000002043500000020021000390000000000020435000000000001043500000018010000290000000002010433000000050020008c000021d50000213d000000400100043d00001aa80010009c000021cf0000213d0000000003030433000000000404043300000000050504330000000006060433000000a007100039000000400070043f00001a9b0660019700000080071000390000000000670435000000600610003900000000005604350000004005100039000000000045043500001a9b033001970000002004100039000000000034043500000000002104350000000002090433000000000002004b0000202c0000613d00000000001c043500000002010003670000001402100360000000000202043b000000000002004b000017580000613d000000000c0000190000001602100360000000000302043b000000000200003100000000048200490000001f0440008a00001b010540019700001b0106300197000000000756013f000000000056004b000000000500001900001b0105004041000000000043004b000000000400001900001b010400804100001b010070009c000000000504c019000000000005004b000021cd0000c13d0000000004830019000000000341034f000000000303043b00001ac20030009c000021cd0000213d00000006053002100000000005520049000000200440003900001b010650019700001b0107400197000000000867013f000000000067004b000000000600001900001b0106004041000000000054004b000000000500001900001b010500204100001b010080009c000000000605c019000000000006004b000021cd0000c13d00000000003c004b0000202c0000813d0000000603c002100000000005340019000000000252004900001b030020009c000021cd0000213d000000400020008c000021cd0000413d000000400200043d00001a9c0020009c000021cf0000213d0000004003200039000000400030043f000000000351034f000000000403043b00000000034204360000002005500039000000000151034f000000000501043b00001a9b0050009c000021cd0000213d000000000053043500000000060b0433000000050060008c000021d50000213d000000400100043d00001aa80010009c000021cf0000213d00000000070a0433000000a008100039000000400080043f000000800810003900000000005804350000006005100039000000000045043500001a9b0470019700000020051000390000000000450435000000000061043500000040041000390000000000040435000000010cc0003900000000040904330000000000c4004b0000202c0000a13d0000000504c0021000000020054000390000000004950019000000000014043500000000010904330000000000c1004b0000202c0000a13d00000000010b0433000000050010008c000021d50000213d001900000005001d000000400400043d00001ac80040009c000021cf0000213d00000000050a043300000000060204330000000002030433000000c003400039000000400030043f00001a9b03200197000000a0024000390000000000320435000000800240003900000000006204350000006002400039000000000062043500001a9b055001970000002002400039000000000052043500000000001404350000004002400039000000000002043500000015020000290000000004020433000000400200043d000000e0072000390000000000370435000000c0032000390000000000630435000000a00320003900000000006304350000006003200039000000000053043500000040032000390000000000130435000000e001000039000000000112043600000000004104350000008003200039000000000003043500001b070020009c000021cf0000213d0000010003200039000000400030043f00001a980010009c00001a98010080410000004001100210000000000202043300001a980020009c00001a98020080410000006002200210000000000112019f000000000200041400001a980020009c00001a9802008041000000c002200210000000000112019f00001ac1011001c7000080100200003900180000000c001d6a5a6a550000040f000000180c000029000000100b000029000000110a00002900000012090000290000001a080000290000000100200190000021cd0000613d0000001302000029000000000202043300000000030204330000000000c3004b00000019030000290000202c0000a13d0000000002230019000000000101043b000000000012043500000002010003670000001402100360000000000202043b00000000002c004b000016a70000413d000000400100043d0000002002100039000000130300002900000000030304330000000004030433000000000004004b0000000005020019000017680000613d000000000600001900000000050200190000002003300039000000000703043300000000057504360000000106600039000000000046004b000017620000413d0000000003150049000000200430008a00000000004104350000001f0330003900001b1f043001970000000003140019000000000043004b0000000004000039000000010400403900001ac20030009c000021cf0000213d0000000100400190000021cf0000c13d000000400030043f00001a980020009c00001a98020080410000004002200210000000000101043300001a980010009c00001a98010080410000006001100210000000000121019f000000000200041400001a980020009c00001a9802008041000000c002200210000000000112019f00001ac1011001c700008010020000396a5a6a550000040f0000000b0f000029000000100e000029000000110d000029000000120c0000290000001a080000290000000100200190000021cd0000613d000000000101043b0000000a020000290000000000120435000000140100002900000020021000390000000201000367000000000221034f000000000302043b000000000200003100000000048200490000001f0440008a00001b010540019700001b0106300197000000000756013f000000000056004b000000000500001900001b0105004041000000000043004b000000000400001900001b010400804100001b010070009c000000000504c019000000000005004b000021cd0000c13d0000000004830019000000000341034f000000000303043b00001ac20030009c000021cd0000213d000000200440003900000006053002100000000005520049000000000054004b000000000600001900001b010600204100001b010550019700001b0107400197000000000857013f000000000057004b000000000500001900001b010500404100001b010080009c000000000506c019000000000005004b000021cd0000c13d0000001405100360000000000505043b000000000035004b000017f10000813d00000006065002100000000007640019000000000672004900001b030060009c000021cd0000213d000000400060008c000021cd0000413d000000400800043d00001a9c0080009c000021cf0000213d0000004006800039000000400060043f000000000671034f000000000606043b00000000096804360000002007700039000000000771034f000000000807043b00001a9b0080009c000021cd0000213d000000000089043500000000090e0433000000050090008c000021d50000213d000000400700043d00001aa80070009c000021cf0000213d000000000a0d0433000000a00b7000390000004000b0043f000000800b70003900000000008b04350000006008700039000000000068043500001a9b06a0019700000020087000390000000000680435000000000097043500000040067000390000000000060435000000010550003900000000060c0433000000000056004b0000202c0000a13d000000050650021000000000066f0019000000000076043500000000060c0433000000000056004b000017bc0000213d0000202c0000013d000000400200043d00001a9c0020009c000021cf0000213d0000004001200039000000400010043f00000001010000390000000003120436000000400100043d00001b2e0010009c000021cf0000213d001900000002001d0000008002100039000000400020043f0000006002100039000000000002043500000040021000390000000000020435000000200210003900000000000204350000000000010435001800000003001d000000000013043500001b040100004100000000001004430000000001000412000000040010044300000060010000390000002400100443000000000100041400001a980010009c00001a9801008041000000c00110021000001b05011001c700008005020000396a5a6a550000040f0000000100200190000021fa0000613d000000000101043b0000001502000029000000000012043500000002010000290000000004010433000000050040008c000021d50000213d0000001401000029000001400510008a0000000201000367000000000251034f000000000602043b00001a9b0060009c0000001808000029000021cd0000213d000000400200043d00001b2e0020009c0000001907000029000021cf0000213d0000008003200039000000400030043f0000002003200039000000000063043500000000004204350000002004500039000000000441034f000000000604043b00000040042000390000000000640435001400400050003d0000001401100360000000000101043b000000600520003900000000001504350000000001070433000000000001004b0000202c0000613d0000000000280435000000400800043d00001b2f0080009c000021cf0000213d0000002001800039000000400010043f0000000002020433000000050020008c000021d50000213d00000015060000290000000006060433000000000303043300000000040404330000000005050433000000e0078000390000000000570435000000c0078000390000000000570435000000a00580003900000000004504350000006004800039000000000024043500001a9b023001970000008003800039000000000023043500000040028000390000000000620435000000c003000039000000000031043500001b070080009c000021cf0000213d001800000008001d0000010003800039000000400030043f00001a980020009c00001a98020080410000004002200210000000000101043300001a980010009c00001a98010080410000006001100210000000000121019f000000000200041400001a980020009c00001a9802008041000000c002200210000000000112019f00001ac1011001c700008010020000396a5a6a550000040f0000000100200190000021cd0000613d000000000301043b000000180100002900000000003104350000002002000039000000400100043d0000000002210436000000000032043500001a9c0010009c000021cf0000213d0000004003100039000000400030043f00001a980020009c00001a98020080410000004002200210000000000101043300001a980010009c00001a98010080410000006001100210000000000121019f000000000200041400001a980020009c00001a9802008041000000c002200210000000000112019f00001ac1011001c700008010020000396a5a6a550000040f0000000100200190000021cd0000613d000000000101043b0000000902000029000000000012043500001b0401000041000000000010044300000000010004120000000400100443000000a0010000390000002400100443000000000100041400001a980010009c00001a9801008041000000c00110021000001b05011001c700008005020000396a5a6a550000040f0000000100200190000021fa0000613d000000000101043b000000150200002900000000001204350000001401000029000000800310008a0000000201300367000000000101043b00001a9b0010009c000021cd0000213d000000000010043f0000000201000039000000200010043f000000000100041400001a980010009c00001a9801008041000000c00110021000001b0b011001c70000801002000039001800000003001d6a5a6a550000040f00000018070000290000000100200190000021cd0000613d0000000202000367000000000372034f00000015040000290000000006040433000000000101043b000000000101041a000000000503043b00001a9b0050009c000021cd0000213d0000002004700039000000000342034f000000000703043b00001a9b0070009c000021cd0000213d0000000e030000290000000008030433000000040080008c000021d50000213d000000090300002900000000090304330000000a03000029000000000a030433000000400300043d000000c00b30003900000000008b0435000000a0083000390000000000a8043500000080083000390000000000980435000000600830003900000000007804350000004007300039000000000057043500000020053000390000000000650435000000a006400039000000000662034f000000000606043b000000e0073000390000000000670435000000c006400039000000000662034f000000000606043b00000100073000390000000000670435000000e006400039000000000662034f000000000606043b000001200730003900000000006704350000010006400039000000000662034f000000000606043b00000140073000390000000000670435001801200040003d0000001802200360000000000202043b00000180043000390000000000140435000001600130003900000000002104350000018001000039000000000013043500001b0a0030009c000021cf0000213d000001a001300039000000400010043f00001a980050009c00001a98050080410000004001500210000000000203043300001a980020009c00001a98020080410000006002200210000000000112019f000000000200041400001a980020009c00001a9802008041000000c002200210000000000112019f00001ac1011001c700008010020000396a5a6a550000040f000000120a0000290000000100200190000021cd0000613d000000000201043b0000000c0100002900000000002104350000001801000029000001400c10008a00000002010003670000000003c1034f000000000503043b00001a9b0050009c000021cd0000213d0000002003c00039000000000131034f000000000601043b00001a9b0060009c000021cd0000213d000000400100043d0000004003100039000000800400003900000000004304350000000002210436000000000300041100001a9b03300197000b00000003001d0000000000320435000000190b00002900000000030b043300000080021000390000000000320435000000a002100039000000000003004b000019410000613d0000000004000019000000200bb0003900000000070b04330000000089070434000000050090008c000021d50000213d0000000009920436000000000808043300001a9b0880019700000000008904350000004008700039000000000808043300000040092000390000000000890435000000600770003900000000070704330000006008200039000000000078043500000080022000390000000104400039000000000034004b0000192c0000413d00000000031200490000006004100039000000000034043500000000030a04330000000002320436000000000003004b000019630000613d0000000004000019000000200aa0003900000000070a04330000000089070434000000050090008c000021d50000213d0000000009920436000000000808043300001a9b088001970000000000890435000000400870003900000000080804330000004009200039000000000089043500000060087000390000000008080433000000600920003900000000008904350000008007700039000000000707043300001a9b0770019700000080082000390000000000780435000000a0022000390000000104400039000000000034004b000019490000413d000000000212004900001a980020009c00001a9802008041000000600220021000001a980010009c00001a98010080410000004001100210000000000112019f000000000200041400001a980020009c00001a9802008041000000c002200210000000000121019f00001ac1011001c70000800d02000039000000030300003900001b300400004100180000000c001d6a5a6a500000040f00000018040000290000001a080000290000000100200190000021cd0000613d0000000202000367000000000142034f0000000c030000290000000003030433001900000003001d000000000101043b001500000001001d00001a9b0010009c000021cd0000213d000001c009400039000000000192034f000000000101043b000000000300003100000000048300490000001f0440008a00001b010540019700001b0106100197000000000756013f000000000056004b000000000500001900001b0105004041000000000041004b000000000400001900001b010400804100001b010070009c000000000504c019000000000005004b000021cd0000c13d0000000004810019000000000142034f000000000101043b00001ac20010009c000021cd0000213d0000000006130049000000200540003900001b010460019700001b0107500197000000000847013f000000000047004b000000000400001900001b0104004041000000000065004b000000000600001900001b010600204100001b010080009c000000000406c019000000000004004b000021cd0000c13d0000001f0410003900001b1f044001970000003f0440003900001b1f04400197000000400700043d0000000004470019000000000074004b0000000006000039000000010600403900001ac20040009c000021cf0000213d0000000100600190000021cf0000c13d000000400040043f001400000007001d00000000041704360000000006510019000000000036004b000021cd0000213d001800000009001d000000000352034f00001b1f051001980000001f0610018f0000000002540019000019c90000613d000000000703034f0000000008040019000000007907043c0000000008980436000000000028004b000019c50000c13d000000000006004b000019d60000613d000000000353034f0000000305600210000000000602043300000000065601cf000000000656022f000000000303043b0000010005500089000000000353022f00000000035301cf000000000363019f0000000000320435000000000114001900000000000104350000001901000029000000000010043f0000000301000039000000200010043f000000000100041400001a980010009c00001a9801008041000000c00110021000001b0b011001c700008010020000396a5a6a550000040f00000001002001900000001a070000290000001809000029000021cd0000613d000000000201043b000000000102041a0000ff00001001900000220f0000c13d00001b3100100198000022120000c13d000000ff001001900000000f03000029000019f90000c13d0000001501000029001500000002001d000000190200002900000014030000296a5a584c0000040f000000150200002900000018090000290000000f030000290000001a0700002900001b3301000041000000000012041b000001c00870003900000002040003670000000c010000290000000001010433000e00000001001d002300000001001d000000040030008c00001a070000c13d000000600190008a000000000114034f000000000601043b00001a250000013d000001a001700039000000050030008c0000000001086019000000000114034f000000000601043b000000020030008c00001a250000813d000000000174034f000000000101043b00001a9b0010009c000021cd0000213d0000002002700039000000000224034f000000000202043b000000000212019f0000000001000415000000210110008a0000000501100210000000000002004b002100000000003d002100010000c03d0000000f0300002900001a4e0000c13d000000020030008c00001a2b0000c13d0000000002000415000000200220008a0000000502200210002000010000003d00001a330000013d0000000001000415000000220110008a0000000501100210002200000000003d000000020030008c00001a200000613d00000000020004150000001e0220008a0000000502200210000000030030008c00000000030000390000000103006039001e00000003001d00001a510000c13d000002000390008a000000000334034f000000000303043b000000000003004b0000000005000039000000010500c0390000000502200270000000000205001f0000000501100270000000000105001f001f00000005001d00000000010004150000001f0110008a0000000501100210000000000003004b00001a4e0000c13d0000000702000029000000040020008c00001a5a0000c13d000001600290008a000000000224034f000000000202043b000000000002004b0000000501100270000000000100003f000000010100c03f00001a5c0000613d000000400100043d00001b4102000041000021e00000013d0000000501100270000000000103001f001d00000003001d00000000010004150000001d0110008a00000005011002100000000702000029000000040020008c00001a460000613d0000000501100270000000000100003f000000400100043d001900000001001d00001a9c0010009c000021cf0000213d000000a00270003900000019050000290000004001500039000000400010043f00000020035000390000006001000039001100000003001d000000000013043500000000000504350000000f03000029000000000003004b001200000002001d00001aee0000613d000000010030008c00001bf60000613d000000020030008c00001ca70000613d000000030030008c00001d280000c13d000000000124034f000000000101043b00001a9b0010009c000021cd0000213d0000001202000029000000400320008a000000000234034f000000000202043b00001a9b0020009c000021cd0000213d001700000003001d00000017030000290000006003300039000000000334034f00000017050000290000008005500039000000000454034f000000000504043b000000000403043b00000000030004110000001907000029001800000008001d6a5a51eb0000040f000000170300002900000018090000290000001a080000290000000201000367000000000231034f000000000202043b001300000002001d00001a9b0020009c000021cd0000213d000000000281034f000000200330008a000000000331034f000000000303043b001000000003001d000000000202043b001700000002001d00001a9b0020009c000021cd0000213d00141b44008000a10000001602100360000000000302043b0000000002000031000000140420002900001b010540019700001b0106300197000000000756013f000000000056004b000000000500001900001b0105004041000000000043004b000000000400001900001b010400804100001b010070009c000000000504c019000000000491034f000000000404043b001500000004001d000000000005004b000021cd0000c13d00000000090000190000000004830019000000000341034f000000000303043b00001ac20030009c000021cd0000213d00000006053002100000000005520049000000200240003900001b010450019700001b0106200197000000000746013f000000000046004b000000000400001900001b0104004041000000000052004b000000000500001900001b010500204100001b010070009c000000000405c019000000000004004b000021cd0000c13d000000000039004b00001d220000813d000000060390021000000000022300190000002003200039000000000331034f000000000303043b00001a9b0030009c000021cd0000213d000000000121034f000000000401043b0000001701000029000000000200041100000015050000290000001906000029001800000009001d6a5a5c060000040f00000018090000290000001a0800002900000002010003670000001602100360000000000302043b0000000002000031000000140420002900001b010540019700001b0106300197000000000756013f000000000056004b000000000500001900001b0105002041000000000043004b000000000400001900001b010400404100001b010070009c000000000504c0190000000109900039000000000005004b00001ab20000c13d000021cd0000013d000000000124034f000000000101043b00001a9b0010009c000021cd0000213d0000001202000029000000400320008a000000000234034f000000000202043b00001a9b0020009c000021cd0000213d0000000005030019001800000005001d0000006003500039000000000334034f0000008005500039000000000454034f000000000504043b000000000403043b000000000300041100000019070000296a5a541c0000040f0000001a0c00002900001b4409c000990000001808000029000001a00a80003900000002010003670000000002a1034f000000000302043b0000000002000031000000000492001900001b010540019700001b0106300197000000000756013f000000000056004b000000000500001900001b0105004041000000000043004b000000000400001900001b010400804100001b010070009c000000000504c019000000200480008a000000000441034f000000000404043b001000000004001d000000000005004b000021cd0000c13d000000000b000019001400000009001d00130000000a001d0000000004c30019000000000341034f000000000303043b00001ac20030009c000021cd0000213d00000006053002100000000005520049000000200240003900001b010450019700001b0106200197000000000746013f000000000046004b000000000400001900001b0104004041000000000052004b000000000500001900001b010500204100001b010070009c000000000405c019000000000004004b000021cd0000c13d00000000003b004b00001b9f0000813d0000000603b002100000000002230019000000000321034f000000000503043b0017001700500073000021db0000413d0000002002200039000000000121034f000000000401043b00001a9b0040009c000021cd0000213d000000000005004b000021de0000613d0000000001000414000000040040008c001800000005001d001600000004001d00001b4e0000c13d00000001010000310000000102000039000000000001004b00001b620000c13d00001b890000013d00001a980010009c00001a9801008041000000c00110021000001ac1011001c700008009020000390000000003050019000000000500001900150000000b001d6a5a6a500000040f000000150b000029000000130a00002900000014090000290000001a0c000029000000010220018f0003000000010355000000600110027000011a980010019d00001a9801100197000000000001004b00001b890000613d00001ac20010009c000021cf0000213d0000001f0310003900001b1f033001970000003f0330003900001b1f04300197000000400300043d0000000004430019000000000034004b0000000005000039000000010500403900001ac20040009c000021cf0000213d0000000100500190000021cf0000c13d000000400040043f000000000613043600001b1f041001980000000003460019000000030500036700001b7c0000613d000000000705034f000000007807043c0000000006860436000000000036004b00001b780000c13d0000001f0110019000001b890000613d000000000445034f0000000301100210000000000503043300000000051501cf000000000515022f000000000404043b0000010001100089000000000414022f00000000011401cf000000000151019f0000000000130435000000000002004b000021e60000613d00000002010003670000000002a1034f000000000302043b0000000002000031000000000492001900001b010540019700001b0106300197000000000756013f000000000056004b000000000500001900001b0105002041000000000043004b000000000400001900001b010400404100001b010070009c000000000504c019000000010bb00039000000000005004b00001b200000c13d000021cd0000013d0000001003000029000000170030006b000021db0000413d0000000d01100360000000000401043b00001a9b0040009c000021cd0000213d000000100000006b000021de0000613d0000000001000414000000040040008c001800000004001d00001bb10000c13d00000001020000390000000101000031000000000001004b00001bc10000c13d00001be90000013d00001a980010009c00001a9801008041000000c00110021000001ac1011001c70000800902000039000000100300002900000000050000196a5a6a500000040f0000001a0c000029000000010220018f0003000000010355000000600110027000011a980010019d00001a9801100197000000000001004b00001be90000613d00001ac20010009c000021cf0000213d0000001f0310003900001b1f033001970000003f0330003900001b1f04300197000000400300043d0000000004430019000000000034004b0000000005000039000000010500403900001ac20040009c000021cf0000213d0000000100500190000021cf0000c13d000000400040043f000000000713043600001b1f041001980000001f0510018f0000000003470019000000030600036700001bdc0000613d000000000806034f000000008908043c0000000007970436000000000037004b00001bd80000c13d000000000005004b00001be90000613d000000000446034f0000000305500210000000000603043300000000065601cf000000000656022f000000000404043b0000010005500089000000000454022f00000000045401cf000000000464019f0000000000430435000000000002004b000022280000613d0000001003000029000000170930006b00001e760000a13d00000000020004140000000b04000029000000040040008c00001db80000c13d0000000102000039000000000001004b00001dca0000c13d00001df00000013d000000000124034f000000000101043b00001a9b0010009c000021cd0000213d0000001202000029000000400320008a000000000234034f000000000202043b00001a9b0020009c000021cd0000213d0000000005030019001800000005001d0000006003500039000000000334034f0000008005500039000000000454034f000000000504043b000000000403043b000000000300041100000019070000296a5a51eb0000040f0000001a0c00002900001b4409c000990000001808000029000001a00a80003900000002010003670000000002a1034f000000000302043b0000000002000031000000000492001900001b010540019700001b0106300197000000000756013f000000000056004b000000000500001900001b0105004041000000000043004b000000000400001900001b010400804100001b010070009c000000000504c019000000200480008a000000000441034f000000000404043b001000000004001d000000000005004b000021cd0000c13d000000000b000019001400000009001d00130000000a001d0000000004c30019000000000341034f000000000303043b00001ac20030009c000021cd0000213d00000006053002100000000005520049000000200240003900001b010450019700001b0106200197000000000746013f000000000046004b000000000400001900001b0104004041000000000052004b000000000500001900001b010500204100001b010070009c000000000405c019000000000004004b000021cd0000c13d00000000003b004b00001da40000813d0000000603b002100000000002230019000000000321034f000000000503043b0017001700500073000021db0000413d0000002002200039000000000121034f000000000401043b00001a9b0040009c000021cd0000213d000000000005004b000021de0000613d0000000001000414000000040040008c001800000005001d001600000004001d00001c560000c13d00000001010000310000000102000039000000000001004b00001c6a0000c13d00001c910000013d00001a980010009c00001a9801008041000000c00110021000001ac1011001c700008009020000390000000003050019000000000500001900150000000b001d6a5a6a500000040f000000150b000029000000130a00002900000014090000290000001a0c000029000000010220018f0003000000010355000000600110027000011a980010019d00001a9801100197000000000001004b00001c910000613d00001ac20010009c000021cf0000213d0000001f0310003900001b1f033001970000003f0330003900001b1f04300197000000400300043d0000000004430019000000000034004b0000000005000039000000010500403900001ac20040009c000021cf0000213d0000000100500190000021cf0000c13d000000400040043f000000000613043600001b1f041001980000000003460019000000030500036700001c840000613d000000000705034f000000007807043c0000000006860436000000000036004b00001c800000c13d0000001f0110019000001c910000613d000000000445034f0000000301100210000000000503043300000000051501cf000000000515022f000000000404043b0000010001100089000000000414022f00000000011401cf000000000151019f0000000000130435000000000002004b000021e60000613d00000002010003670000000002a1034f000000000302043b0000000002000031000000000492001900001b010540019700001b0106300197000000000756013f000000000056004b000000000500001900001b0105002041000000000043004b000000000400001900001b010400404100001b010070009c000000000504c019000000010bb00039000000000005004b00001c280000c13d000021cd0000013d000000000124034f000000000101043b00001a9b0010009c000021cd0000213d0000001202000029000000400320008a000000000234034f000000000202043b00001a9b0020009c000021cd0000213d001700000003001d00000017030000290000006003300039000000000334034f00000017050000290000008005500039000000000454034f000000000504043b000000000403043b00000000030004110000001907000029001800000008001d6a5a541c0000040f000000170300002900000018090000290000001a080000290000000201000367000000000231034f000000000202043b001300000002001d00001a9b0020009c000021cd0000213d000000000281034f000000200330008a000000000331034f000000000303043b001000000003001d000000000202043b001700000002001d00001a9b0020009c000021cd0000213d00141b44008000a10000001602100360000000000302043b0000000002000031000000140420002900001b010540019700001b0106300197000000000756013f000000000056004b000000000500001900001b0105004041000000000043004b000000000400001900001b010400804100001b010070009c000000000504c019000000000491034f000000000404043b001500000004001d000000000005004b000021cd0000c13d00000000090000190000000004830019000000000341034f000000000303043b00001ac20030009c000021cd0000213d00000006053002100000000005520049000000200240003900001b010450019700001b0106200197000000000746013f000000000046004b000000000400001900001b0104004041000000000052004b000000000500001900001b010500204100001b010070009c000000000405c019000000000004004b000021cd0000c13d000000000039004b00001d220000813d000000060390021000000000022300190000002003200039000000000331034f000000000303043b00001a9b0030009c000021cd0000213d000000000121034f000000000401043b0000001701000029000000000200041100000015050000290000001906000029001800000009001d6a5a5c060000040f00000018090000290000001a0800002900000002010003670000001602100360000000000302043b0000000002000031000000140420002900001b010540019700001b0106300197000000000756013f000000000056004b000000000500001900001b0105002041000000000043004b000000000400001900001b010400404100001b010070009c000000000504c0190000000109900039000000000005004b00001ce60000c13d000021cd0000013d0000001701000029000000000200041100000013030000290000001004000029000000150500002900001e730000013d000000000174034f000000000101043b000000040030008c00001df60000c13d00001a9b0010009c000021cd0000213d0000000d02400360000000000302043b00001a9b0030009c000021cd0000213d00000006024003600000000804400360000000000504043b000000000402043b000000000200041100000019070000296a5a541c0000040f0000001a0900002900000002010003670000000d02100360000000000202043b001500000002001d00001a9b0020009c000021cd0000213d0000000d020000290000004004200039000000000241034f000000000202043b001400000002001d00001a9b0020009c000021cd0000213d00001b4405900099001601600040003d0000001602100360000000000302043b0000000002000031001000000005001d000000000552001900001b010650019700001b0107300197000000000867013f000000000067004b000000000600001900001b0106004041000000000053004b000000000500001900001b010500804100001b010080009c000000000605c0190000010004400039000000000441034f000000000404043b001300000004001d000000000006004b000021cd0000c13d0000001604000029000001200440008a000000000441034f000000000804043b000000000a0000190000000004930019000000000341034f000000000303043b00001ac20030009c000021cd0000213d00000006053002100000000005520049000000200240003900001b010450019700001b0106200197000000000746013f000000000046004b000000000400001900001b0104004041000000000052004b000000000500001900001b010500204100001b010070009c000000000405c019000000000004004b000021cd0000c13d00000000003a004b00001e6e0000813d0000000603a002100000000002230019000000000321034f000000000403043b000000000848004b000021f40000413d0000002002200039000000000121034f000000000301043b00001a9b0030009c000021cd0000213d0000001401000029000000150200002900000013050000290000001906000029001800000008001d00170000000a001d6a5a5c060000040f000000170a00002900000018080000290000001a0900002900000002010003670000001602100360000000000302043b0000000002000031000000100420002900001b010540019700001b0106300197000000000756013f000000000056004b000000000500001900001b0105002041000000000043004b000000000400001900001b010400404100001b010070009c000000000504c019000000010aa00039000000000005004b00001d640000c13d000021cd0000013d0000001003000029000000170030006b000021db0000413d0000000d01100360000000000401043b00001a9b0040009c000021cd0000213d000000100000006b000021de0000613d0000000001000414000000040040008c001800000004001d000021470000c13d00000001020000390000000101000031000000000001004b000021570000c13d0000217f0000013d0000000301000039000014dd0000013d00001a980020009c00001a9802008041000000c00120021000001ac1011001c7000080090200003900000000030900190000000005000019001800000009001d6a5a6a500000040f00000018090000290000001a0c000029000000010220018f0003000000010355000000600110027000011a980010019d00001a9801100197000000000001004b00001df00000613d0000001f0310003900001b1f033001970000003f0330003900001b1f04300197000000400300043d0000000004430019000000000034004b0000000005000039000000010500403900001ac20040009c000021cf0000213d0000000100500190000021cf0000c13d000000400040043f000000000613043600001b1f031001980000001f0410018f0000000001360019000000030500036700001de30000613d000000000705034f000000007807043c0000000006860436000000000016004b00001ddf0000c13d000000000004004b00001df00000613d000000000335034f0000000304400210000000000501043300000000054501cf000000000545022f000000000303043b0000010004400089000000000343022f00000000034301cf000000000353019f0000000000310435000000000002004b00001e760000c13d000000400100043d00000024021000390000000000920435000021c80000013d00001a9b0010009c000021cd0000213d0000000d02400360000000000302043b00001a9b0030009c000021cd0000213d00000006024003600000000804400360000000000504043b000000000402043b000000000200041100000019070000296a5a51eb0000040f0000001a0900002900000002010003670000000d02100360000000000202043b001500000002001d00001a9b0020009c000021cd0000213d0000000d020000290000004004200039000000000241034f000000000202043b001400000002001d00001a9b0020009c000021cd0000213d00001b4405900099001601600040003d0000001602100360000000000302043b0000000002000031001000000005001d000000000552001900001b010650019700001b0107300197000000000867013f000000000067004b000000000600001900001b0106004041000000000053004b000000000500001900001b010500804100001b010080009c000000000605c0190000010004400039000000000441034f000000000404043b001300000004001d000000000006004b000021cd0000c13d0000001604000029000001200440008a000000000441034f000000000804043b000000000a0000190000000004930019000000000341034f000000000303043b00001ac20030009c000021cd0000213d00000006053002100000000005520049000000200240003900001b010450019700001b0106200197000000000746013f000000000046004b000000000400001900001b0104004041000000000052004b000000000500001900001b010500204100001b010070009c000000000405c019000000000004004b000021cd0000c13d00000000003a004b00001e6e0000813d0000000603a002100000000002230019000000000321034f000000000403043b000000000848004b000021f40000413d0000002002200039000000000121034f000000000301043b00001a9b0030009c000021cd0000213d0000001401000029000000150200002900000013050000290000001906000029001800000008001d00170000000a001d6a5a5c060000040f000000170a00002900000018080000290000001a0900002900000002010003670000001602100360000000000302043b0000000002000031000000100420002900001b010540019700001b0106300197000000000756013f000000000056004b000000000500001900001b0105002041000000000043004b000000000400001900001b010400404100001b010070009c000000000504c019000000010aa00039000000000005004b00001e2e0000c13d000021cd0000013d0000001401000029000000150200002900000000030004110000000004080019000000130500002900000019060000296a5a5c060000040f0000001a0c000029000000110100002900000000010104330000000001010433000000000001004b00001f5a0000613d00000019010000290000000001010433001800000001001d000000400100043d001900000001001d000000200210003900001b3501000041001700000002001d000000000012043500001b040100004100000000001004430000000001000412000000040010044300000120010000390000002400100443000000000100041400001a980010009c00001a9801008041000000c00110021000001b05011001c700008005020000396a5a6a550000040f0000000100200190000021fa0000613d000000000101043b0000001904000029000000600240003900000018030000290000000000320435000000400240003900001a9b01100197000000000012043500001b040100004100000000001004430000000001000412000000040010044300000160010000390000002400100443000000000100041400001a980010009c00001a9801008041000000c00110021000001b05011001c700008005020000396a5a6a550000040f0000000100200190000021fa0000613d000000000101043b0000001904000029000000a00240003900001b3603000041000000000032043500000080024000390000000000120435000000a001000039000000000014043500001ac80040009c000021cf0000213d0000001902000029000000c001200039000000400010043f000000170100002900001a980010009c00001a98010080410000004001100210000000000202043300001a980020009c00001a98020080410000006002200210000000000112019f000000000200041400001a980020009c00001a9802008041000000c002200210000000000112019f00001ac1011001c700008010020000396a5a6a550000040f0000000100200190000021cd0000613d000000000101043b00001b3702000041000000000020044300001a9b01100197001900000001001d0000000400100443000000000100041400001a980010009c00001a9801008041000000c00110021000001b1b011001c700008002020000396a5a6a550000040f0000000100200190000021fa0000613d000000400b00043d0000002404b000390000000403b00039000000000101043b000000000001004b0000221d0000613d0000001101000029000000000201043300001b380100004100000000001b043500000020010000390000000000130435000000000302043300000000003404350000004401b00039000000000003004b0000001a0c00002900001f0c0000613d0000000004000019000000200220003900000000050204330000000067050434000000040070008c000021d50000813d0000000007710436000000000606043300001a9b0660019700000000006704350000004006500039000000000606043300001a9b06600197000000400710003900000000006704350000006006500039000000000606043300001a9b06600197000000600710003900000000006704350000008006500039000000000606043300000080071000390000000000670435000000a0055000390000000005050433000000a0061000390000000000560435000000c0011000390000000104400039000000000034004b00001eed0000413d00000000040004140000001902000029000000040020008c00001f150000c13d0000000103000031000000200030008c0000002004000039000000000403401900001f470000013d0000000001b1004900001a980010009c00001a9801008041000000600110021000001a9800b0009c00001a980300004100000000030b40190000004003300210000000000131019f00001a980040009c00001a9804008041000000c003400210000000000131019f00190000000b001d6a5a6a500000040f000000190b0000290000000003010019000000600330027000001a9803300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b001900001f350000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b00001f310000c13d000000000006004b00001f420000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000100000003001f000300000001035500000001002001900000001a0c0000290000223c0000613d0000001f01400039000000600210018f0000000001b20019000000000021004b0000000002000039000000010200403900001ac20010009c000021cf0000213d0000000100200190000021cf0000c13d000000400010043f000000200030008c000021cd0000413d00000000010b043300001b3900100198000021cd0000c13d000000600100003900000011020000290000000000120435000000400100043d001a00000001001d00001a9c0010009c000021cf0000213d0000001a020000290000004001200039000000400010043f00000001010000390000000002120436000000020100036700000000050000310000000e030000290000000000320435000000400400043d00001a9c0040009c000021cf0000213d0000004002400039000000400020043f00000001020000390000000002240436000000400600043d00001b2e0060009c000021cf0000213d0000008007600039000000400070043f000000600760003900000000000704350000004007600039000000000007043500000020076000390000000000070435000000000006043500000000006204350000001206100360000000000706043b00001a9b0070009c000021cd0000213d000000400600043d00001b2e0060009c000021cf0000213d0000008008600039000000400080043f000000010300002900000005083002700000000008080031000000050080008c000021d50000213d00000020096000390000000000790435000000000086043500000012030000290000002007300039000000000771034f000000000707043b000000400860003900000000007804350000004007300039000000000871034f000000000808043b000000600960003900000000008904350000000008040433000000000008004b0000202c0000613d00000000006204350000000006c500490000012002700039000000000221034f000000000202043b0000001f0660008a00001b010760019700001b0108200197000000000978013f000000000078004b000000000700001900001b0107004041000000000062004b000000000600001900001b010600804100001b010090009c000000000706c019000000000007004b000021cd0000c13d0000000006c20019000000000261034f000000000202043b00001ac20020009c000021cd0000213d00000006072002100000000005750049000000200660003900001b010750019700001b0108600197000000000978013f000000000078004b000000000700001900001b0107004041000000000056004b000000000500001900001b010500204100001b010090009c000000000705c019000000000007004b000021cd0000c13d00001b2d0020009c000021cf0000213d000000010820003900000005078002100000003f0570003900001b0209500197000000400500043d0000000009950019000000000059004b000000000a000039000000010a00403900001ac20090009c000021cf0000213d0000000100a00190000021cf0000c13d000000400090043f00000000088504360000000009000019000000400a00043d00001aa800a0009c000021cf0000213d000000a00ba000390000004000b0043f000000800ba0003900000000000b0435000000600ba0003900000000000b0435000000400ba0003900000000000b0435000000200ba0003900000000000b043500000000000a0435000000000b9800190000000000ab04350000002009900039000000000079004b00001fd40000413d0000000007c1034f000000000907043b00001a9b0090009c000021cd0000213d0000000d07100360000000000707043b00001a9b0070009c000021cd0000213d000000400c00043d00001aa800c0009c000021cf0000213d000000a00ac000390000004000a0043f000000270a0000290000000500a0008c000021d50000213d000000200bc0003900000000009b04350000000000ac0435000000060b100360000000000b0b043b000000400dc000390000000000bd0435000000080d100360000000000d0d043b000000800ec0003900000000007e0435000000600ec000390000000000de0435000000000d05043300000000000d004b0000202c0000613d0000000000c80435000000000c00001900000000002c004b000020320000813d000000060dc00210000000000e6d0019000000200de00039000000000dd1034f000000000f0d043b00001a9b00f0009c000021cd0000213d000000400d00043d00001aa800d0009c000021cf0000213d000000a003d00039000000400030043f0000004003d000390000000000b304350000002003d0003900000000009304350000000000ad04350000000003e1034f000000000303043b000000800ed000390000000000fe0435000000600ed0003900000000003e0435000000010cc0003900000000030504330000000000c3004b0000202c0000a13d0000000503c0021000000000038300190000000000d3043500000000030504330000000000c3004b000020090000213d00001b0801000041000000000010043f0000003201000039000000040010043f00001b090100004100006a5c000104300000002802000029000000040020008c000021d50000213d00000000060004150000001c0660008a0000000506600210000000020020008c0000203f0000613d00000000060004150000001b0660008a0000000506600210000000030020008c000021440000c13d00000008020000290000004009200039000000000291034f000000000202043b00001a9b0020009c000021cd0000213d0000000003000411000000000023004b0000000503600270000000000300003f000000010300c03f000021440000613d000000400b00043d00001b3b00b0009c000021cf0000213d0000014003b00039000000400030043f0000008008b000390000000000580435000000600ab0003900000000004a0435000000400cb0003900000000007c04350000000e0300002900000000073b043600000000030004110000000000370435000000400400043d00001b2f0040009c000021cf0000213d0000002003400039000000400030043f0000000000040435000000c005b000390000001a030000290000000000350435000000a006b000390000000000460435000000a003900039000000000331034f000000000403043b000000e003b000390000000000430435000000c004900039000000000441034f000000000d04043b0000010004b000390000000000d40435000000e009900039000000000191034f000000000901043b0000012001b00039000000000091043500001b3c09000041000000400f00043d00000000009f04350000000409f00039000000200d0000390000000000d9043500000000090b0433000000240bf0003900000000009b0435000000000707043300001a9b077001970000004409f00039000000000079043500000000070c043300001a9b077001970000006409f00039000000000079043500000000090a04330000014007000039000000840af0003900000000007a04350000016407f00039000000000a0904330000000000a704350000018407f0003900000000000a004b000020a50000613d000000000b0000190000002009900039000000000c09043300000000de0c04340000000500e0008c000021d50000213d000000000ee70436000000000d0d043300001a9b0dd001970000000000de0435000000400dc00039000000000d0d0433000000400e7000390000000000de0435000000600cc00039000000000c0c0433000000600d7000390000000000cd04350000008007700039000000010bb000390000000000ab004b000020900000413d0000000009f70049000000240990008a0000000008080433000000a40af0003900000000009a043500000000090804330000000007970436000000000009004b000020c90000613d000000000a0000190000002008800039000000000b08043300000000cd0b04340000000500d0008c000021d50000213d000000000dd70436000000000c0c043300001a9b0cc001970000000000cd0435000000400cb00039000000000c0c0433000000400d7000390000000000cd0435000000600cb00039000000000c0c0433000000600d7000390000000000cd0435000000800bb00039000000000b0b043300001a9b0bb00197000000800c7000390000000000bc0435000000a007700039000000010aa0003900000000009a004b000020af0000413d0000000008f70049000000240880008a0000000006060433000000c409f00039000000000089043500000000980604340000000006870436000000000008004b000020da0000613d0000000007000019000000000a670019000000000b790019000000000b0b04330000000000ba04350000002007700039000000000087004b000020d30000413d000000000786001900000000000704350000001f0780003900001b1f0770019700000000087600190000000006f80049000000240760008a0000000006050433000000e405f00039000000000075043500000000070604330000000005780436000000000007004b000020ef0000613d00000000080000190000002006600039000000000906043300000000059504360000000108800039000000000078004b000020e90000413d00000000030304330000010406f00039000000000036043500000000030404330000012404f0003900000000003404350000014403f00039000000000101043300000000001304350000000001000414000000040020008c000021000000c13d0000000103000031000000200030008c00000020040000390000000004034019000021310000013d0000000003f5004900001a980030009c00001a9803008041000000600330021000001a9800f0009c00001a980400004100000000040f40190000004004400210000000000343019f00001a980010009c00001a9801008041000000c001100210000000000131019f001a0000000f001d6a5a6a500000040f0000001a0f0000290000000003010019000000600330027000001a9803300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057f0019000021200000613d000000000801034f00000000090f0019000000008a08043c0000000009a90436000000000059004b0000211c0000c13d000000000006004b0000212d0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000100000003001f000300000001035500000001002001900000225a0000613d0000001f01400039000000600210018f0000000001f20019000000000021004b0000000002000039000000010200403900001ac20010009c000021cf0000213d0000000100200190000021cf0000c13d000000400010043f000000200030008c000021cd0000413d00000000020f043300001b3900200198000021cd0000c13d00001b3d0220019700001b3c0020009c000022370000c13d0000000101000039000000000011041b000000000001042d00001a980010009c00001a9801008041000000c00110021000001ac1011001c70000800902000039000000100300002900000000050000196a5a6a500000040f0000001a0c000029000000010220018f0003000000010355000000600110027000011a980010019d00001a9801100197000000000001004b0000217f0000613d00001ac20010009c000021cf0000213d0000001f0310003900001b1f033001970000003f0330003900001b1f04300197000000400300043d0000000004430019000000000034004b0000000005000039000000010500403900001ac20040009c000021cf0000213d0000000100500190000021cf0000c13d000000400040043f000000000713043600001b1f041001980000001f0510018f00000000034700190000000306000367000021720000613d000000000806034f000000008908043c0000000007970436000000000037004b0000216e0000c13d000000000005004b0000217f0000613d000000000446034f0000000305500210000000000603043300000000065601cf000000000656022f000000000404043b0000010005500089000000000454022f00000000045401cf000000000464019f0000000000430435000000000002004b000022280000613d0000001003000029000000170330006b00001e760000a13d00000000020004140000000b04000029000000040040008c001800000003001d0000218d0000c13d0000000102000039000000000001004b0000219c0000c13d000021c20000013d00001a980020009c00001a9802008041000000c00120021000001ac1011001c7000080090200003900000000050000196a5a6a500000040f0000001a0c000029000000010220018f0003000000010355000000600110027000011a980010019d00001a9801100197000000000001004b000021c20000613d0000001f0310003900001b1f033001970000003f0330003900001b1f04300197000000400300043d0000000004430019000000000034004b0000000005000039000000010500403900001ac20040009c000021cf0000213d0000000100500190000021cf0000c13d000000400040043f000000000613043600001b1f031001980000001f0410018f00000000013600190000000305000367000021b50000613d000000000705034f000000007807043c0000000006860436000000000016004b000021b10000c13d000000000004004b000021c20000613d000000000335034f0000000304400210000000000501043300000000054501cf000000000545022f000000000303043b0000010004400089000000000343022f00000000034301cf000000000353019f0000000000310435000000000002004b000000180300002900001e760000c13d000000400100043d0000002402100039000000000032043500001b3402000041000000000021043500000004021000390000000b03000029000021ee0000013d000000000100001900006a5c0001043000001b0801000041000000000010043f0000004101000039000000040010043f00001b090100004100006a5c0001043000001b0801000041000000000010043f0000002101000039000000040010043f00001b090100004100006a5c00010430000000400100043d00001b4002000041000021e00000013d000000400100043d00001b3f02000041000000000021043500001a980010009c00001a9801008041000000400110021000001aca011001c700006a5c00010430000000400100043d00000024021000390000001803000029000000000032043500001b3402000041000000000021043500000004021000390000001603000029000000000032043500001a980010009c00001a9801008041000000400110021000001b2a011001c700006a5c0001043000001b0801000041000000000010043f0000001101000039000000040010043f00001b090100004100006a5c00010430000000000001042f000000400100043d00001b4302000041000021e00000013d000000400100043d00001b1702000041000021e00000013d000000400100043d0000002402100039000000000052043500001b290200004100000000002104350000000402100039000021ee0000013d00001b4201000041000000000013043500001a980030009c00001a9803008041000000400130021000001aca011001c700006a5c00010430000000400100043d00001b1202000041000022140000013d000000400100043d00001b3202000041000000000021043500000004021000390000001903000029000000000032043500001a980010009c00001a9801008041000000400110021000001b09011001c700006a5c0001043000001b3a0100004100000000001b0435000000180100002900000000001304350000001901000029000000000014043500001a9800b0009c00001a980b0080410000004001b0021000001b2a011001c700006a5c00010430000000400100043d00000024021000390000001003000029000000000032043500001b3402000041000000000021043500000004021000390000001803000029000021ee0000013d000000400100043d00001ae802000041000000000021043500000004021000390000000000020435000022180000013d00001b3e02000041000000000021043500000004021000390000002303000029000022170000013d0000001f0530018f00001a9a06300198000000400200043d0000000004620019000022470000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000022430000c13d000000000005004b000022540000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f0000000000140435000000600130021000001a980020009c00001a98020080410000004002200210000000000112019f00006a5c000104300000001f0530018f00001a9a06300198000000400200043d0000000004620019000022650000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000022610000c13d000000000005004b000022720000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f0000000000140435000000600130021000001a980020009c00001a98020080410000004002200210000000000121019f00006a5c000104300000000203000367000000000223034f000000000402043b000000000200003100000000051200490000001f0550008a00001b010650019700001b0107400197000000000867013f000000000067004b000000000600001900001b0106002041000000000054004b000000000500001900001b010500404100001b010080009c000000000605c019000000000006004b000022a10000613d0000000004140019000000000143034f000000000101043b00001ac20010009c000022a10000213d00001b21031000d100000000022300190000002003400039000000000023004b000000000400001900001b010400204100001b010220019700001b0103300197000000000523013f000000000023004b000000000200001900001b010200404100001b010050009c000000000204c019000000000002004b000022a10000c13d000000000001042d000000000100001900006a5c0001043000001b250020009c0000231e0000813d00000005052002100000003f0450003900001b0206400197000000400400043d0000000006640019000000000046004b0000000007000039000000010700403900001ac20060009c0000231e0000213d00000001007001900000231e0000c13d000000400060043f00000000002404350000000002150019000000000032004b0000231c0000213d000000000012004b0000231a0000a13d000000020500036700000000060400190000000007010019000022c30000013d0000002006600039000000800a80003900000000009a043500000000008604350000002007700039000000000027004b0000231a0000813d000000000875034f000000000808043b00001ac20080009c0000231c0000213d0000000009180019000000000893004900001b030080009c0000231c0000213d000000a00080008c0000231c0000413d000000400800043d00001aa80080009c0000231e0000213d000000a00a8000390000004000a0043f000000000a95034f000000000a0a043b000000000ba80436000000200a900039000000000ca5034f000000000c0c043b0000000100c0008c0000231c0000213d0000000000cb0435000000200ba00039000000000bb5034f000000000b0b043b000000400c8000390000000000bc0435000000400ba00039000000000bb5034f000000000b0b043b000000600c8000390000000000bc0435000000600aa00039000000000aa5034f000000000a0a043b00001ac200a0009c0000231c0000213d000000000a9a00190000001f09a00039000000000039004b000000000b00001900001b010b00804100001b010990019700001b010c300197000000000dc9013f0000000000c9004b000000000900001900001b010900404100001b0100d0009c00000000090bc019000000000009004b0000231c0000c13d0000000009a5034f000000000b09043b00001ac200b0009c0000231e0000213d000000050cb002100000003f09c0003900001b020d900197000000400900043d000000000dd9001900000000009d004b000000000e000039000000010e00403900001ac200d0009c0000231e0000213d0000000100e001900000231e0000c13d0000004000d0043f0000000000b90435000000200aa00039000000000bca001900000000003b004b0000231c0000213d0000000000ba004b000022bc0000813d000000000c090019000000000da5034f000000000d0d043b000000200cc000390000000000dc0435000000200aa000390000000000ba004b000023120000413d000022bc0000013d0000000001040019000000000001042d000000000100001900006a5c0001043000001b0801000041000000000010043f0000004101000039000000040010043f00001b090100004100006a5c0001043000001a9b01100197000000000010043f0000000201000039000000200010043f000000000100041400001a980010009c00001a9801008041000000c00110021000001b0b011001c700008010020000396a5a6a550000040f0000000100200190000023340000613d000000000101043b000000000101041a000000000001042d000000000100001900006a5c00010430000d000000000002000300000002001d000400000001001d0000004001100039000a00000001001d0000000001010433000000000101043300001b250010009c000025140000813d00000005021002100000003f0320003900001b0203300197000000400700043d0000000003370019000000000073004b0000000004000039000000010400403900001ac20030009c000025140000213d0000000100400190000025140000c13d000000400030043f0000000001170436000700000001001d0000001f0320018f00000000010000310000000201100367000000000002004b0000235a0000613d00000007050000290000000002250019000000000401034f000000004604043c0000000005650436000000000025004b000023560000c13d000000000003004b00000004020000290000014002200039000900000002001d000000000302043300001ac20030009c000025140000213d00000005023002100000003f0420003900001b0204400197000000400600043d0000000004460019000000000064004b0000000005000039000000010500403900001ac20040009c000025140000213d0000000100500190000025140000c13d000000400040043f0000000003360436000600000003001d0000001f0320018f000000000002004b000023790000613d00000006040000290000000002240019000000001501043c0000000004540436000000000024004b000023750000c13d000d00000007001d000800000006001d000000000003004b00001b040100004100000000001004430000000001000412000000040010044300000060010000390000002400100443000000000100041400001a980010009c00001a9801008041000000c00110021000001b05011001c700008005020000396a5a6a550000040f0000000100200190000025220000613d000000000101043b000500000001001d0000000a0100002900000000010104330000000002010433000000000002004b000023d80000613d0000000004000019000b0005004002180000000b01100029000000200110003900000000010104330000000032010434000000060020008c0000251c0000813d000c00000004001d0000000003030433000000400410003900000000040404330000006005100039000000000505043300000080011000390000000006010433000000400100043d000000c0071000390000000000670435000000a0061000390000000000560435000000800510003900000000004504350000004004100039000000000024043500001a9b0230019700000060031000390000000000230435000000200210003900000005030000290000000000320435000000c003000039000000000031043500001b060010009c000025140000213d000000e003100039000000400030043f00001a980020009c00001a98020080410000004002200210000000000101043300001a980010009c00001a98010080410000006001100210000000000121019f000000000200041400001a980020009c00001a9802008041000000c002200210000000000112019f00001ac1011001c700008010020000396a5a6a550000040f00000001002001900000251a0000613d0000000d0200002900000000020204330000000c04000029000000000042004b0000250e0000a13d0000000b030000290000000702300029000000000101043b000000000012043500000001044000390000000a0100002900000000010104330000000002010433000000000024004b000023930000413d00001b040100004100000000001004430000000001000412000000040010044300000080010000390000002400100443000000000100041400001a980010009c00001a9801008041000000c00110021000001b05011001c700008005020000396a5a6a550000040f0000000100200190000025220000613d000000000101043b000a00000001001d00000009010000290000000001010433000000000001004b0000000d07000029000024400000613d0000000401000029000700600010003d0000000004000019000000070100002900000000010104330000000002010433000000000042004b0000250e0000a13d000b0005004002180000000b01100029000000200110003900000000010104330000000032010434000000050020008c0000251c0000213d000c00000004001d0000000003030433000000a0041000390000000004040433000000400510003900000000050504330000006006100039000000000606043300000080011000390000000007010433000000400100043d000000c0081000390000000000780435000000a0071000390000000000670435000000800610003900000000005604350000004005100039000000000025043500001a9b02400197000000e004100039000000000024043500001a9b023001970000006003100039000000000023043500000020021000390000000a030000290000000000320435000000e003000039000000000031043500001b070010009c000025140000213d0000010003100039000000400030043f00001a980020009c00001a98020080410000004002200210000000000101043300001a980010009c00001a98010080410000006001100210000000000121019f000000000200041400001a980020009c00001a9802008041000000c002200210000000000112019f00001ac1011001c700008010020000396a5a6a550000040f00000001002001900000251a0000613d000000080200002900000000020204330000000c04000029000000000042004b0000000d070000290000250e0000a13d0000000b030000290000000602300029000000000101043b0000000000120435000000010440003900000009010000290000000001010433000000000014004b000023f10000413d000000400100043d000000200210003900000004030000290000000034030434000d00000004001d0000000003030433000c00000003001d0000000003070433000000000003004b0000000004020019000024530000613d000000000500001900000000040200190000002007700039000000000607043300000000046404360000000105500039000000000035004b0000244d0000413d0000000003140049000000200430008a00000000004104350000001f0330003900001b1f043001970000000003140019000000000043004b0000000004000039000000010400403900001ac20030009c000025140000213d0000000100400190000025140000c13d000000400030043f00001a980020009c00001a98020080410000004002200210000000000101043300001a980010009c00001a98010080410000006001100210000000000121019f000000000200041400001a980020009c00001a9802008041000000c002200210000000000112019f00001ac1011001c700008010020000396a5a6a550000040f00000001002001900000251a0000613d000000400200043d0000002003200039000000000101043b000b00000001001d00000008070000290000000001070433000000000001004b0000000004030019000024840000613d000000000500001900000000040300190000002007700039000000000607043300000000046404360000000105500039000000000015004b0000247e0000413d0000000001240049000000200410008a00000000004204350000001f0110003900001b1f041001970000000001240019000000000041004b0000000004000039000000010400403900001ac20010009c000025140000213d0000000100400190000025140000c13d000000400010043f00001a980030009c00001a98030080410000004001300210000000000202043300001a980020009c00001a98020080410000006002200210000000000112019f000000000200041400001a980020009c00001a9802008041000000c002200210000000000112019f00001ac1011001c700008010020000396a5a6a550000040f00000001002001900000251a0000613d000000000101043b000a00000001001d000000040100002900000080011000390000000001010433000900000001001d000000040010008c0000251c0000213d000000040200002900000120012000390000000001010433000100000001001d00000100012000390000000001010433000200000001001d000000e0012000390000000001010433000500000001001d000000c0012000390000000001010433000600000001001d000000a0012000390000000001010433000700000001001d000000400100043d000800000001001d00001b0401000041000000000010044300000000010004120000000400100443000000a0010000390000002400100443000000000100041400001a980010009c00001a9801008041000000c00110021000001b05011001c700008005020000396a5a6a550000040f0000000100200190000025220000613d0000000d0200002900001a9b022001970000000c0300002900001a9b03300197000000000401043b0000000806000029000001800160003900000003050000290000000000510435000001600160003900000001050000290000000000510435000001400160003900000002050000290000000000510435000001200160003900000005050000290000000000510435000001000160003900000006050000290000000000510435000000e00160003900000007050000290000000000510435000000c00160003900000009050000290000000000510435000000a0016000390000000a05000029000000000051043500000080016000390000000b0500002900000000005104350000006001600039000000000031043500000040016000390000000000210435000000200160003900000000004104350000018002000039000000000026043500001b0a0060009c000025140000213d000001a002600039000000400020043f00001a980010009c00001a98010080410000004001100210000000000206043300001a980020009c00001a98020080410000006002200210000000000112019f000000000200041400001a980020009c00001a9802008041000000c002200210000000000112019f00001ac1011001c700008010020000396a5a6a550000040f00000001002001900000251a0000613d000000000101043b000000000001042d00001b0801000041000000000010043f0000003201000039000000040010043f00001b090100004100006a5c0001043000001b0801000041000000000010043f0000004101000039000000040010043f00001b090100004100006a5c00010430000000000100001900006a5c0001043000001b0801000041000000000010043f0000002101000039000000040010043f00001b090100004100006a5c00010430000000000001042f000d000000000002000200000001001d0000000021010434000100000002001d000300000001001d00001b250010009c000026a10000813d000000030100002900000005011002100000003f0210003900001b0202200197000000400300043d0000000002230019000800000003001d000000000032004b0000000003000039000000010300403900001ac20020009c000026a10000213d0000000100300190000026a10000c13d000000400020043f000000030200002900000008030000290000000003230436000700000003001d000000000002004b000026990000613d00000000020000190000006005000039000000400300043d00001b060030009c000026a10000213d000000e004300039000000400040043f000000c0043000390000000000540435000000a0043000390000000000540435000000400430003900000000005404350000002004300039000000000054043500000080043000390000000000040435000000600430003900000000000404350000000000030435000000070420002900000000003404350000002002200039000000000012004b000025410000413d0000000001000031000400020010036b000000000200001900000002010000290000000001010433000a00000002001d000000000021004b0000269b0000a13d000000400100043d00001b060010009c000026a10000213d0000000a020000290000000503200210000600000003001d00000001023000290000000004020433000000e002100039000000400020043f000000c00210003900000060030000390000000000320435000000a0021000390000000000320435000000400210003900000000003204350000002002100039000000000032043500000080021000390000000000020435000000600210003900000000000204350000000000010435000900000004001d0000000021040434000500000002001d0000004001100039000000000401043300000000e204043400001ac20020009c000026a10000213d00000005012002100000003f0310003900001b0203300197000000400b00043d00000000033b00190000000000b3004b0000000005000039000000010500403900001ac20030009c000026a10000213d0000000100500190000026a10000c13d000000400030043f00000000032b0436000000000002004b000025a20000613d0000000002000019000000400500043d00001b2e0050009c000026a10000213d0000008006500039000000400060043f0000006006500039000000000006043500000040065000390000000000060435000000200650003900000000000604350000000000050435000000000623001900000000005604350000002002200039000000000012004b000025910000413d000000000104043300001ac20010009c000026a10000213d00000005021002100000003f0520003900001b0205500197000000400600043d0000000005560019000d00000006001d000000000065004b0000000006000039000000010600403900001ac20050009c000026a10000213d0000000100600190000026a10000c13d000000400050043f0000000d050000290000000001150436000000000002004b000025be0000613d0000000005210019000000040600035f0000000007010019000000006806043c0000000007870436000000000057004b000025ba0000c13d0000001f002001900000000002040433000000000002004b000025ee0000613d0000000005000019000000050250021000000000062e0019000000000a06043300000000c90a0434000000060090008c000026a70000813d000000400700043d00001b2e0070009c000026a10000213d0000006006a0003900000000080c0433000000400aa00039000000000a0a0433000000000c060433000000800f7000390000004000f0043f000000600f7000390000000000cf0435000000400c7000390000000000ac043500001a9b08800197000000200a70003900000000008a0435000000000097043500000000080b0433000000000058004b0000269b0000a13d0000000008230019000000000078043500000000070b0433000000000057004b0000269b0000a13d0000000d070000290000000007070433000000000057004b0000269b0000a13d00000000021200190000000006060433000000000062043500000001055000390000000002040433000000000025004b000025c30000413d0000000901000029000000000101043300000060011000390000000001010433000c00000001001d0000000012010434000b00000001001d00001ac20020009c000026a10000213d00000005012002100000003f0310003900001b0203300197000000400e00043d00000000033e00190000000000e3004b0000000005000039000000010500403900001ac20030009c000026a10000213d0000000100500190000026a10000c13d000000400030043f00000000032e0436000000000002004b0000261b0000613d0000000002000019000000400500043d00001aa80050009c000026a10000213d000000a006500039000000400060043f000000800650003900000000000604350000006006500039000000000006043500000040065000390000000000060435000000200650003900000000000604350000000000050435000000000623001900000000005604350000002002200039000000000012004b000026080000413d0000000c01000029000000000501043300001ac20050009c000026a10000213d00000005025002100000003f0120003900001b0206100197000000400100043d0000000006610019000000000016004b0000000007000039000000010700403900001ac20060009c000026a10000213d0000000100700190000026a10000c13d000000400060043f0000000007510436000000000002004b000026360000613d0000000005270019000000040600035f0000000008070019000000006906043c0000000008980436000000000058004b000026320000c13d0000001f002001900000000c020000290000000002020433000000000002004b0000266e0000613d000000000500001900000005025002100000000b06200029000000000a06043300000000890a0434000000050090008c000026a70000213d000000400c00043d00001aa800c0009c000026a10000213d0000006006a000390000000008080433000000400da00039000000000d0d04330000000004060433000000a00aa00039000000000a0a0433000000000f0b0019000000a00bc000390000004000b0043f00001a9b0aa00197000000800bc000390000000000ab0435000000000b0f0019000000600ac0003900000000004a04350000004004c000390000000000d4043500001a9b048001970000002008c00039000000000048043500000000009c043500000000040e0433000000000054004b0000269b0000a13d00000000042300190000000000c4043500000000040e0433000000000054004b0000269b0000a13d0000000004010433000000000054004b0000269b0000a13d00000000027200190000000004060433000000000042043500000001055000390000000c020000290000000002020433000000000025004b0000263c0000413d000000400200043d00001b060020009c000026a10000213d0000000903000029000000000303043300000000040304330000012003300039000000000303043300000005050000290000000005050433000000e006200039000000400060043f000000c0062000390000000000160435000000a0012000390000000d06000029000000000061043500001b1301500197000000800520003900000000001504350000006001200039000000000031043500000040012000390000000000e1043500000020012000390000000000b1043500001a9b014001970000000000120435000000080100002900000000010104330000000a0010006c0000269b0000a13d000000060300002900000007013000290000000000210435000000080100002900000000010104330000000a0010006c0000269b0000a13d0000000a020000290000000102200039000000030020006c0000255b0000413d0000000801000029000000000001042d00001b0801000041000000000010043f0000003201000039000000040010043f00001b090100004100006a5c0001043000001b0801000041000000000010043f0000004101000039000000040010043f00001b090100004100006a5c0001043000001b0801000041000000000010043f0000002101000039000000040010043f00001b090100004100006a5c000104300012000000000002000100000009001d000300000008001d000600000005001d000000800010043f000000a00020043f000001e00030043f000001a00040043f000002000060043f000002400070043f0000028000a0043f000003600000043f000000000201043300001b250020009c000032ae0000813d00000005032002100000003f0130003900001b0204100197000000400100043d0000000004410019000000000014004b0000000005000039000000010500403900001ac20040009c000032ae0000213d0000000100500190000032ae0000c13d000000400040043f00000000052104360000001f0430018f0000000202000367000000000003004b000026d40000613d00000000033500190000000006200368000000006706043c0000000005750436000000000035004b000026d00000c13d000000000004004b000000e00010043f000000000102043b00001b3d0110019700001b450010009c0000000002000039000000010200c03900001b460010009c0000000001000039000000010100c039000000000121016f000001c00010043f000002600000043f000003200000043f000000800100043d0000000002010433000000000002004b00002d190000613d00000000020000190000000503200210000000200330003900000000011300190000000005010433000003400050043f000000a00100043d0000000004010433000000000024004b000032b40000a13d00000000011300190000000001010433000003000010043f000002800100043d000000000001004b000028810000613d0000000001000415000d00000001001d000a00000005001d0000000012050434000900000001001d000000c0012000390000000001010433000b00000001001d000c00000002001d000000a0012000390000000001010433000e00000001001d00001b28010000410000000000100443000000000100041400001a980010009c00001a9801008041000000c00110021000001ac7011001c70000800b020000396a5a6a550000040f0000000100200190000033020000613d000000000101043b0000000e0010006c0000287b0000413d0000000b0010006c0000287b0000813d0000000c0100002900000080011000390000000003010433000000050030008c000033060000813d0000000a050000290000004002500039000000000202043300001b13062001970000000901000029000000000201043300001b1304200197000000040030008c000028590000c13d000000010040008c0000000c030000290000332f0000c13d000000010060008c0000332f0000c13d0000000001000415000700000001001d000001400130003900000000010104330000006002300039000900000002001d00000000020204330000000002020433000000000012004b000033320000c13d00000080015000390000000001010433000b00000001001d000000000103043300001a9b01100197000000000010043f0000000401000039000000200010043f000000000100041400001a980010009c00001a9801008041000000c00110021000001b0b011001c700008010020000396a5a6a550000040f0000000100200190000032ba0000613d000000000101043b000000000e01041a0000000102e0003a000032ef0000613d000000000021041b0000000c010000290000004001100039000e00000001001d0000000002010433000000004702043400001ac20070009c000032ae0000213d00000005067002100000003f0160003900001b0203100197000000400100043d0000000005310019000000000015004b0000000003000039000000010300403900001ac20050009c000032ae0000213d0000000100300190000032ae0000c13d0000000c03000029000000000f03043300000009030000290000000003030433000000400050043f0000000005710436000000000007004b000027720000613d0000000007000019000000400800043d00001b2e0080009c000032ae0000213d0000008009800039000000400090043f0000006009800039000000000009043500000040098000390000000000090435000000200980003900000000000904350000000000080435000000000975001900000000008904350000002007700039000000000067004b000027610000413d0000000006020433000000000006004b0000279a0000613d000000000600001900000005076002100000000008740019000000000a08043300000000b90a0434000000050090008c000033060000213d000000400800043d00001b2e0080009c000032ae0000213d000000000b0b0433000000400ca00039000000000c0c0433000000600aa00039000000000a0a0433000000800d8000390000004000d0043f000000600d8000390000000000ad0435000000400a8000390000000000ca043500001a9b0ab00197000000200b8000390000000000ab043500000000009804350000000009010433000000000069004b000032b40000a13d000000000775001900000000008704350000000007010433000000000067004b000032b40000a13d00000001066000390000000007020433000000000076004b000027760000413d000000004703043400001ac20070009c000032ae0000213d00000005067002100000003f0260003900001b0205200197000000400200043d0000000005520019000000000025004b0000000008000039000000010800403900001ac20050009c000032ae0000213d0000000100800190000032ae0000c13d000000400050043f0000000005720436000000000007004b000027bf0000613d0000000007000019000000400800043d00001b2e0080009c000032ae0000213d0000008009800039000000400090043f0000006009800039000000000009043500000040098000390000000000090435000000200980003900000000000904350000000000080435000000000975001900000000008904350000002007700039000000000067004b000027ae0000413d0000000006030433000000000006004b000027e70000613d000000000600001900000005076002100000000008740019000000000a08043300000000b90a0434000000050090008c000033060000213d000000400800043d00001b2e0080009c000032ae0000213d000000000b0b0433000000400ca00039000000000c0c0433000000600aa00039000000000a0a0433000000800d8000390000004000d0043f000000600d8000390000000000ad0435000000400a8000390000000000ca043500001a9b0ab00197000000200b8000390000000000ab043500000000009804350000000009020433000000000069004b000032b40000a13d000000000775001900000000008704350000000007020433000000000067004b000032b40000a13d00000001066000390000000007030433000000000076004b000027c30000413d0000000c030000290000000005030433000000400400043d000000440340003900000080060000390000000000630435000000200340003900001b4b0600004100000000006304350000002406400039000000000700041100000000007604350000000007010433000000a4064000390000000000760435000000c406400039000000000007004b0000280f0000613d00000000080000190000002001100039000000000901043300000000ab0904340000000500b0008c000033060000213d000000000bb60436000000000a0a043300001a9b0aa001970000000000ab0435000000400a900039000000000a0a0433000000400b6000390000000000ab043500000060099000390000000009090433000000600a60003900000000009a043500000080066000390000000108800039000000000078004b000027fa0000413d0000000001460049000000240110008a0000006407400039000000000017043500000000070204330000000001760436000000000007004b0000282d0000613d000000000600001900000020022000390000000008020433000000009a0804340000000500a0008c000033060000213d000000000aa10436000000000909043300001a9b0990019700000000009a043500000040098000390000000009090433000000400a10003900000000009a0435000000600880003900000000080804330000006009100039000000000089043500000080011000390000000106600039000000000076004b000028180000413d0000000002410049000000240220008a000000840640003900000000002604350000000b0200002900000000620204340000000001210436000000000002004b0000283e0000613d000000000700001900000000081700190000000009760019000000000909043300000000009804350000002007700039000000000027004b000028370000413d000000000621001900000000000604350000001f0220003900001b1f0220019700000000024200490000000001210019000000200210008a00000000002404350000001f0110003900001b1f021001970000000001420019000000000021004b0000000002000039000000010200403900001ac20010009c000032ae0000213d0000000100200190000032ae0000c13d00001a9b02500197000000400010043f00000000040404330000000001000414000000040020008c0000288e0000c13d00000001010000310000000102000039000028a30000013d000000010240008a000000000062004b0000000c010000290000332f0000813d000e00000004001d000b00000006001d000000000064004b000028630000813d0000000100300190000033350000613d6a5a563f0000040f000800000001001d000000000010043f0000000301000039000000200010043f000000000100041400001a980010009c00001a9801008041000000c00110021000001b0b011001c700008010020000396a5a6a550000040f0000000100200190000032ba0000613d000000000601043b000000000306041a0000ff00003001900000287b0000c13d0000008807300270000000100130027000001b130210019800002cb00000613d000000000072004b00002cb00000413d00000000010004150000000d011000690000000001000002000002e00000043f000002c00000043f000003400500043d00000020015000390000000000010435000003000100043d00000080011000390000000000010435000003200100043d0000000102100039000003200020043f000000800100043d0000000003010433000000000032004b000026e70000413d00002d130000013d00001a980030009c00001a9803008041000000400330021000001a980040009c00001a98040080410000006004400210000000000334019f00001a980010009c00001a9801008041000000c001100210000000000113019f000c0000000e001d000b0000000f001d6a5a6a500000040f0000000b0f0000290000000c0e000029000000010220018f0003000000010355000000600110027000011a980010019d00001a9801100197000000000001004b0000008009000039000000600a000039000028cf0000613d00001ac20010009c000032ae0000213d0000001f0310003900001b1f033001970000003f0330003900001b1f03300197000000400a00043d00000000033a00190000000000a3004b0000000004000039000000010400403900001ac20030009c000032ae0000213d0000000100400190000032ae0000c13d000000400030043f00000000091a043600001b1f0410019800000000034900190000000305000367000028c20000613d000000000605034f0000000007090019000000006806043c0000000007870436000000000037004b000028be0000c13d0000001f01100190000028cf0000613d000000000445034f0000000301100210000000000503043300000000051501cf000000000515022f000000000404043b0000010001100089000000000414022f00000000011401cf000000000151019f00000000001304350000006001f002100008000000e10143000000000002004b0000291b0000613d000c00000009001d000000400100043d00001b4c0010009c000032ae0000213d000b0000000a001d000000240210003900001b4d030000410000000000320435000000440210003900000000030004140000006004000039000000000042043500001b4e020000410000000000210435000000640210003900000000000204350000000402100039000000000002043500001a980010009c00001a9801008041000000400110021000001a980030009c00001a9803008041000000c002300210000000000121019f00001b4f011001c700008006020000396a5a6a500000040f0000000100200190000033380000613d000000000101043b000000000001004b0000000c070000290000333e0000613d000000400d00043d00001b5002000041000000000e2d04360000000402d00039000000200300003900000000003204350000000b0200002900000000030204330000002402d0003900000000003204350000004404d00039000000000003004b0000290a0000613d000000000200001900000000054200190000000006270019000000000606043300000000006504350000002002200039000000000032004b000029030000413d00000000023400190000000000020435000000000500041400001a9b02100197000000040020008c0000291d0000c13d0000000006000415000000120660008a00000005066002100000000005000415000000110550008a000000050550021000000003010003670000000102000031001100000000003d001200000000003d000029410000013d000000000100001900002b330000013d000b0000000e001d0000001f0130003900001b1f011001970000000001d10049000000000141001900001a980010009c00001a9801008041000000600110021000001a9800d0009c000c0000000d001d00001a980300004100000000030d40190000004003300210000000000131019f00001a980050009c00001a9805008041000000c003500210000000000131019f6a5a6a550000040f0000000006000415000000100660008a000000050660021000000000050004150000000f0550008a00000005055002100000000003010019000000600330027000011a980030019d0003000000010355001000000000003d000f00000000003d0000000100200190000032e40000613d00001a98023001970000000c0d0000290000000b0e00002900001b1f0420019800000000034d00190000294a0000613d000000000701034f00000000080d0019000000007907043c0000000008980436000000000038004b000029460000c13d0000001f07200190000029570000613d000000000141034f0000000304700210000000000703043300000000074701cf000000000747022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000171019f00000000001304350000001f0120003900001b1f031001970000000001d30019000000000031004b0000000003000039000000010300403900001ac20010009c000032ae0000213d0000000100300190000032ae0000c13d000000400010043f00001b030020009c000032ba0000213d000000400020008c000032ba0000413d00000000030d043300001ac20030009c000032ba0000213d0000000003d300190000000007d2001900001b01027001970000001f0430003900001b0108400197000000000928013f000000000028004b000000000800001900001b0108004041000000000074004b000000000400001900001b010400804100001b010090009c000000000804c019000000000008004b000032ba0000c13d000000003803043400001ac20080009c000032ae0000213d00000005048002100000003f0440003900001b0204400197000000000414001900001ac20040009c000032ae0000213d000000400040043f000000000481043600000007088002100000000008380019000000000078004b000032ba0000213d000000000083004b000029a90000813d0000000009040019000000000a37004900001b0300a0009c000032ba0000213d0000008000a0008c000032ba0000413d000000400a00043d00001b2e00a0009c000032ae0000213d000000800ba000390000004000b0043f00000000bc0304340000000500c0008c000032ba0000213d000000000cca0436000000000b0b043300001a9b00b0009c000032ba0000213d0000000000bc0435000000400b300039000000000b0b0433000000400ca000390000000000bc0435000000600b300039000000000b0b0433000000600ca000390000000000bc04350000000009a904360000008003300039000000000083004b0000298b0000413d00000000030e043300001ac20030009c000032ba0000213d0000000003d300190000001f08300039000000000078004b000000000900001900001b010900804100001b0108800197000000000a28013f000000000028004b000000000200001900001b010200404100001b0100a0009c000000000209c019000000000002004b000032ba0000c13d000000008303043400001ac20030009c000032ae0000213d00000005023002100000003f0220003900001b0202200197000000400a00043d00000000092a0019000c0000000a001d0000000000a9004b0000000002000039000000010200403900001ac20090009c000032ae0000213d0000000100200190000032ae0000c13d000000400090043f0000000c020000290000000002320436000b00000002001d000000a0023000c90000000009820019000000000079004b000032ba0000213d000000000098004b000029fa0000813d0000000c0a000029000000000287004900001b030020009c000032ba0000213d000000a00020008c000032ba0000413d000000400300043d00001aa80030009c000032ae0000213d000000a002300039000000400020043f000000002b0804340000000500b0008c000032ba0000213d000000000bb30436000000000202043300001a9b0020009c000032ba0000213d00000000002b043500000040028000390000000002020433000000400b30003900000000002b04350000006002300039000000600b800039000000000b0b04330000000000b204350000008002800039000000000202043300001a9b0020009c000032ba0000213d000000200aa00039000000800b30003900000000002b043500000000003a0435000000a008800039000000000098004b000029d50000413d0000000502600270000000000201001f00000005025002700000000c0200002f00000000050104330000000e0200002900000000020204330000000006020433000000000056004b000032e40000213d000000000065004b00002a430000a13d00001ac20050009c000032ae0000213d00000005095002100000003f0290003900001b0202200197000000400700043d0000000003270019000000000073004b0000000002000039000000010200403900001ac20030009c000032ae0000213d0000000100200190000032ae0000c13d000000400030043f00000000085704360000000003000019000000400a00043d00001aa800a0009c000032ae0000213d000000a002a00039000000400020043f0000008002a0003900000000000204350000006002a0003900000000000204350000004002a0003900000000000204350000002002a00039000000000002043500000000000a043500000000028300190000000000a204350000002003300039000000000093004b00002a170000413d000000000006004b00002a410000613d00000000030000190000000e0200002900000000090204330000000002090433000000000032004b000032b40000a13d0000000002070433000000000032004b000032b40000a13d0000000502300210000000000a82001900000000029200190000002002200039000000000202043300000000002a04350000000002070433000000000032004b000032b40000a13d0000000103300039000000000063004b00002a2d0000413d0000000e020000290000000000720435000000000006004b00002a800000613d00000000070000190000000e0200002900000000030204330000000002030433000000000072004b000032b40000a13d0000000002010433000000000072004b000032b40000a13d000000050270021000000000033200190000002003300039000000000d030433000000009b0d04340000000500b0008c000033060000213d000000000242001900000000030204330000000400b0008c0000004008d00039000000400a30003900002a620000413d0000000002080433000000000002004b00002a620000c13d000000020bb0008a0000000000bd043500000000020a04330000000000280435000000600cd0003900000000020c0433000000800dd00039000000000e0d04330000000000e2004b000032e40000c13d000000600e300039000000000f0e04330000000000f2004b000032e40000213d0000000032030434000000050020008c000033060000213d00000000002b004b000032e40000c13d00000000020904330000000003030433000000000223013f00001a9b00200198000032e40000c13d00000000020a04330000000003080433000000000023004b000032e40000c13d0000000000fc043500000000020e043300000000002d04350000000107700039000000000067004b00002a460000413d000000000065004b00002aa50000a13d0000000e0200002900000000030204330000000002030433000000000062004b000032b40000a13d0000000002010433000000000062004b000032b40000a13d0000000508600210000000000248001900000000070204330000000029070434000000050090008c000033060000213d0000000003380019000000200330003900000000030304330000000008930436000000000202043300001a9b022001970000000000280435000000400270003900000000020204330000004008300039000000000028043500000060027000390000006007300039000000000802043300000000008704350000008003300039000000000202043300000000002304350000000106600039000000000056004b00002a820000413d0000000c010000290000000001010433000000090200002900000000040204330000000032040434000e00000003001d000000000021004b000032e40000213d000000000001004b00002af80000613d000000000600001900002aba0000013d00000000003c043500000000020f043300000000002d0435000000000208043300001a9b0220019700000000002704350000000106600039000000000016004b00002af60000813d0000000c020000290000000002020433000000000062004b000032b40000a13d0000000002040433000000000062004b000032b40000a13d00000005026002100000000e03200029000000000703043300000000ae0704340000000500e0008c000033060000213d0000000b0220002900000000080204330000000300e0008c0000004009700039000000400b80003900002ad40000a13d0000000002090433000000000002004b00002ad40000c13d000000020ee0008a0000000000e7043500000000020b04330000000000290435000000600c70003900000000020c0433000000800d70003900000000030d0433000000000032004b000032e40000c13d000000600f80003900000000030f0433000000000023004b000032e40000213d0000000025080434000000050050008c000033060000213d00000000005e004b000032e40000c13d00000000050a04330000000002020433000000000252013f00001a9b00200198000032e40000c13d00000000020b04330000000005090433000000000025004b000032e40000c13d0000008008800039000000a007700039000000000207043300001a9b0220019800002ab10000613d000000000508043300001a9b05500197000000000052004b00002ab10000613d000032e40000013d00001ac20010009c000032ae0000213d00000005061002100000003f0260003900001b0203200197000000400200043d0000000003320019000000000023004b0000000005000039000000010500403900001ac20030009c000032ae0000213d0000000100500190000032ae0000c13d000000400030043f0000000003120436000000000001004b00002b300000613d0000000007000019000000400800043d00001ac80080009c000032ae0000213d000000c005800039000000400050043f000000a0058000390000000000050435000000800580003900000000000504350000006005800039000000000005043500000040058000390000000000050435000000200580003900000000000504350000000000080435000000000537001900000000008504350000002007700039000000000067004b00002b090000413d00000000060000190000000005040433000000000065004b000032b40000a13d0000000005020433000000000065004b000032b40000a13d000000050560021000000000073500190000000e05500029000000000505043300000000005704350000000005020433000000000065004b000032b40000a13d0000000106600039000000000016004b00002b1f0000413d000000090100002900000000002104350000000101000039000000000200041500000007022000690000000002000002000000000401001900000000020004150000000d022000690000000002000002000002e00040043f000002c00010043f000000000001004b000028800000613d000000e00100043d0000000003010433000003200200043d000000000023004b000032b40000a13d00000005022002100000000001210019000000200110003900000008020000290000000000210435000002800100043d000000010110008a000002800010043f000003400200043d000000000302043300000040013000390000000001010433000002200010043f00000080033000390000000003030433000002a00030043f000000040030008c000033060000213d000003600400043d000000000004004b00002b5e0000c13d000000020030008c00002b5e0000813d0000000003010433000000000003004b00002b630000c13d00002c030000013d0000000103000039000003600030043f0000000003010433000000000003004b00002c030000613d00000000080000190000000509800210000000000191001900000020011000390000000002010433000002600100043d000000000001004b00002b760000c13d0000000001020433000000050010008c000033060000213d000000000001004b000000000100001900002b750000c13d000002a00100043d000000040010008c0000000001000039000000010100c039000000010110018f000002600010043f0000008001200039000000000b010433000002c00300043d000002e00400043d000000000043004b00002b800000c13d000000600a200039000000000c0a043300002bab0000013d0000000006b300a900000000000b004b00002b860000613d0000000005b600d9000000000035004b000032ef0000c13d000000000004004b00002d0d0000613d00000000054600d900000000074500a9000000000046004b00002b8f0000413d00000000065700d9000000000046004b000032ef0000c13d000000000003004b00002d0d0000613d00000000063700d90000000000b6004b000032ff0000c13d000000600a20003900000000020a04330000000000b2004b000000000c020019000000000c05601900002baa0000613d00000000063200a9000000000002004b00002ba00000613d00000000072600d9000000000037004b000032ef0000c13d000000000c4600d900000000074c00a9000000000046004b00002ba70000413d0000000006c700d9000000000046004b000032ef0000c13d00000000033700d9000000000023004b000032ff0000c13d000000000b0500190000000000ca04350000000000b104350000000000bc004b00002be80000613d000003400100043d0000000001010433000000c0021000390000000002020433000000a0011000390000000003010433000700000002001d000000000132004b000032ef0000413d000800000003001d000900000001001d000a0000000c001d000b0000000b001d000c0000000a001d000d00000009001d000e00000008001d00001b28010000410000000000100443000000000100041400001a980010009c00001a9801008041000000c00110021000001ac7011001c70000800b020000396a5a6a550000040f0000000100200190000033020000613d000000000101043b0000000807000029000000000271004b0000000e080000290000000d090000290000000c0a0000290000000b050000290000000a040000290000000906000029000032ef0000413d000000000326004b000032ef0000413d00000000014300a9000000000004004b00002bdc0000613d00000000044100d9000000000034004b000032ef0000c13d00000000035200a9000000000005004b00002be20000613d00000000045300d9000000000024004b000032ef0000c13d000000000031001a000032ef0000413d000000070070006b00002d0d0000613d0000000001310019000000000b6100d90000000000ba0435000003000100043d000000200110003900000000020104330000000001020433000000000081004b000032b40000a13d00000020019000390000000002210019000000000202043300000060022000390000000000b20435000003000200043d000000a00220003900000000020204330000000003020433000000000083004b000032b40000a13d000000000121001900000000020a043300000000002104350000000108800039000002200100043d0000000002010433000000000028004b00002b640000413d000003400200043d0000006001000039000001800010043f000000000102043300000060011000390000000001010433000001600010043f000001400000043f000003000200043d0000004003200039000001000030043f000000c003000039000001200030043f000000c002200039000000c00020043f0000000002010433000000000002004b000028860000613d0000000002000019000000050220021000000000012100190000002001100039000000000401043300000080014000390000000003010433000002c00100043d000002e00200043d000000000021004b000000000703001900002c340000613d00000000053100a9000000000003004b00002c260000613d00000000063500d9000000000016004b000032ef0000c13d000000000002004b00002d0d0000613d00000000072500d900000000062700a9000000000025004b00002c2f0000413d00000000057600d9000000000025004b000032ef0000c13d000000000001004b00002d0d0000613d00000000051600d9000000000035004b000032ff0000c13d000001800500043d00000000064500190000000004060433000000000034004b00000000080400190000000008076019000000000021004b00002c520000613d000000000034004b00002c520000613d00000000031400a9000000000004004b00002c440000613d00000000054300d9000000000015004b000032ef0000c13d000000000002004b00002d0d0000613d00000000082300d900000000052800a9000000000023004b00002c4d0000413d00000000038500d9000000000023004b000032ef0000c13d000000000001004b00002d0d0000613d00000000011500d9000000000041004b000032ff0000c13d0000000000860435000000000078004b00002c8f0000613d000003400100043d0000000001010433000001200200043d00000000021200190000000002020433000000a0011000390000000003010433000900000002001d000000000132004b000032ef0000413d000a00000003001d000b00000001001d000c00000008001d000d00000007001d000e00000006001d00001b28010000410000000000100443000000000100041400001a980010009c00001a9801008041000000c00110021000001ac7011001c70000800b020000396a5a6a550000040f0000000100200190000033020000613d000000000101043b0000000a08000029000000000181004b0000000e060000290000000d050000290000000c040000290000000b07000029000032ef0000413d000000000317004b000032ef0000413d000000090080006b000032ef0000613d00000000024300a9000000000004004b00002c810000613d00000000044200d9000000000034004b000032ef0000c13d00000000035100a9000000000005004b00002c870000613d00000000045300d9000000000014004b000032ef0000c13d000000000032001a000032ef0000413d000000010170008a0000000002320019000000000021001a000032ef0000413d000000000121001900000000077100d90000000000760435000001000100043d00000000010104330000000003010433000001400200043d000000000023004b000032b40000a13d0000000502200210000000000112001900000020011000390000000001010433000001800200043d00000000012100190000000000710435000000c00100043d00000000010104330000000003010433000001400200043d000000000023004b000032b40000a13d00000005022002100000000001120019000000200110003900000000020604330000000000210435000001400100043d0000000102100039000001400020043f000001600100043d0000000003010433000000000032004b00002c150000413d000028860000013d000000ff0030019000002cb80000613d00001b470030009c00002cca0000813d0000000e0500002900000010015002100000000b0400002900002d040000013d0000000a010000290000006001100039000700000003001d00000000030104330000000c01000029000000000101043300001a9b01100197000900000002001d0000000802000029000c00000006001d000a00000007001d6a5a584c0000040f000000070300002900000009020000290000000a070000290000000c0600002900001b470030009c00002cb40000413d0000000b01000029000000010010008c0000000e0500002900002cd30000c13d00000000050700190000000001250019000000000071004b00002ce00000213d00002ce30000013d000000000017004b00002cda0000c13d00000000070100190000000001250019000000000071004b00002ce00000213d00002ce30000013d00000000055700a900000000071700a900000000021200a90000000001250019000000000071004b00002ce30000a13d000000000527004b000032ef0000413d0000000001070019000000000271019f00001b480020009c00002ce80000813d000000000407001900002d020000013d000000000007004b00002cf20000613d00000000030700190000000004010019000000000203001900000000302400d9000000000003004b000000000402001900002cec0000c13d00002cf50000013d000000000001004b000000000201001900002d0a0000613d0000000004050019000000000302001900000000203400d9000000000002004b000000000403001900002cf60000c13d00000000013100d900001b130010009c000032ef0000213d00000000043700d900001b130040009c000032ef0000213d00000000053500d9000000100110021000001b31011001970000008802400210000000000121019f00000001011001bf000000000016041b00001b130150019700002b370000013d000000000005004b000000000305001900002cfb0000c13d00001b0801000041000000000010043f0000001201000039000000040010043f00001b090100004100006a5c00010430000002600100043d000000000001004b00002d190000613d000001c00100043d000000000001004b000033600000c13d000001e00100043d0000000001010433000a00000001001d000000000001004b00002dc90000613d000000000300001900002d270000013d0000000001010433000000000001004b00002dc60000c13d0000000b0300002900000001033000390000000a0030006c00002dc90000813d000001e00100043d0000000002010433000000000032004b000032b40000a13d000b00000003001d00000005023002100000000001120019000000200110003900000000010104330000000023010434000000a00400043d0000000005040433000000000053004b000033030000813d00000005033002100000000003340019000000200330003900000000030304330000008004300039000000000404043300001b130040019800002d230000613d0000000004020433000000010040008c000033060000213d00000040021000390000000002020433000000000004004b00002d4a0000613d000000400330003900000000030304330000000004030433000000000042004b00002d4f0000413d000033290000013d000000200330003900000000030304330000000004030433000000000042004b0000332c0000813d00000005022002100000000002320019000000200220003900000000020204330000000003020433000000050030008c000033060000213d00000040042000390000000005040433000000040030008c000000030300003900000002030060390000000000320435000000600210003900000000030204330000000000340435000033160000413d00000080011000390000000001010433000000000005004b00002d200000613d000d00000001001d000900000005001d0000000003020433000000400100043d00000020020000390000000002210436000000000032043500001a9c0010009c000032ae0000213d0000004003100039000000400030043f00001a980020009c00001a98020080410000004002200210000000000101043300001a980010009c00001a98010080410000006001100210000000000121019f000000000200041400001a980020009c00001a9802008041000000c002200210000000000112019f00001ac1011001c700008010020000396a5a6a550000040f0000000100200190000032ba0000613d000000000101043b0000000d020000290000000032020434000c00000003001d000000000002004b00002dc40000613d0000000003000019000e00000003001d00000005023002100000000c05200029000000400200043d000000400420003900000020032000390000000005050433000000000051004b00002da30000a13d000000000053043500000000001404350000004001000039000000000012043500001ac50020009c000032ae0000213d0000006001200039000000400010043f00001a980030009c00001a98030080410000004001300210000000000202043300001a980020009c00001a98020080410000006002200210000000000112019f000000000200041400002db40000013d000000000013043500000000005404350000004001000039000000000012043500001ac50020009c000032ae0000213d0000006001200039000000400010043f00001a980030009c00001a98030080410000004001300210000000000202043300001a980020009c00001a98020080410000006002200210000000000112019f000000000200041400001a980020009c00001a9802008041000000c002200210000000000112019f00001ac1011001c700008010020000396a5a6a550000040f0000000100200190000032ba0000613d000000000101043b0000000e0300002900000001033000390000000d020000290000000002020433000000000023004b00002d880000413d000000090010006c00002d230000613d000000400100043d00001b5702000041000032f90000013d000000a00100043d0000000032010434000000000002004b00002dfc0000613d000000000100001900002dd20000013d0000000101100039000000000021004b00002dfc0000813d0000000504100210000000000443001900000000040404330000008005400039000000000505043300001b130050019800002dcf0000613d000000200540003900000000050504330000000065050434000000000005004b00002dea0000613d00000000070000190000000508700210000000000886001900000000080804330000000008080433000000050080008c000033060000213d000000030080008c000032d30000213d0000000107700039000000000057004b00002ddf0000413d000000400440003900000000040404330000000054040434000000000004004b00002dcf0000613d00000000060000190000000507600210000000000775001900000000070704330000000007070433000000050070008c000033060000213d000000040070008c000032d80000813d0000000106600039000000000046004b00002df00000413d00002dcf0000013d000000800100043d0000000002010433000000000002004b00002e830000613d000000e00200043d0000000103000029000d1a9b0030019b000000000c00001900002e090000013d000000010cc00039000000000301043300000000003c004b00002e830000813d00000000030204330000000000c3004b000032b40000a13d0000000503c00210000000200330003900000000042300190000000006040433000000000006004b00002e050000613d000000a00200043d00000000040204330000000000c4004b000032b40000a13d000000000223001900000000011300190000000001010433000000000101043300000000050204330000004002500039000000000402043300000020021000390000000002020433000000000301043300000020015000390000000005010433000000400100043d00000040071000390000008008000039000000000087043500000020071000390000000d0800002900000000008704350000000000610435000000000705043300000080061000390000000000760435000000a006100039000000000007004b00002e460000613d00000000080000190000002005500039000000000905043300000000ab0904340000000500b0008c000033060000213d000000000bb60436000000000a0a043300001a9b0aa001970000000000ab0435000000400a900039000000000a0a0433000000400b6000390000000000ab043500000060099000390000000009090433000000600a60003900000000009a043500000080066000390000000108800039000000000078004b00002e310000413d00000000051600490000006007100039000000000057043500000000050404330000000007560436000000000005004b00002e680000613d000000000600001900000020044000390000000008040433000000009a0804340000000500a0008c000033060000213d000000000aa70436000000000909043300001a9b0990019700000000009a043500000040098000390000000009090433000000400a70003900000000009a043500000060098000390000000009090433000000600a70003900000000009a04350000008008800039000000000808043300001a9b0880019700000080097000390000000000890435000000a0077000390000000106600039000000000056004b00002e4e0000413d000e0000000c001d00001a9b0530019700001a9b06200197000000000217004900001a980020009c00001a9802008041000000600220021000001a980010009c00001a98010080410000004001100210000000000112019f000000000200041400001a980020009c00001a9802008041000000c002200210000000000121019f00001ac1011001c70000800d02000039000000030300003900001b30040000416a5a6a500000040f0000000100200190000032ba0000613d000000800100043d000000e00200043d0000000e0c00002900002e050000013d000000060100002900001ac20010009c000032ae0000213d000000060100002900000005021002100000003f0120003900001b0201100197000000400300043d0000000004130019000c00000003001d000000000034004b0000000001000039000000010100403900001ac20040009c000032ae0000213d0000000100100190000032ae0000c13d000001a00100043d0000000003000031000000400040043f00000006040000290000000c0500002900000000004504350000000002210019000000000032004b000032ba0000213d000000000012004b00002eec0000a13d000000020400036700001b01053001970000000c07000029000000000801001900002ea90000013d000000200770003900000000006704350000002008800039000000000028004b00002eec0000813d000000000684034f000000000606043b00001ac20060009c000032ba0000213d00000000091600190000001f06900039000000000036004b000000000a00001900001b010a00804100001b0106600197000000000b56013f000000000056004b000000000600001900001b010600404100001b0100b0009c00000000060ac019000000000006004b000032ba0000c13d000000000694034f000000000a06043b00001ac200a0009c000032ae0000213d0000000506a002100000003f0660003900001b020b600197000000400600043d000000000bb6001900000000006b004b000000000c000039000000010c00403900001ac200b0009c000032ae0000213d0000000100c00190000032ae0000c13d00000020099000390000004000b0043f0000000000a60435000000060aa00210000000000a9a001900000000003a004b000032ba0000213d00000000009a004b00002ea40000a13d000000000b060019000000000c93004900001b0300c0009c000032ba0000213d0000004000c0008c000032ba0000413d000000400c00043d00001a9c00c0009c000032ae0000213d000000200bb00039000000400dc000390000004000d0043f000000000d94034f000000000d0d043b000000000ddc0436000000200e900039000000000ee4034f000000000e0e043b0000000000ed04350000000000cb043500000040099000390000000000a9004b00002ed50000413d00002ea40000013d000002400100043d000400000001001d00001ac20010009c000032ae0000213d000000040100002900000005021002100000003f0120003900001b0201100197000000400500043d0000000004150019000500000005001d000000000054004b0000000001000039000000010100403900001ac20040009c000032ae0000213d0000000100100190000032ae0000c13d000002000100043d000000400040043f0000000504000029000000040500002900000000005404350000000002120019000000000032004b000032ba0000213d000000000012004b00002f580000a13d000000020400036700001b01053001970000000507000029000000000801001900002f120000013d000000200770003900000000006704350000002008800039000000000028004b00002f550000813d000000000684034f000000000606043b00001ac20060009c000032ba0000213d00000000091600190000001f06900039000000000036004b000000000a00001900001b010a00804100001b0106600197000000000b56013f000000000056004b000000000600001900001b010600404100001b0100b0009c00000000060ac019000000000006004b000032ba0000c13d000000000694034f000000000a06043b00001ac200a0009c000032ae0000213d0000000506a002100000003f0660003900001b020b600197000000400600043d000000000bb6001900000000006b004b000000000c000039000000010c00403900001ac200b0009c000032ae0000213d0000000100c00190000032ae0000c13d00000020099000390000004000b0043f0000000000a60435000000060aa00210000000000a9a001900000000003a004b000032ba0000213d00000000009a004b00002f0d0000a13d000000000b060019000000000c93004900001b0300c0009c000032ba0000213d0000004000c0008c000032ba0000413d000000400c00043d00001a9c00c0009c000032ae0000213d000000200bb00039000000400dc000390000004000d0043f000000000d94034f000000000d0d043b000000000ddc0436000000200e900039000000000ee4034f000000000e0e043b0000000000ed04350000000000cb043500000040099000390000000000a9004b00002f3e0000413d00002f0d0000013d00000005010000290000000001010433000400000001001d0000000c010000290000000002010433000700000002001d000000040020002a000032ef0000413d00000007020000290000000401200029000200000001001d00001ac20010009c000032ae0000213d000000020100002900000005011002100000003f0210003900001b0202200197000000400300043d0000000002230019000900000003001d000000000032004b0000000003000039000000010300403900001ac20020009c000032ae0000213d0000000100300190000032ae0000c13d000000400020043f000000090200002900000002030000290000000002320436000b00000002001d000000000003004b00002f930000613d0000000002000019000000400300043d00001ac50030009c000032ae0000213d0000006004300039000000400040043f00001b070030009c000032ae0000213d0000010005300039000000400050043f00000000000404350000000004430436000000e0053000390000000000050435000000c0053000390000000000050435000000a0053000390000000000050435000000800530003900000000000504350000004005300039000000000005043500000000000404350000000b0420002900000000003404350000002002200039000000000012004b00002f780000413d000000070000006b000030cf0000613d0000000101000029000d1a9b0010019b000000000b000019000600000000001d00002fa00000013d0000000601000029000600010010003e000032ef0000613d000000010bb000390000000700b0006c000030d00000813d0000000c0100002900000000010104330000000000b1004b000032b40000a13d000000400100043d00001ac50010009c000032ae0000213d0000000502b002100000000c02200029000000a00c00043d0000002002200039000000000d0204330000006002100039000000400020043f00001b070010009c000032ae0000213d0000010003100039000000400030043f00000000000204350000000002210436000000e0031000390000000000030435000000c0031000390000000000030435000000a003100039000000000003043500000080031000390000000000030435000000400110003900000000000104350000000000020435000000400100043d00000000f20d0434000000000002004b0000330c0000613d00001ac50010009c000032ae0000213d0000006002100039000000400020043f00001b070010009c000032ae0000213d0000010003100039000000400030043f00000000000204350000000002210436000000e0031000390000000000030435000000c0031000390000000000030435000000a003100039000000000003043500000080031000390000000000030435000000400110003900000000000104350000000000020435000000400e00043d00001ac500e0009c000032ae0000213d0000006001e00039000000400010043f00001b0700e0009c000032ae0000213d0000010002e00039000000400020043f000000000001043500000000011e0436000000e002e000390000000000020435000000c002e000390000000000020435000000a002e0003900000000000204350000008002e0003900000000000204350000004002e0003900000000000204350000000000010435000000400100043d00001b060010009c000032ae0000213d000000e002100039000000400020043f000000c00210003900000060030000390000000000320435000000a002100039000000000032043500000040021000390000000000320435000000200210003900000000003204350000008002100039000000000002043500000060021000390000000000020435000000000001043500000000060d0433000000000006004b000030970000613d0000002001c0003900000000020000190000000003000019000030110000013d00000000040304330000000000030435000000000004004b0000000103000039000032cd0000613d00000000060d04330000000102200039000000000062004b000030970000813d00000005042002100000000004f400190000000005040433000000007505043400000000080c0433000000000085004b000032f70000813d0000000505500210000000000551001900000000050504330000008008500039000000000808043300001b13008001980000300e0000613d0000000007070433000000200850003900000000090804330000000008090433000000000087004b0000300e0000813d0000000506700210000000000696001900000020066000390000000006060433000000000003004b000030580000613d0000006004600039000000000a04043300000000780e04340000006009800039000000000809043300000000008a001a000032ef0000413d00000000088a0019000000000089043500000040086000390000000008080433000000000a0e04330000004009a000390000000009090433000000000089004b000032c90000c13d00000000080504330000000007070433000000000778013f00001a9b00700198000032c90000c13d000000600550003900000000050504330000004007e000390000000007070433000000000057004b000032c90000c13d00000000570a0434000000050070008c000033060000213d0000000069060434000000050090008c000033060000213d000000000097004b000032c90000c13d0000000006060433000000000705043300000000050404330000000000040435000000000476013f00001a9b00400198000032f50000c13d000000000005004b0000300d0000c13d000032cd0000013d000000003e0604340000000500e0008c000033060000213d0000000008010019000000400a00043d00001aa800a0009c000032ae0000213d0000000001030433000e00000001001d0000004003600039000000000703043300000060036000390000000006030433000000a009a00039000000400090043f0000008009a0003900000000010f0019000000000f0c0019000000000c0d0019000000000d0b00190000000d0b0000290000000000b90435000000000b0d0019000000000d0c0019000000000c0f0019000000000f0100190000006009a0003900000000006904350000004006a0003900000000007604350000000e0100002900001a9b061001970000002007a0003900000000006704350000000000ea0435000000400e00043d00001ac500e0009c000032ae0000213d0000000006050433000000600550003900000000050504330000006007e00039000000400070043f0000004007e00039000000000057043500001a9b056001970000002006e0003900000000005604350000000000ae0435000000000002004b0000000001080019000030080000613d00000000050d0433000000000025004b000032b40000a13d00000000050f0433000000000604043300000000006f0435000000000054043500000000040d0433000000000024004b000030080000213d000032b40000013d00000000010e043300000060021000390000000002020433000000000002004b0000309f0000613d0000002003e000390000008002100039000030b60000013d000000400100043d00001aa80010009c000032ae0000213d000000a002100039000000400020043f000000010200003900000000022104360000006003100039000000000003043500000040031000390000000000030435000000000002043500000080021000390000000000020435000000400e00043d00001ac500e0009c000032ae0000213d0000006003e00039000000400030043f00000000031e04360000004004e000390000000000040435000000000003043500000000020204330000000003030433000000000223013f00001a9b00200198000030c90000613d0000000601b0006c000032ef0000413d00000009020000290000000002020433000000000012004b000032b40000a13d00000005021002100000000b022000290000000000e2043500000009020000290000000002020433000000000012004b00002f9d0000213d000032b40000013d0000000001010433000000050010008c000033060000213d000000000001004b00002f9a0000c13d000030bb0000013d000600000000001d000000040000006b000032520000613d000000010c0000390000000002000019000030dc0000013d0000000601000029000600010010003e000032ef0000613d0000000a020000290000000102200039000000040020006c000032520000813d00000005010000290000000001010433000a00000002001d000000000021004b000032b40000a13d000000400100043d00001ac50010009c000032ae0000213d0000000a0200002900000005022002100000000502200029000000a00900043d0000002002200039000000000a0204330000006002100039000000400020043f00001b070010009c000032ae0000213d0000010003100039000000400030043f00000000000204350000000002210436000000e0031000390000000000030435000000c0031000390000000000030435000000a003100039000000000003043500000080031000390000000000030435000000400110003900000000000104350000000000020435000000400100043d00000000320a0434000800000003001d000000000002004b000033110000613d00001ac50010009c000032ae0000213d0000006002100039000000400020043f00001b070010009c000032ae0000213d0000010003100039000000400030043f00000000000204350000000002210436000000e0031000390000000000030435000000c0031000390000000000030435000000a003100039000000000003043500000080031000390000000000030435000000400110003900000000000104350000000000020435000000400100043d00001ac50010009c000032ae0000213d0000006002100039000000400020043f00001b070010009c000032ae0000213d0000010003100039000000400030043f00000000000204350000000002210436000000e0031000390000000000030435000000c0031000390000000000030435000000a003100039000000000003043500000080031000390000000000030435000000400110003900000000000104350000000000020435000000400b00043d00001aa800b0009c000032ae0000213d000000a001b00039000000400010043f0000008001b0003900000000000104350000006001b0003900000000000104350000004001b0003900000000000104350000002001b00039000000000001043500000000000b0435000000400e00043d00001b2e00e0009c000032ae0000213d0000008001e00039000000400010043f0000006001e00039000c00000001001d0000000000010435000000400fe0003900000000000f043500000000010e0436000d00000001001d0000000000010435000000400100043d00001aa80010009c000032ae0000213d000000a002100039000000400020043f000000800210003900000000000204350000006002100039000000000002043500000040021000390000000000020435000000200210003900000000000204350000000000010435000000400100043d00001b060010009c000032ae0000213d000000e002100039000000400020043f000000c00210003900000060030000390000000000320435000000a002100039000000000032043500000040021000390000000000320435000000200210003900000000003204350000008002100039000000000002043500000060021000390000000000020435000000000001043500000000010a0433000000000001004b000032080000613d000000200d900039000e00000000001d000000000100001900000008020000290000000d08000029000b0000000d001d000031890000013d000000010480018f00000000004f04350000000d080000290000000b0d0000290000000004060433000000000004004b000000000400003900000001040060390000000c03000029000000000043043500000000050f0433000000000005004b000000010440c1bf00000000004f0435000000000006043500000000040f0433000000000004004b000032bc0000c13d000000010110003900000000040a0433000000000041004b0000320b0000813d000000050410021000000000052400190000000004050433000000000604043300000000006e043500000000040a0433000000000014004b000032b40000a13d00000000040504330000002004400039000000000404043300000000004804350000000007090433000000000076004b0000000007000039000000010700803900000000007f0435000032bc0000813d0000000007090433000000000067004b000032b40000a13d000000050660021000000000066d001900000000060604330000008007600039000000000707043300001b1300700198000031850000613d000000400660003900000000060604330000000007060433000000000074004b000031850000813d00000005044002100000000004640019000000200440003900000000040404330000000e0000006b000031d70000613d0000006005b00039000000000805043300000060064000390000000007060433000000000087001a000032ef0000413d000000000787001900000000007504350000008005b00039000000000505043300000080074000390000000007070433000000000557013f00001a9b0050019800000000080c0019000031730000c13d00000000580b0434000000050080008c000033060000213d00000000d7040434000000050070008c000033060000213d000000000078004b00000000080c0019000031730000c13d000000000505043300000000070d0433000000000557013f00001a9b0050019800000000080c0019000031730000c13d000000400440003900000000040404330000004005b000390000000005050433000000000045004b0000000008000039000000010800c039000031730000013d0000000067040434000000050070008c000033060000213d000000400b00043d00001aa800b0009c000032ae0000213d00000000020c001900000000080604330000004006400039000000000d0604330000008006400039000000000c06043300000060064000390000000004060433000000a003b00039000000400030043f00001a9b03c00197000000800cb0003900000000003c04350000006003b0003900000000004304350000004003b000390000000000d3043500001a9b038001970000002004b00039000000000034043500000000007b0435000000000001004b000032040000613d00000000030a0433000000000013004b000000000c02001900000008020000290000000d080000290000000b0d000029000032b40000a13d000000000302043300000000040504330000000000420435000000000035043500000000030a0433000000000013004b000032b40000a13d000e0000000c001d000031770000013d000000000c020019000e0000000c001d0000000802000029000031750000013d00000000010f0433000000000001004b000032bc0000c13d000000400100043d00001ac50010009c000032ae0000213d0000006002100039000000400020043f0000004002100039000000030300002900000000003204350000002002100039000000000300041100000000003204350000000000b104350000006002b000390000000002020433000000000002004b0000321d0000613d0000008002b00039000032340000013d000000400b00043d00001aa800b0009c000032ae0000213d000000a001b00039000000400010043f0000000001cb04360000006002b0003900000000000204350000004002b00039000000000002043500000000000104350000008002b000390000000000020435000000400100043d00001ac50010009c000032ae0000213d0000006003100039000000400030043f0000000003b1043600000040041000390000000000040435000000000003043500000000030000190000000002020433000000000223013f00001a9b002001980000324c0000613d0000000a03000029000000070030002a000032ef0000413d0000000a030000290000000702300029000000060220006c000032ef0000413d00000009030000290000000003030433000000000023004b000032b40000a13d000000050320021000000009040000290000000003430019000000200330003900000000001304350000000001040433000000000021004b000030d80000213d000032b40000013d00000000020b0433000000050020008c000033060000213d000000000002004b000030d50000c13d000032380000013d0000000602000029000000000002004b0000326c0000613d000000020120006b000032ef0000413d00001ac20010009c000032ae0000213d00000005041002100000003f0240003900001b0203200197000000400200043d0000000003320019000000000023004b0000000005000039000000010500403900001ac20030009c000032ae0000213d0000000100500190000032ae0000c13d000000400030043f00000000031204360000000606000029000000020060006b000032730000c13d000900000002001d0000326e0000013d00000009010000290000000001010433000000000001004b000032a40000c13d000000400100043d00001b5d02000041000032f90000013d0000000005000019000000400600043d00001ac50060009c000032ae0000213d0000006007600039000000400070043f00001b070060009c000032ae0000213d0000010008600039000000400080043f00000000000704350000000007760436000000e0086000390000000000080435000000c0086000390000000000080435000000a008600039000000000008043500000080086000390000000000080435000000400860003900000000000804350000000000070435000000000753001900000000006704350000002005500039000000000045004b000032740000413d000000000400001900000009050000290000000005050433000000000045004b000032b40000a13d0000000005020433000000000045004b000032b40000a13d0000000505400210000000000653001900000009055000290000002005500039000000000505043300000000005604350000000005020433000000000045004b000032b40000a13d0000000104400039000000000014004b000032900000413d000900000002001d000000800100043d000000a00200043d000000e00400043d000003600600043d0000000903000029000900000003001d00000001050000296a5a5e820000040f0000000902000029000000000001042d00001b0801000041000000000010043f0000004101000039000000040010043f00001b090100004100006a5c0001043000001b0801000041000000000010043f0000003201000039000000040010043f00001b090100004100006a5c00010430000000000100001900006a5c00010430000000400200043d00001a980020009c00001a98010000410000000001024019000000400110021000001aca011001c70000000c030000290000000003030433000000000003004b000032d00000c13d00001b5b03000041000000000032043500006a5c0001043000000000010404330000000000040435000000000001004b000032f70000c13d000000400100043d00001b3f02000041000032f90000013d00001b3f03000041000000000032043500006a5c00010430000000400200043d0000002403200039000000000073043500001b5903000041000032dc0000013d000000400200043d0000002403200039000000000063043500001b5a0300004100000000003204350000000403200039000000000013043500001a980020009c00001a9802008041000000400120021000001b2a011001c700006a5c00010430000000400100043d00001b5102000041000000000021043500000004021000390000000803000029000000000032043500001a980010009c00001a9801008041000000400110021000001b09011001c700006a5c0001043000001b0801000041000000000010043f0000001101000039000000040010043f00001b090100004100006a5c00010430000000000005004b000032cd0000613d000000400100043d00001b5b02000041000000000021043500001a980010009c00001a9801008041000000400110021000001aca011001c700006a5c00010430000000400100043d00001b5202000041000032f90000013d000000000001042f0000000002020433000000010020008c000033190000a13d00001b0801000041000000000010043f0000002101000039000000040010043f00001b090100004100006a5c0001043000001b5c02000041000000000021043500000004021000390000000000020435000032ea0000013d00001b5c02000041000000000021043500000004021000390000000103000039000032e90000013d000000400100043d00001b5802000041000032f90000013d000000400300043d000e00000003001d00001b5401000041000000000013043500000004013000396a5a5b690000040f0000000e02000029000000000121004900001a980010009c00001a9801008041000000600110021000001a980020009c00001a98020080410000004002200210000000000121019f00006a5c00010430000000400100043d00001b5502000041000032f90000013d000000400100043d00001b5602000041000032f90000013d000000400100043d00001b4a02000041000032f90000013d000000400100043d00001b1502000041000032f90000013d000000400100043d00001b4902000041000032f90000013d00030000000103550000000002010019000000600220027000011a980020019d00001a9802200197000033400000013d0000000301000367000000010200003100001b1f052001980000001f0620018f000000400300043d00000000045300190000334b0000613d000000000701034f0000000008030019000000007907043c0000000008980436000000000048004b000033470000c13d000000000006004b000033580000613d000000000151034f0000000305600210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f000000000014043500001a980020009c00001a9802008041000000600120021000001a980030009c00001a98030080410000004002300210000000000112019f00006a5c00010430000000400100043d00001b5302000041000032f90000013d0009000000000002000800000001001d000400000002001d00001b250020009c000035690000813d000000040100002900000005011002100000003f0210003900001b0202200197000000400300043d0000000002230019000300000003001d000000000032004b0000000003000039000000010300403900001ac20020009c000035690000213d0000000100300190000035690000c13d000000400020043f000000040200002900000003030000290000000004230436000700000004001d000000000002004b000035650000613d00000000020000190000006006000039000000400300043d00001aa80030009c000035690000213d000000a004300039000000400040043f00001b270030009c000035690000213d0000020005300039000000400050043f000000000004043500000100053000390000000000650435000000e005300039000000000065043500000080053000390000000000650435000000600530003900000000006504350000000004430436000001e0053000390000000000050435000001c0053000390000000000050435000001a005300039000000000005043500000180053000390000000000050435000001600530003900000000000504350000014005300039000000000005043500000120053000390000000000050435000000c0053000390000000000050435000000400530003900000000000504350000000000040435000000070420002900000000003404350000002002200039000000000012004b0000337f0000413d0000000006000031000000080160006a00000002070003670000003f0110008a000200000001001d00011b010010019b0000000002000019000600000002001d0000000502200210000500000002001d0000000801200029000000000117034f000000000201043b00001b0101200197000000010310014f000000010010006c000000000100001900001b0101002041000000020020006c000000000400001900001b010400404100001b010030009c000000000104c019000000000001004b000035670000613d000000400100043d00001aa80010009c000035690000213d000000a003100039000000400030043f00001b270010009c000035690000213d00000008022000290000020004100039000000400040043f0000000000030435000001000410003900000060050000390000000000540435000000e004100039000000000054043500000080041000390000000000540435000000600410003900000000005404350000000003310436000001e0041000390000000000040435000001c0041000390000000000040435000001a004100039000000000004043500000180041000390000000000040435000001600410003900000000000404350000014004100039000000000004043500000120041000390000000000040435000000c00410003900000000000404350000004001100039000000000001043500000000000304350000000003260049000000000127034f000000000101043b0000015f0430008a00001b010540019700001b0108100197000000000958013f000000000058004b000000000500001900001b0105004041000000000041004b000000000400001900001b010400804100001b010090009c000000000504c019000000000005004b000035670000c13d0000002004200039000000000447034f000000000404043b0000001f0330008a00001b010540019700001b0108300197000000000985013f000000000085004b000000000500001900001b0105004041000000000034004b000000000300001900001b010300804100001b010090009c000000000503c019000000000005004b000035670000c13d0000000003240019000000000437034f000000000e04043b00001ac200e0009c000035670000213d0000000004e60049000000200a30003900001b010340019700001b0105a00197000000000835013f000000000035004b000000000300001900001b010300404100000000004a004b000000000400001900001b010400204100001b010080009c000000000304c019000000000003004b000035670000c13d000000400f00043d00001aa800f0009c000035690000213d000000000b2100190000000001b60049000000a002f00039000900000002001d000000400020043f00001b030010009c000035670000213d000001600010008c000035670000413d00001b2700f0009c000035690000213d0000020001f00039000000400010043f0000000001b7034f000000000101043b00001a9b0010009c000035670000213d000000090200002900000000001204350000002001b00039000000000217034f000000000202043b00001a9b0020009c000035670000213d000000c003f0003900000000002304350000002001100039000000000117034f000000000101043b00001ac20010009c000035670000213d0000000001b100190000001f02100039000000000062004b000000000300001900001b010300804100001b010420019700001b0102600197000000000524013f000000000024004b000000000400001900001b010400404100001b010050009c000000000403c019000000000004004b000035670000c13d000000000317034f000000000303043b00001ac20030009c000035690000213d00000005043002100000003f0440003900001b0204400197000000400900043d0000000004490019000000000094004b0000000005000039000000010500403900001ac20040009c000035690000213d0000000100500190000035690000c13d0000002001100039000000400040043f0000000000390435000000a0033000c90000000003130019000000000063004b000035670000213d000000000013004b000034950000a13d0000000004090019000000000516004900001b030050009c000035670000213d000000a00050008c000035670000413d000000400500043d00001aa80050009c000035690000213d000000a008500039000000400080043f000000000817034f000000000808043b000000050080008c000035670000213d0000000008850436000000200d100039000000000cd7034f000000000c0c043b00001a9b00c0009c000035670000213d00000020044000390000000000c804350000002008d00039000000000887034f000000000808043b000000400c50003900000000008c04350000004008d00039000000000887034f000000000808043b000000600c50003900000000008c04350000006008d00039000000000887034f000000000808043b000000800c50003900000000008c04350000000000540435000000a001100039000000000031004b0000346c0000413d000000e001f0003900000000009104350000006001b00039000000000117034f000000000101043b00001ac20010009c000035670000213d0000000001b100190000001f03100039000000000063004b000000000400001900001b010400804100001b0103300197000000000523013f000000000023004b000000000200001900001b010200404100001b010050009c000000000204c019000000000002004b000035670000c13d000000000217034f000000000302043b00001ac20030009c000035690000213d00000005023002100000003f0220003900001b0204200197000000400200043d0000000005420019000000000025004b0000000004000039000000010400403900001ac20050009c000035690000213d0000000100400190000035690000c13d0000002004100039000000400050043f0000000000320435000000c0013000c90000000001410019000000000061004b000035670000213d000000000041004b000034f40000a13d0000000003020019000000000546004900001b030050009c000035670000213d000000c00050008c000035670000413d000000400900043d00001ac80090009c000035690000213d000000c005900039000000400050043f000000000547034f000000000505043b000000050050008c000035670000213d00000000085904360000002005400039000000000c57034f000000000c0c043b00001a9b00c0009c000035670000213d0000000000c804350000002008500039000000000887034f000000000808043b000000400c90003900000000008c04350000004008500039000000000887034f000000000808043b000000600c90003900000000008c04350000006008500039000000000887034f000000000808043b000000800c90003900000000008c04350000008005500039000000000557034f000000000505043b00001a9b0050009c000035670000213d0000002003300039000000a00890003900000000005804350000000000930435000000c004400039000000000014004b000034c40000413d0000010001f0003900000000002104350000008001b00039000000000217034f000000000202043b000000040020008c000035670000213d0000012003f0003900000000002304350000002002100039000000000227034f000000000202043b0000014003f0003900000000002304350000004002100039000000000227034f000000000202043b0000016003f0003900000000002304350000006002100039000000000227034f000000000202043b0000018003f0003900000000002304350000008002100039000000000227034f000000000202043b000001a003f000390000000000230435000000a002100039000000000227034f000000000202043b000001c003f000390000000000230435000000c001100039000000000117034f000000000101043b0000004002f00039000000010300003900000000003204350000002002f000390000000000320435000000090200002900000000002f0435000001e002f0003900000000001204350000001f01e0003900001b1f011001970000003f0110003900001b1f02100197000000400100043d0000000002210019000000000012004b0000000003000039000000010300403900001ac20020009c000035690000213d0000000100300190000035690000c13d000000400020043f0000000002e104360000000003ae0019000000000063004b000035670000213d0000000004a7034f00001b1f05e0019800000000035200190000353e0000613d000000000804034f0000000009020019000000008a08043c0000000009a90436000000000039004b0000353a0000c13d0000001f08e001900000354b0000613d000000000454034f0000000305800210000000000803043300000000085801cf000000000858022f000000000404043b0000010005500089000000000454022f00000000045401cf000000000484019f00000000004304350000000002e2001900000000000204350000006002f000390000000000120435000000400100043d00001b2f0010009c000035690000213d0000002002100039000000400020043f00000000000104350000008002f000390000000000120435000000030300002900000000010304330000000602000029000000000021004b0000356f0000a13d000000050400002900000007014000290000000000f104350000000001030433000000000021004b0000356f0000a13d0000000102200039000000040020006c000033b10000413d0000000001030019000000000001042d000000000100001900006a5c0001043000001b0801000041000000000010043f0000004101000039000000040010043f00001b090100004100006a5c0001043000001b0801000041000000000010043f0000003201000039000000040010043f00001b090100004100006a5c000104300019000000000002000200000005001d000400000004001d000300000002001d000002800030043f000900000001001d0000000012010434000800000001001d000a00000002001d00001b250020009c000042500000813d0000000a0100002900000005021002100000003f0120003900001b0201100197000000400300043d0000000001130019001400000003001d000000000031004b0000000003000039000000010300403900001ac20010009c000042500000213d0000000100300190000042500000c13d000000400010043f00000014010000290000000a030000290000000001310436001300000001001d000000000003004b000036ef0000613d00000000010000190000006005000039000000400300043d00001b060030009c000042500000213d000000e004300039000000400040043f000000c0043000390000000000540435000000a0043000390000000000540435000000400430003900000000005404350000002004300039000000000054043500000080043000390000000000040435000000600430003900000000000404350000000000030435000000130410002900000000003404350000002001100039000000000021004b000035970000413d0000000001000031000b00020010036b000000000200001900000009010000290000000001010433000f00000002001d000000000021004b0000424a0000a13d000000400100043d00001b060010009c000042500000213d0000000f020000290000000503200210000c00000003001d00000008023000290000000004020433000000e002100039000000400020043f000000c00210003900000060030000390000000000320435000000a0021000390000000000320435000000400210003900000000003204350000002002100039000000000032043500000080021000390000000000020435000000600210003900000000000204350000000000010435000e00000004001d0000000021040434000d00000002001d0000004001100039000000000901043300000000a209043400001ac20020009c000042500000213d00000005012002100000003f0310003900001b0203300197000000400600043d0000000004360019000000000064004b0000000003000039000000010300403900001ac20040009c000042500000213d0000000100300190000042500000c13d000000400040043f000000000b260436000000000002004b000035f80000613d0000000002000019000000400400043d00001b2e0040009c000042500000213d0000008003400039000000400030043f000000600340003900000000000304350000004003400039000000000003043500000020034000390000000000030435000000000004043500000000032b001900000000004304350000002002200039000000000012004b000035e70000413d000000000209043300001ac20020009c000042500000213d00000005012002100000003f0310003900001b0203300197000000400500043d0000000004350019001200000005001d000000000054004b0000000003000039000000010300403900001ac20040009c000042500000213d0000000100300190000042500000c13d000000400040043f0000001203000029000000000c230436000000000001004b000036140000613d00000000021c00190000000b0400035f00000000030c0019000000004504043c0000000003530436000000000023004b000036100000c13d0000001f001001900000000001090433000000000001004b000036440000613d000000000d0000190000000501d0021000000000021a0019000000000502043300000000e7050434000000060070008c000042ab0000813d000000400400043d00001b2e0040009c000042500000213d000000600250003900000000030e043300000040055000390000000005050433000000000e020433000000800f4000390000004000f0043f000000600f4000390000000000ef0435000000400e40003900000000005e043500001a9b0330019700000020054000390000000000350435000000000074043500000000030604330000000000d3004b0000424a0000a13d00000000031b0019000000000043043500000000030604330000000000d3004b0000424a0000a13d000000120300002900000000030304330000000000d3004b0000424a0000a13d0000000001c1001900000000020204330000000000210435000000010dd00039000000000109043300000000001d004b000036190000413d0000000e01000029000000000101043300000060011000390000000001010433001100000001001d0000000012010434001000000001001d00001ac20020009c000042500000213d00000005012002100000003f0310003900001b0203300197000000400900043d0000000004390019000000000094004b0000000003000039000000010300403900001ac20040009c000042500000213d0000000100300190000042500000c13d000000400040043f000000000c290436000000000002004b000036710000613d0000000002000019000000400400043d00001aa80040009c000042500000213d000000a003400039000000400030043f00000080034000390000000000030435000000600340003900000000000304350000004003400039000000000003043500000020034000390000000000030435000000000004043500000000032c001900000000004304350000002002200039000000000012004b0000365e0000413d0000001101000029000000000201043300001ac20020009c000042500000213d00000005012002100000003f0310003900001b0203300197000000400d00043d00000000043d00190000000000d4004b0000000003000039000000010300403900001ac20040009c000042500000213d0000000100300190000042500000c13d000000400040043f000000000e2d0436000000000001004b0000368c0000613d00000000021e00190000000b0400035f00000000030e0019000000004504043c0000000003530436000000000023004b000036880000c13d0000001f0010019000000011010000290000000001010433000000000001004b000036c40000613d000000000f0000190000000501f00210000000100210002900000000050204330000000034050434000000050040008c000042ab0000213d000000400700043d00001aa80070009c000042500000213d0000006002500039000000000303043300000040085000390000000008080433000000000b020433000000a0055000390000000005050433000000000a060019000000a006700039000000400060043f00001a9b055001970000008006700039000000000056043500000000060a001900000060057000390000000000b504350000004005700039000000000085043500001a9b0330019700000020057000390000000000350435000000000047043500000000030904330000000000f3004b0000424a0000a13d00000000031c0019000000000073043500000000030904330000000000f3004b0000424a0000a13d00000000030d04330000000000f3004b0000424a0000a13d0000000001e1001900000000020204330000000000210435000000010ff000390000001101000029000000000101043300000000001f004b000036920000413d000000400100043d00001b060010009c000042500000213d0000000e0200002900000000020204330000000003020433000001200220003900000000020204330000000d040000290000000004040433000000e005100039000000400050043f000000c0051000390000000000d50435000000a0051000390000001207000029000000000075043500001b13044001970000008005100039000000000045043500000060041000390000000000240435000000400210003900000000009204350000002002100039000000000062043500001a9b023001970000000000210435000000140200002900000000020204330000000f0020006c0000424a0000a13d0000000c0300002900000013023000290000000000120435000000140100002900000000010104330000000f0010006c0000424a0000a13d0000000f0200002900000001022000390000000a0020006c000035b10000413d00000009010000290000000001010433000002600000043f000700000001001d00001ac20010009c000042500000213d000000070100002900000005021002100000003f0120003900001b0201100197000000400300043d0000000001130019000600000003001d000000000031004b0000000003000039000000010300403900001ac20010009c000042500000213d0000000100300190000042500000c13d000000400010043f000000060100002900000007030000290000000001310436000500000001001d0000001f0320018f0000000201000367000000000002004b000037130000613d000000050500002900000000022500190000000004100368000000004604043c0000000005650436000000000025004b0000370f0000c13d000000000003004b000000000101043b00001b3d0210019700001b450020009c0000000001000039000000010100c03900001b460020009c0000000002000039000000010200c039001900000000003d000003600000043f00000009030000290000000003030433000000000003004b00003d400000613d00010000001201730000000001000019000037320000013d000700000000001d00000020014000390000000000010435000003400100043d00000080011000390000000000010435000003600100043d0000000101100039000003600010043f00000009020000290000000002020433000000000021004b00003d3a0000813d000000050210021000000008032000290000000004030433000002e00040043f00000014030000290000000003030433000000000013004b0000424a0000a13d00000013012000290000000001010433000003400010043f000000070000006b000037250000613d0000000001000415000d00000001001d001200000004001d0000000012040434000e00000001001d000000c0012000390000000001010433001000000001001d001100000002001d000000a0012000390000000001010433000f00000001001d00001b28010000410000000000100443000000000100041400001a980010009c00001a9801008041000000c00110021000001ac7011001c70000800b020000396a5a6a550000040f00000001002001900000428d0000613d000000000101043b0000000f03000029000000000013004b0000001004000029000042b10000213d000000000014004b000042b10000a13d000000110100002900000080011000390000000003010433000000040030008c0000001205000029000042ab0000213d0000004002500039000000000202043300001b13062001970000000e01000029000000000201043300001b1304200197000038a10000c13d000000010040008c0000001103000029000042bd0000c13d000000010060008c000042bd0000c13d000001400130003900000000010104330000006002300039000e00000002001d00000000020204330000000002020433000000000012004b000042d60000c13d00000080015000390000000001010433001000000001001d000000000103043300001a9b01100197000000000010043f0000000401000039000000200010043f000000000100041400001a980010009c00001a9801008041000000c00110021000001b0b011001c700008010020000396a5a6a550000040f0000000100200190000042560000613d000000000101043b000000000e01041a0000000102e0003a000042630000613d000000000021041b00000011010000290000004001100039001200000001001d0000000002010433000000004702043400001ac20070009c000042500000213d00000005067002100000003f0160003900001b0203100197000000400100043d0000000005310019000000000015004b0000000003000039000000010300403900001ac20050009c000042500000213d0000000100300190000042500000c13d0000001103000029000000000f0304330000000e030000290000000003030433000000400050043f0000000005710436000000000007004b000037ba0000613d0000000007000019000000400800043d00001b2e0080009c000042500000213d0000008009800039000000400090043f0000006009800039000000000009043500000040098000390000000000090435000000200980003900000000000904350000000000080435000000000975001900000000008904350000002007700039000000000067004b000037a90000413d0000000006020433000000000006004b000037e20000613d000000000600001900000005076002100000000008740019000000000a08043300000000b90a0434000000050090008c000042ab0000213d000000400800043d00001b2e0080009c000042500000213d000000000b0b0433000000400ca00039000000000c0c0433000000600aa00039000000000a0a0433000000800d8000390000004000d0043f000000600d8000390000000000ad0435000000400a8000390000000000ca043500001a9b0ab00197000000200b8000390000000000ab043500000000009804350000000009010433000000000069004b0000424a0000a13d000000000775001900000000008704350000000007010433000000000067004b0000424a0000a13d00000001066000390000000007020433000000000076004b000037be0000413d000000004703043400001ac20070009c000042500000213d00000005067002100000003f0260003900001b0205200197000000400200043d0000000005520019000000000025004b0000000008000039000000010800403900001ac20050009c000042500000213d0000000100800190000042500000c13d000000400050043f0000000005720436000000000007004b000038070000613d0000000007000019000000400800043d00001b2e0080009c000042500000213d0000008009800039000000400090043f0000006009800039000000000009043500000040098000390000000000090435000000200980003900000000000904350000000000080435000000000975001900000000008904350000002007700039000000000067004b000037f60000413d0000000006030433000000000006004b0000382f0000613d000000000600001900000005076002100000000008740019000000000a08043300000000b90a0434000000050090008c000042ab0000213d000000400800043d00001b2e0080009c000042500000213d000000000b0b0433000000400ca00039000000000c0c0433000000600aa00039000000000a0a0433000000800d8000390000004000d0043f000000600d8000390000000000ad0435000000400a8000390000000000ca043500001a9b0ab00197000000200b8000390000000000ab043500000000009804350000000009020433000000000069004b0000424a0000a13d000000000775001900000000008704350000000007020433000000000067004b0000424a0000a13d00000001066000390000000007030433000000000076004b0000380b0000413d00000011030000290000000005030433000000400400043d000000440340003900000080060000390000000000630435000000200340003900001b4b0600004100000000006304350000002406400039000000000700041100000000007604350000000007010433000000a4064000390000000000760435000000c406400039000000000007004b000038570000613d00000000080000190000002001100039000000000901043300000000ab0904340000000500b0008c000042ab0000213d000000000bb60436000000000a0a043300001a9b0aa001970000000000ab0435000000400a900039000000000a0a0433000000400b6000390000000000ab043500000060099000390000000009090433000000600a60003900000000009a043500000080066000390000000108800039000000000078004b000038420000413d0000000001460049000000240110008a0000006407400039000000000017043500000000070204330000000001760436000000000007004b000038750000613d000000000600001900000020022000390000000008020433000000009a0804340000000500a0008c000042ab0000213d000000000aa10436000000000909043300001a9b0990019700000000009a043500000040098000390000000009090433000000400a10003900000000009a0435000000600880003900000000080804330000006009100039000000000089043500000080011000390000000106600039000000000076004b000038600000413d0000000002410049000000240220008a00000084064000390000000000260435000000100200002900000000620204340000000001210436000000000002004b000038860000613d000000000700001900000000081700190000000009760019000000000909043300000000009804350000002007700039000000000027004b0000387f0000413d000000000621001900000000000604350000001f0220003900001b1f0220019700000000024200490000000001210019000000200210008a00000000002404350000001f0110003900001b1f021001970000000001420019000000000021004b0000000002000039000000010200403900001ac20010009c000042500000213d0000000100200190000042500000c13d00001a9b02500197000000400010043f00000000040404330000000001000414000000040020008c000038cc0000c13d00000001010000310000000102000039000038e10000013d000000010240008a000000000062004b0000001101000029000042bd0000813d001000000004001d000e00000006001d000000000064004b000038ab0000813d0000000100300190000042d90000613d6a5a563f0000040f000f00000001001d000000000010043f0000000301000039000000200010043f000000000100041400001a980010009c00001a9801008041000000c00110021000001b0b011001c700008010020000396a5a6a550000040f0000000100200190000042560000613d000000000601043b000000000806041a0000ff0000800190000042dc0000c13d0000008807800270000000100180027000001b130210019800000010050000290000000e04000029000038c50000613d000000000072004b000042df0000813d000000ff00800190000000060300002900003b760000613d00001b5e0080009c00003b8b0000213d000000100150021000003bc60000013d00001a980030009c00001a9803008041000000400330021000001a980040009c00001a98040080410000006004400210000000000334019f00001a980010009c00001a9801008041000000c001100210000000000113019f00110000000e001d00100000000f001d6a5a6a500000040f000000100f000029000000110e000029000000010220018f0003000000010355000000600110027000011a980010019d00001a9801100197000000000001004b0000008009000039000000600a0000390000390d0000613d00001ac20010009c000042500000213d0000001f0310003900001b1f033001970000003f0330003900001b1f03300197000000400a00043d00000000033a00190000000000a3004b0000000004000039000000010400403900001ac20030009c000042500000213d0000000100400190000042500000c13d000000400030043f00000000091a043600001b1f0410019800000000034900190000000305000367000039000000613d000000000605034f0000000007090019000000006806043c0000000007870436000000000037004b000038fc0000c13d0000001f011001900000390d0000613d000000000445034f0000000301100210000000000503043300000000051501cf000000000515022f000000000404043b0000010001100089000000000414022f00000000011401cf000000000151019f0000000000130435001100000009001d0000006001f00210000f000000e10143000000000002004b000042580000613d000000400100043d00001b4c0010009c000042500000213d00100000000a001d000000240210003900001b4d030000410000000000320435000000440210003900000000030004140000006004000039000000000042043500001b4e020000410000000000210435000000640210003900000000000204350000000402100039000000000002043500001a980010009c00001a9801008041000000400110021000001a980030009c00001a9803008041000000c002300210000000000121019f00001b4f011001c700008006020000396a5a6a500000040f0000000100200190000042e20000613d000000000101043b000000000001004b0000001107000029000042e80000613d000000400d00043d00001b5002000041000000000e2d04360000000402d0003900000020030000390000000000320435000000100200002900000000030204330000002402d0003900000000003204350000004404d00039000000000003004b000039480000613d000000000200001900000000054200190000000006270019000000000606043300000000006504350000002002200039000000000032004b000039410000413d00000000023400190000000000020435000000000500041400001a9b02100197000000040020008c000039590000c13d0000000006000415000000180660008a00000005066002100000000005000415000000170550008a000000050550021000000003010003670000000102000031001700000000003d001800000000003d0000397d0000013d00100000000e001d0000001f0130003900001b1f011001970000000001d10049000000000141001900001a980010009c00001a9801008041000000600110021000001a9800d0009c00110000000d001d00001a980300004100000000030d40190000004003300210000000000131019f00001a980050009c00001a9805008041000000c003500210000000000131019f6a5a6a550000040f0000000006000415000000160660008a00000005066002100000000005000415000000150550008a00000005055002100000000003010019000000600330027000011a980030019d0003000000010355001600000000003d001500000000003d0000000100200190000042580000613d00001a9802300197000000110d000029000000100e00002900001b1f0420019800000000034d0019000039860000613d000000000701034f00000000080d0019000000007907043c0000000008980436000000000038004b000039820000c13d0000001f07200190000039930000613d000000000141034f0000000304700210000000000703043300000000074701cf000000000747022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000171019f00000000001304350000001f0120003900001b1f031001970000000001d30019000000000031004b0000000003000039000000010300403900001ac20010009c000042500000213d0000000100300190000042500000c13d000000400010043f00001b030020009c000042560000213d000000400020008c000042560000413d00000000030d043300001ac20030009c000042560000213d0000000003d300190000000007d2001900001b01027001970000001f0430003900001b0108400197000000000928013f000000000028004b000000000800001900001b0108004041000000000074004b000000000400001900001b010400804100001b010090009c000000000804c019000000000008004b000042560000c13d000000003803043400001ac20080009c000042500000213d00000005048002100000003f0440003900001b0204400197000000000414001900001ac20040009c000042500000213d000000400040043f000000000481043600000007088002100000000008380019000000000078004b000042560000213d000000000083004b000039e50000813d0000000009040019000000000a37004900001b0300a0009c000042560000213d0000008000a0008c000042560000413d000000400a00043d00001b2e00a0009c000042500000213d000000800ba000390000004000b0043f00000000bc0304340000000500c0008c000042560000213d000000000cca0436000000000b0b043300001a9b00b0009c000042560000213d0000000000bc0435000000400b300039000000000b0b0433000000400ca000390000000000bc0435000000600b300039000000000b0b0433000000600ca000390000000000bc04350000000009a904360000008003300039000000000083004b000039c70000413d00000000030e043300001ac20030009c000042560000213d0000000003d300190000001f08300039000000000078004b000000000900001900001b010900804100001b0108800197000000000a28013f000000000028004b000000000200001900001b010200404100001b0100a0009c000000000209c019000000000002004b000042560000c13d000000008303043400001ac20030009c000042500000213d00000005023002100000003f0220003900001b0202200197000000400a00043d00000000092a001900110000000a001d0000000000a9004b0000000002000039000000010200403900001ac20090009c000042500000213d0000000100200190000042500000c13d000000400090043f00000011020000290000000002320436001000000002001d000000a0023000c90000000009820019000000000079004b000042560000213d000000000098004b00003a360000813d000000110a000029000000000287004900001b030020009c000042560000213d000000a00020008c000042560000413d000000400300043d00001aa80030009c000042500000213d000000a002300039000000400020043f000000002b0804340000000500b0008c000042560000213d000000000bb30436000000000202043300001a9b0020009c000042560000213d00000000002b043500000040028000390000000002020433000000400b30003900000000002b04350000006002300039000000600b800039000000000b0b04330000000000b204350000008002800039000000000202043300001a9b0020009c000042560000213d000000200aa00039000000800b30003900000000002b043500000000003a0435000000a008800039000000000098004b00003a110000413d0000000502600270000000000201001f0000000502500270000000110200002f0000000005010433000000120200002900000000020204330000000006020433000000000056004b000042580000213d000000000065004b00003a7f0000a13d00001ac20050009c000042500000213d00000005095002100000003f0290003900001b0202200197000000400700043d0000000003270019000000000073004b0000000002000039000000010200403900001ac20030009c000042500000213d0000000100200190000042500000c13d000000400030043f00000000085704360000000003000019000000400a00043d00001aa800a0009c000042500000213d000000a002a00039000000400020043f0000008002a0003900000000000204350000006002a0003900000000000204350000004002a0003900000000000204350000002002a00039000000000002043500000000000a043500000000028300190000000000a204350000002003300039000000000093004b00003a530000413d000000000006004b00003a7d0000613d0000000003000019000000120200002900000000090204330000000002090433000000000032004b0000424a0000a13d0000000002070433000000000032004b0000424a0000a13d0000000502300210000000000a82001900000000029200190000002002200039000000000202043300000000002a04350000000002070433000000000032004b0000424a0000a13d0000000103300039000000000063004b00003a690000413d00000012020000290000000000720435000000000006004b00003abc0000613d0000000007000019000000120200002900000000030204330000000002030433000000000072004b0000424a0000a13d0000000002010433000000000072004b0000424a0000a13d000000050270021000000000033200190000002003300039000000000d030433000000009b0d04340000000500b0008c000042ab0000213d000000000242001900000000030204330000000400b0008c0000004008d00039000000400a30003900003a9e0000413d0000000002080433000000000002004b00003a9e0000c13d000000020bb0008a0000000000bd043500000000020a04330000000000280435000000600cd0003900000000020c0433000000800dd00039000000000e0d04330000000000e2004b000042580000c13d000000600e300039000000000f0e04330000000000f2004b000042580000213d0000000032030434000000050020008c000042ab0000213d00000000002b004b000042580000c13d00000000020904330000000003030433000000000223013f00001a9b00200198000042580000c13d00000000020a04330000000003080433000000000023004b000042580000c13d0000000000fc043500000000020e043300000000002d04350000000107700039000000000067004b00003a820000413d000000000065004b00003ae10000a13d000000120200002900000000030204330000000002030433000000000062004b0000424a0000a13d0000000002010433000000000062004b0000424a0000a13d0000000508600210000000000248001900000000070204330000000029070434000000050090008c000042ab0000213d0000000003380019000000200330003900000000030304330000000008930436000000000202043300001a9b022001970000000000280435000000400270003900000000020204330000004008300039000000000028043500000060027000390000006007300039000000000802043300000000008704350000008003300039000000000202043300000000002304350000000106600039000000000056004b00003abe0000413d000000110100002900000000010104330000000e0200002900000000040204330000000032040434001200000003001d000000000021004b000042580000213d000000000001004b00003b340000613d000000000600001900003af60000013d00000000003c043500000000020f043300000000002d0435000000000208043300001a9b0220019700000000002704350000000106600039000000000016004b00003b320000813d00000011020000290000000002020433000000000062004b0000424a0000a13d0000000002040433000000000062004b0000424a0000a13d00000005026002100000001203200029000000000703043300000000ae0704340000000500e0008c000042ab0000213d000000100220002900000000080204330000000300e0008c0000004009700039000000400b80003900003b100000a13d0000000002090433000000000002004b00003b100000c13d000000020ee0008a0000000000e7043500000000020b04330000000000290435000000600c70003900000000020c0433000000800d70003900000000030d0433000000000032004b000042580000c13d000000600f80003900000000030f0433000000000023004b000042580000213d0000000025080434000000050050008c000042ab0000213d00000000005e004b000042580000c13d00000000050a04330000000002020433000000000252013f00001a9b00200198000042580000c13d00000000020b04330000000005090433000000000025004b000042580000c13d0000008008800039000000a007700039000000000207043300001a9b0220019800003aed0000613d000000000508043300001a9b05500197000000000052004b00003aed0000613d000042580000013d00001ac20010009c000042500000213d00000005061002100000003f0260003900001b0203200197000000400200043d0000000003320019000000000023004b0000000005000039000000010500403900001ac20030009c000042500000213d0000000100500190000042500000c13d000000400030043f0000000003120436000000000001004b00003b6c0000613d0000000007000019000000400800043d00001ac80080009c000042500000213d000000c005800039000000400050043f000000a0058000390000000000050435000000800580003900000000000504350000006005800039000000000005043500000040058000390000000000050435000000200580003900000000000504350000000000080435000000000537001900000000008504350000002007700039000000000067004b00003b450000413d00000000060000190000000005040433000000000065004b0000424a0000a13d0000000005020433000000000065004b0000424a0000a13d000000050560021000000000073500190000001205500029000000000505043300000000005704350000000005020433000000000065004b0000424a0000a13d0000000106600039000000000016004b00003b5b0000413d0000000e01000029000000000021043500000000010004150000000d0110006900000000010000020000000101000039000003200010043f000002c00010043f000000060300002900003bd10000013d0000001201000029000000600110003900000000030104330000001101000029000000000101043300001a9b01100197000c00000002001d0000000f02000029001200000006001d001100000007001d000b00000008001d6a5a584c0000040f0000000b080000290000000c0200002900000011070000290000000e0400002900000012060000290000001005000029000000060300002900001b5e0080009c000038ca0000a13d000000010040008c00003ba10000c13d00000000050700190000000001250019000000000071004b00003bae0000a13d000000000527004b000042630000413d0000000001070019000000000271019f00001b480020009c00003bb10000413d000000000007004b00003bb30000613d00000000030700190000000004010019000000000203001900000000302400d9000000000003004b000000000402001900003b9b0000c13d00003bb60000013d000000000047004b00003ba80000c13d00000000070400190000000001250019000000000071004b00003b910000213d00003bae0000013d00000000055700a900000000074700a900000000024200a90000000001250019000000000071004b00003b910000213d000000000271019f00001b480020009c00003b970000813d000000000407001900003bc30000013d000000000001004b000000000201001900003d310000613d0000000004050019000000000302001900000000203400d9000000000002004b000000000403001900003bb70000c13d00000000013100d900001b130010009c000042630000213d00000000043700d900001b130040009c000042630000213d00000000053500d9000000100110021000001b310110019700000006030000290000008802400210000000000121019f00000001011001bf000000000016041b00000000010004150000000d011000690000000001000002000003200040043f00001b1301500198000002c00010043f00003d2f0000613d0000000002030433000003600100043d000000000012004b0000424a0000a13d000000050110021000000005011000290000000f020000290000000000210435000002e00200043d000000000302043300000040013000390000000001010433000002a00010043f00000080033000390000000003030433000003000030043f000000040030008c000042ab0000213d000002600400043d000000000004004b00003be80000c13d000000020030008c00003bea0000413d0000000103000039000002600030043f00000019080000290000000003010433000000000003004b00003c8e0000613d0000000009000019000000050a9002100000000001a1001900000020011000390000000002010433000000000008004b00003c000000c13d0000000001020433000000050010008c000042ab0000213d000000000001004b000000000100001900003bff0000c13d000003000100043d000000040010008c0000000001000039000000010100c039000000010810018f0000008001200039000000000c010433000002c00300043d000003200400043d000000000043004b00003c090000c13d000000600b200039000000000d0b043300003c340000013d0000000006c300a900000000000c004b00003c0f0000613d0000000005c600d9000000000035004b000042630000c13d000000000004004b00003d340000613d00000000054600d900000000074500a9000000000046004b00003c180000413d00000000065700d9000000000046004b000042630000c13d000000000003004b00003d340000613d00000000063700d90000000000c6004b000042760000c13d000000600b20003900000000020b04330000000000c2004b000000000d020019000000000d05601900003c330000613d00000000063200a9000000000002004b00003c290000613d00000000072600d9000000000037004b000042630000c13d000000000d4600d900000000074d00a9000000000046004b00003c300000413d0000000006d700d9000000000046004b000042630000c13d00000000033700d9000000000023004b000042760000c13d000000000c0500190000000000db04350000000000c104350000000000cd004b00003c730000613d000002e00100043d0000000001010433000000c0021000390000000002020433000000a0011000390000000003010433000a00000002001d000000000132004b000042630000413d000b00000003001d000c00000001001d000d0000000d001d000e0000000c001d000f0000000b001d00100000000a001d001100000009001d001200000008001d00001b28010000410000000000100443000000000100041400001a980010009c00001a9801008041000000c00110021000001ac7011001c70000800b020000396a5a6a550000040f00000001002001900000428d0000613d000000000101043b0000000b07000029000000000271004b00000012080000290000001109000029000000100a0000290000000f0b0000290000000e050000290000000d040000290000000c06000029000042630000413d000000000326004b000042630000413d00000000014300a9000000000004004b00003c670000613d00000000044100d9000000000034004b000042630000c13d00000000035200a9000000000005004b00003c6d0000613d00000000045300d9000000000024004b000042630000c13d000000000031001a000042630000413d0000000a0070006b00003d340000613d0000000001310019000000000c6100d90000000000cb0435000003400100043d000000200110003900000000020104330000000001020433000000000091004b0000424a0000a13d0000002001a000390000000002210019000000000202043300000060022000390000000000c20435000003400200043d000000a00220003900000000020204330000000003020433000000000093004b0000424a0000a13d000000000121001900000000020b043300000000002104350000000109900039000002a00100043d0000000002010433000000000029004b00003bef0000413d000002e00200043d00000007010000290007000100100092001900000008001d000000000102043300000060011000390000000001010433000002400010043f0000000002010433000000000002004b0000372b0000613d000000000700001900000005087002100000000001810019000000200110003900000000040104330000008001400039000000000a010433000002c00100043d000003200200043d000000000021004b00003ca90000c13d0000006009400039000000000b0904330000000000b904350000000000ab004b00003cd70000c13d00003d140000013d0000000005a100a900000000000a004b00003caf0000613d0000000003a500d9000000000013004b000042630000c13d000000000002004b00003d340000613d00000000032500d900000000062300a9000000000025004b00003cb80000413d00000000053600d9000000000025004b000042630000c13d000000000001004b00003d340000613d00000000051600d90000000000a5004b000042760000c13d000000600940003900000000040904330000000000a4004b000000000b040019000000000b03601900003cd30000613d00000000051400a9000000000004004b00003cc90000613d00000000064500d9000000000016004b000042630000c13d000000000b2500d900000000062b00a9000000000025004b00003cd00000413d0000000005b600d9000000000025004b000042630000c13d00000000011600d9000000000041004b000042760000c13d000000000a0300190000000000b904350000000000ab004b00003d140000613d000002e00100043d0000000001010433000000c0021000390000000002020433000000a0011000390000000003010433000b00000002001d000000000132004b000042630000413d000c00000003001d000d00000001001d000e0000000b001d000f0000000a001d001000000009001d001100000008001d001200000007001d00001b28010000410000000000100443000000000100041400001a980010009c00001a9801008041000000c00110021000001ac7011001c70000800b020000396a5a6a550000040f00000001002001900000428d0000613d000000000101043b0000000c0a0000290000000001a1004b0000001207000029000000110800002900000010090000290000000f050000290000000e040000290000000d06000029000042630000413d000000000316004b000042630000413d0000000b00a0006b000042630000613d00000000024300a9000000000004004b00003d060000613d00000000044200d9000000000034004b000042630000c13d00000000035100a9000000000005004b00003d0c0000613d00000000045300d9000000000014004b000042630000c13d000000000032001a000042630000413d000000010160008a0000000002320019000000000021001a000042630000413d0000000001210019000000000a6100d90000000000a90435000003400100043d000000400110003900000000020104330000000001020433000000000071004b0000424a0000a13d00000020018000390000000002210019000000000202043300000060022000390000000000a20435000003400200043d000000c00220003900000000020204330000000003020433000000000073004b0000424a0000a13d0000000001210019000000000209043300000000002104350000000107700039000002400100043d0000000002010433000000000027004b00003c990000413d0000372b0000013d000002e00400043d000037260000013d000000000005004b000000000305001900003bbc0000c13d00001b0801000041000000000010043f0000001201000039000000040010043f00001b090100004100006a5c00010430000000190000002a0000000001000039000000010100c039000000010110017f00000001001001900000430d0000c13d00000003010000290000000021010434000e00000002001d000d00000001001d000000000001004b00003def0000613d000000000200001900003d4f0000013d0000000001010433000000000001004b00003dec0000c13d0000000f0200002900000001022000390000000d0020006c00003def0000813d00000003010000290000000001010433000000000021004b0000424a0000a13d000f00000002001d00000005012002100000000e011000290000000001010433000000002301043400000014040000290000000004040433000000000043004b000042a80000813d0000000503300210000000130330002900000000030304330000008004300039000000000404043300001b130040019800003d4b0000613d0000000004020433000000010040008c000042ab0000213d00000040021000390000000002020433000000000004004b00003d700000613d000000400330003900000000030304330000000004030433000000000042004b00003d750000413d000042d30000013d000000200330003900000000030304330000000004030433000000000042004b0000430a0000813d00000005022002100000000002320019000000200220003900000000020204330000000003020433000000050030008c000042ab0000213d00000040042000390000000005040433000000040030008c000000030300003900000002030060390000000000320435000000600210003900000000030204330000000000340435000042c00000413d00000080011000390000000001010433000000000005004b00003d480000613d001100000001001d000c00000005001d0000000003020433000000400100043d00000020020000390000000002210436000000000032043500001a9c0010009c000042500000213d0000004003100039000000400030043f00001a980020009c00001a98020080410000004002200210000000000101043300001a980010009c00001a98010080410000006001100210000000000121019f000000000200041400001a980020009c00001a9802008041000000c002200210000000000112019f00001ac1011001c700008010020000396a5a6a550000040f0000000100200190000042560000613d000000000101043b00000011020000290000000032020434001000000003001d000000000002004b00003dea0000613d0000000003000019001200000003001d00000005023002100000001005200029000000400200043d000000400420003900000020032000390000000005050433000000000051004b00003dc90000a13d000000000053043500000000001404350000004001000039000000000012043500001ac50020009c000042500000213d0000006001200039000000400010043f00001a980030009c00001a98030080410000004001300210000000000202043300001a980020009c00001a98020080410000006002200210000000000112019f000000000200041400003dda0000013d000000000013043500000000005404350000004001000039000000000012043500001ac50020009c000042500000213d0000006001200039000000400010043f00001a980030009c00001a98030080410000004001300210000000000202043300001a980020009c00001a98020080410000006002200210000000000112019f000000000200041400001a980020009c00001a9802008041000000c002200210000000000112019f00001ac1011001c700008010020000396a5a6a550000040f0000000100200190000042560000613d000000000101043b0000001203000029000000010330003900000011020000290000000002020433000000000023004b00003dae0000413d0000000c0010006c00003d4b0000613d000000400100043d00001b5702000041000042990000013d00000014010000290000000002010433000000000002004b00003e220000613d000000000100001900003df80000013d0000000101100039000000000021004b00003e220000813d0000000503100210000000130330002900000000030304330000008004300039000000000404043300001b130040019800003df50000613d000000200430003900000000040404330000000054040434000000000004004b00003e100000613d00000000060000190000000507600210000000000775001900000000070704330000000007070433000000050070008c000042ab0000213d000000030070008c0000427c0000213d0000000106600039000000000046004b00003e050000413d000000400330003900000000030304330000000043030434000000000003004b00003df50000613d00000000050000190000000506500210000000000664001900000000060604330000000006060433000000050060008c000042ab0000213d000000040060008c000042810000813d0000000105500039000000000035004b00003e160000413d00003df50000013d00000009010000290000000001010433000000000001004b00003ea70000613d000000020200002900111a9b0020019b000000000c00001900003e470000013d00120000000c001d00001a9b0530019700001a9b06200197000000000217004900001a980020009c00001a9802008041000000600220021000001a980010009c00001a98010080410000004001100210000000000112019f000000000200041400001a980020009c00001a9802008041000000c002200210000000000121019f00001ac1011001c70000800d02000039000000030300003900001b30040000416a5a6a500000040f0000000100200190000042560000613d00000009010000290000000001010433000000120c000029000000010cc0003900000000001c004b00003ea70000813d000000060200002900000000020204330000000000c2004b0000424a0000a13d0000000502c0021000000005032000290000000006030433000000000006004b00003e440000613d000000140100002900000000010104330000000000c1004b0000424a0000a13d000000130120002900000008022000290000000002020433000000000302043300000000010104330000004002100039000000000402043300000020023000390000000002020433000000000303043300000020011000390000000005010433000000400100043d0000004007100039000000800800003900000000008704350000002007100039000000110800002900000000008704350000000000610435000000000705043300000080061000390000000000760435000000a006100039000000000007004b00003e840000613d00000000080000190000002005500039000000000905043300000000ab0904340000000500b0008c000042ab0000213d000000000bb60436000000000a0a043300001a9b0aa001970000000000ab0435000000400a900039000000000a0a0433000000400b6000390000000000ab043500000060099000390000000009090433000000600a60003900000000009a043500000080066000390000000108800039000000000078004b00003e6f0000413d00000000051600490000006007100039000000000057043500000000050404330000000007560436000000000005004b00003e2a0000613d000000000600001900000020044000390000000008040433000000009a0804340000000500a0008c000042ab0000213d000000000aa70436000000000909043300001a9b0990019700000000009a043500000040098000390000000009090433000000400a70003900000000009a043500000060098000390000000009090433000000600a70003900000000009a04350000008008800039000000000808043300001a9b0880019700000080097000390000000000890435000000a0077000390000000106600039000000000056004b00003e8c0000413d00003e2a0000013d000000400100043d000000200200003900000000022104360000000605000029000000000305043300000000003204350000004002100039000000000003004b00003eb70000613d00000000040000190000002005500039000000000605043300000000026204360000000104400039000000000034004b00003eb10000413d000000000212004900001a980020009c00001a9802008041000000600220021000001a980010009c00001a98010080410000004001100210000000000112019f000000000200041400001a980020009c00001a9802008041000000c002200210000000000121019f00001ac1011001c70000800d02000039000000010300003900001b5f040000416a5a6a500000040f0000000100200190000042560000613d000000040100002900001ac20010009c000042500000213d000000040100002900000005011002100000003f0210003900001b0202200197000000400300043d0000000002230019000c00000003001d000000000032004b0000000003000039000000010300403900001ac20020009c000042500000213d0000000100300190000042500000c13d000000400020043f00000004020000290000000c030000290000000004230436000d00000004001d000000000002004b000042410000613d0000000002000019000000400300043d00001ac50030009c000042500000213d0000006004300039000000400040043f00001b070030009c000042500000213d0000010005300039000000400050043f00000000000404350000000004430436000000e0053000390000000000050435000000c0053000390000000000050435000000a0053000390000000000050435000000800530003900000000000504350000004005300039000000000005043500000000000404350000000d0420002900000000003404350000002002200039000000000012004b00003ee40000413d000000000c0000310000000205000367000800000000001d000000000200001900070000000c001d00003f0d0000013d0000000801000029000800010010003e000042630000613d0000000e020000290000000102200039000000040020006c000000070c000029000041f70000813d000e00000002001d0000000502200210000002800100043d0000000002210019000000000225034f000000000202043b00000000031c00490000003f0330008a00001b010430019700001b0106200197000000000746013f000000000046004b000000000400001900001b0104004041000000000032004b000000000300001900001b010300804100001b010070009c000000000403c019000000000004004b000042560000c13d0000000001120019000000000215034f000000000202043b00000000031c00490000001f0330008a00001b010630019700001b0104200197000000000764013f000000000064004b000000000400001900001b0104004041000000000032004b000000000800001900001b010800804100001b010070009c000000000408c019000000000004004b000042560000c13d0000000002120019000000000425034f000000000704043b00001ac20070009c000042560000213d000000060870021000000000048c0049000000200220003900001b010940019700001b010a200197000000000b9a013f00000000009a004b000000000900001900001b0109004041000000000042004b000000000400001900001b010400204100001b0100b0009c000000000904c019000000000009004b000042560000c13d0000002004100039000000000445034f000000000904043b00001b0104900197000000000a64013f000000000064004b000000000400001900001b0104004041000000000039004b000000000300001900001b010300804100001b0100a0009c000000000403c019000000000004004b000042560000c13d0000000001190019000000000315034f000000000303043b00001ac20030009c000042560000213d000000060630021000000000046c0049000000200110003900001b010940019700001b010a100197000000000b9a013f00000000009a004b000000000900001900001b0109004041000000000041004b000000000400001900001b010400204100001b0100b0009c000000000904c019000000000009004b000042560000c13d00000005047002100000003f0440003900001b0204400197000000400a00043d00000000094a001900100000000a001d0000000000a9004b0000000004000039000000010400403900001ac20090009c000042500000213d0000000100400190000042500000c13d000000400090043f00000010040000290000000004740436001100000004001d00000000072800190000000000c7004b000042560000213d000000000027004b00003f9a0000a13d000000100800002900000000042c004900001b030040009c000042560000213d000000400040008c000042560000413d000000400900043d00001a9c0090009c000042500000213d00000020088000390000004004900039000000400040043f000000000425034f000000000404043b0000000004490436000000200a200039000000000aa5034f000000000a0a043b0000000000a4043500000000009804350000004002200039000000000072004b00003f840000413d00000005023002100000003f0220003900001b0202200197000000400a00043d00000000022a00190000000000a2004b0000000004000039000000010400403900001ac20020009c000042500000213d0000000100400190000042500000c13d000000400020043f00000000023a0436001200000002001d00000000021600190000000000c2004b000042560000213d000000000012004b00003fc50000a13d00000000030a001900000000041c004900001b030040009c000042560000213d000000400040008c000042560000413d000000400600043d00001a9c0060009c000042500000213d00000020033000390000004004600039000000400040043f000000000415034f000000000404043b00000000044604360000002007100039000000000775034f000000000707043b000000000074043500000000006304350000004001100039000000000021004b00003faf0000413d000000400700043d00001ac50070009c000042500000213d0000006001700039000000400010043f00001b070070009c000042500000213d0000010002700039000000400020043f00000000000104350000000002170436000000e0017000390000000000010435000000c0017000390000000000010435000000a00170003900000000000104350000008001700039000000000001043500000040017000390000000000010435000b00000002001d000000000002043500000010010000290000000001010433000000000001004b0000429f0000613d00000000010a0433000000000001004b0000429f0000613d000000400c00043d00001aa800c0009c000042500000213d000000a001c00039000000400010043f0000008001c0003900000000000104350000004001c0003900000000000104350000002001c00039000000000001043500000000000c0435000000600dc0003900000000000d0435000000400100043d00001b2e0010009c000042500000213d0000008002100039000000400020043f0000006002100039000f00000002001d00000000000204350000004002100039000000000002043500000000060104360000000000060435000000400300043d00001aa80030009c000042500000213d000000a004300039000000400040043f000000800430003900000000000404350000006004300039000000000004043500000040043000390000000000040435000000200430003900000000000404350000000000030435000000400300043d00001b060030009c000042500000213d000a00000007001d000000e004300039000000400040043f000000c00430003900000060070000390000000000740435000000a004300039000000000074043500000040043000390000000000740435000000200430003900000000007404350000008004300039000000000004043500000060043000390000000000040435000000000003043500000000030a0433000000000003004b000040b30000613d0000000003000019000000000d000019000040390000013d0000000104f0018f000000000042043500000000040e0433000000000004004b000000000400003900000001040060390000000f0700002900000000004704350000000007020433000000000007004b000000010440c1bf000000000042043500000000000e04350000000004020433000000000004004b000042690000c13d000000010dd0003900000000040a043300000000004d004b000040b10000813d0000000504d0021000000012094000290000000004090433000000000e0404330000000000e1043500000000040a04330000000000d4004b0000424a0000a13d00000000040904330000002004400039000000000704043300000000007604350000001404000029000000000404043300000000004e004b000000000400003900000001040080390000000000420435000042690000813d000000140400002900000000040404330000000000e4004b0000424a0000a13d0000000504e0021000000013044000290000000004040433000000800b400039000000000b0b043300001b1300b00198000040350000613d00000040044000390000000004040433000000000b0404330000000000b7004b000040350000813d0000000507700210000000000447001900000020044000390000000007040433000000000003004b000040880000613d0000006004c000390000000009040433000000600e700039000000000b0e043300000000009b001a000042630000413d00000000099b001900000000009404350000008004c00039000000000404043300000080097000390000000009090433000000000449013f00001a9b00400198000000010f000039000040250000c13d000000009f0c04340000000500f0008c000042ab0000213d000000004b0704340000000500b0008c000042ab0000213d0000000000bf004b000000010f000039000040250000c13d00000000090904330000000004040433000000000494013f00001a9b00400198000040250000c13d000000400470003900000000040404330000004007c000390000000007070433000000000047004b000000000f000039000000010f00c039000040250000013d0000000043070434000000050030008c000042ab0000213d000000400c00043d00001aa800c0009c000042500000213d0000000004040433000000400b700039000000000b0b0433000000800e700039000000000f0e0433000000600e70003900000000070e0433000000a008c00039000000400080043f00001a9b08f00197000000800fc0003900000000008f04350000006008c0003900000000007804350000004007c000390000000000b7043500001a9b044001970000002007c00039000000000047043500000000003c043500000000000d004b000040af0000613d00000000030a04330000000000d3004b0000424a0000a13d0000001207000029000000000307043300000000040904330000000000470435000000000039043500000000030a04330000000000d3004b0000424a0000a13d0000000103000039000040270000013d000000600dc00039000040b60000013d0000000001020433000000000001004b000042690000c13d00000000010d0433000000000001004b000041740000613d000000400b00043d00001ac500b0009c000042500000213d0000006001b00039000000400010043f00001b0700b0009c000042500000213d0000010002b00039000000400020043f000000000001043500000000011b0436000000e002b000390000000000020435000000c002b000390000000000020435000000a002b0003900000000000204350000008002b0003900000000000204350000004002b0003900000000000204350000000000010435000000400100043d00001b060010009c000042500000213d000000e002100039000000400020043f000000c00210003900000060030000390000000000320435000000a002100039000000000032043500000040021000390000000000320435000000200210003900000000003204350000008002100039000000000002043500000060021000390000000000020435000000000001043500000010010000290000000003010433000000000003004b0000417d0000613d00000000010000190000000002000019000040f30000013d00000000030204330000000000020435000000000003004b0000000102000039000042920000613d000000100300002900000000030304330000000101100039000000000031004b0000417e0000813d000000050410021000000011064000290000000004060433000000007404043400000014080000290000000008080433000000000084004b000042970000813d0000000504400210000000130440002900000000090404330000008004900039000000000404043300001b1300400198000040f00000613d0000000004070433000000200790003900000000070704330000000008070433000000000084004b000040f00000813d0000000503400210000000000373001900000020033000390000000003030433000000000002004b0000413e0000613d00000060063000390000000004060433000000000f0b001900000000e70b04340000006007700039000000000b0704330000000000b4001a000042630000413d0000000004b40019000000000047043500000040043000390000000004040433000000000b0f001900000000070b043300000040087000390000000008080433000000000048004b0000428e0000c13d000000000409043300000000080e0433000000000484013f00001a9b004001980000428e0000c13d000000600490003900000000040404330000004008b000390000000008080433000000000048004b0000428e0000c13d0000000074070434000000050040008c000042ab0000213d0000000039030434000000050090008c000042ab0000213d000000000094004b000000000b0f00190000428e0000c13d0000000004030433000000000707043300000000030604330000000000060435000000000474013f00001a9b00400198000042950000c13d000000000003004b000040ee0000c13d000042920000013d0000000028030434000000050080008c000042ab0000213d000000400700043d00001aa80070009c000042500000213d00000000040204330000004002300039000000000b02043300000060023000390000000003020433000000a00e7000390000004000e0043f000000600e70003900000000003e043500000040037000390000000000b3043500001a9b0340019700000020047000390000000000340435000000000087043500000080037000390000000000030435000000400e00043d00001ac500e0009c000042500000213d0000000003090433000000600490003900000000040404330000006008e00039000000400080043f0000004008e00039000000000048043500001a9b033001970000002004e000390000000000340435000000000b0e001900000000007e0435000000000001004b000040e90000613d00000010030000290000000003030433000000000013004b0000424a0000a13d0000001107000029000000000307043300000000040604330000000000470435000000000036043500000010030000290000000003030433000000000013004b000040e90000213d0000424a0000013d0000000b0300002900000000000304350000000a0800002900000000010804330000008001100039000000000001043500000000010804330000000102000039000041d90000013d000000000300001900000000080b001900000000010b04330000000024010434000000050040008c000042ab0000213d00000000670c0434000000050070008c000042ab0000213d000000000074004b000042a20000c13d00000000020204330000000004060433000000000224013f00001a9b00200198000042a20000c13d0000004002c00039000000000202043300000040041000390000000004040433000000000024004b000042a20000c13d00000000020d043300000060011000390000000006010433000000000162004b000041b60000a13d00000000020a0433000000000002004b0000424a0000613d00000012020000290000000002020433000000002302043400000014040000290000000004040433000000000034004b0000424a0000a13d0000000503300210000000130330002900000000030304330000004003300039000000000303043300000000040304330000000002020433000000000024004b0000424a0000a13d00000005022002100000000002230019000000200220003900000000020204330000006002200039000000000012043500000000010804330000006001100039000000000101043300000000001d0435000041d00000013d000000000003004b0000424a0000613d00000011010000290000000001010433000000001301043400000014040000290000000004040433000000000034004b0000424a0000a13d0000000503300210000000130330002900000000030304330000002003300039000000000303043300000000040304330000000001010433000000000014004b0000424a0000a13d000000000226004900000005011002100000000001130019000000200110003900000000010104330000006001100039000000000021043500000000010d04330000000002080433000000600220003900000000001204350000002003800039000000000108043300000080011000390000008002c00039000000000202043300001a9b02200197000000000021043500000000020304330000000004080019000000000108043300000080031000390000000003030433000000000232013f00001a9b00200198000041f10000613d0000000e02000029000000080120006c000042630000413d0000000c020000290000000002020433000000000012004b0000424a0000a13d00000005021002100000000d0220002900000000004204350000000c020000290000000002020433000000000012004b00003f080000213d0000424a0000013d0000000001010433000000050010008c000042ab0000213d000000000001004b00003f050000c13d000041e20000013d0000000802000029000000000002004b000042400000613d000000040120006b000042630000413d00001ac20010009c000042500000213d00000005041002100000003f0240003900001b0203200197000000400200043d0000000003320019000000000023004b0000000005000039000000010500403900001ac20030009c000042500000213d0000000100500190000042500000c13d000000400030043f00000000031204360000000806000029000000040060006b0000423e0000613d0000000005000019000000400600043d00001ac50060009c000042500000213d0000006007600039000000400070043f00001b070060009c000042500000213d0000010008600039000000400080043f00000000000704350000000007760436000000e0086000390000000000080435000000c0086000390000000000080435000000a008600039000000000008043500000080086000390000000000080435000000400860003900000000000804350000000000070435000000000753001900000000006704350000002005500039000000000045004b000042100000413d00000000040000190000000c050000290000000005050433000000000045004b0000424a0000a13d0000000005020433000000000045004b0000424a0000a13d000000050540021000000000065300190000000d05500029000000000505043300000000005604350000000005020433000000000045004b0000424a0000a13d0000000104400039000000000014004b0000422c0000413d0000000003020019000042410000013d0000000c03000029000002600600043d00000009010000290000001402000029000c00000003001d000000060400002900000002050000296a5a5e820000040f0000000c01000029000000000001042d00001b0801000041000000000010043f0000003201000039000000040010043f00001b090100004100006a5c0001043000001b0801000041000000000010043f0000004101000039000000040010043f00001b090100004100006a5c00010430000000000100001900006a5c00010430000000400100043d00001b5102000041000000000021043500000004021000390000000f03000029000000000032043500001a980010009c00001a9801008041000000400110021000001b09011001c700006a5c0001043000001b0801000041000000000010043f0000001101000039000000040010043f00001b090100004100006a5c00010430000000400200043d00001a980020009c00001a98010000410000000001024019000000400110021000001aca011001c70000000f030000290000000003030433000000000003004b000042790000c13d00001b5b03000041000000000032043500006a5c00010430000000400100043d00001b5202000041000042990000013d00001b3f03000041000000000032043500006a5c00010430000000400200043d0000002403200039000000000063043500001b5903000041000042850000013d000000400200043d0000002403200039000000000053043500001b5a0300004100000000003204350000000403200039000000000013043500001a980020009c00001a9802008041000000400120021000001b2a011001c700006a5c00010430000000000001042f00000000010604330000000000060435000000000001004b000042970000c13d000000400100043d00001b3f02000041000042990000013d000000000003004b000042920000613d000000400100043d00001b5b02000041000000000021043500001a980010009c00001a9801008041000000400110021000001aca011001c700006a5c00010430000000400100043d00001b6102000041000042990000013d000000400100043d00001b6002000041000000000021043500000004021000390000000e030000290000425d0000013d0000000002020433000000010020008c000042c30000a13d00001b0801000041000000000010043f0000002101000039000000040010043f00001b090100004100006a5c00010430000000400100043d0000002402100039000000000042043500001b290200004100000000002104350000000402100039000000000032043500001a980010009c00001a9801008041000000400110021000001b2a011001c700006a5c00010430000000400100043d00001b4a02000041000042990000013d000000400100043d00001b5802000041000042990000013d000000400300043d001400000003001d00001b5401000041000000000013043500000004013000396a5a5b690000040f0000001402000029000000000121004900001a980010009c00001a9801008041000000600110021000001a980020009c00001a98020080410000004002200210000000000121019f00006a5c00010430000000400100043d00001b5502000041000042990000013d000000400100043d00001b1502000041000042990000013d000000400100043d00001b4902000041000042990000013d000000400100043d00001b12020000410000425a0000013d000000400100043d00001b14020000410000425a0000013d00030000000103550000000002010019000000600220027000011a980020019d00001a9802200197000042ea0000013d0000000301000367000000010200003100001b1f052001980000001f0620018f000000400300043d0000000004530019000042f50000613d000000000701034f0000000008030019000000007907043c0000000008980436000000000048004b000042f10000c13d000000000006004b000043020000613d000000000151034f0000000305600210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f000000000014043500001a980020009c00001a9802008041000000600120021000001a980030009c00001a98030080410000004002300210000000000112019f00006a5c00010430000000400100043d00001b5602000041000042990000013d000000400100043d00001b5302000041000042990000013d00010000000000020000000002010019000000400100043d00001b260010009c000044ab0000813d000000a003100039000000400030043f00001b270010009c000044ab0000213d0000020004100039000000400040043f0000000000030435000001000410003900000060050000390000000000540435000000e004100039000000000054043500000080041000390000000000540435000000600410003900000000005404350000000003310436000001e0041000390000000000040435000001c0041000390000000000040435000001a004100039000000000004043500000180041000390000000000040435000001600410003900000000000404350000014004100039000000000004043500000120041000390000000000040435000000c00410003900000000000404350000004001100039000000000001043500000000000304350000000203000367000000000123034f000000000701043b000000000500003100000000012500490000015f0410008a00001b010640019700001b0108700197000000000968013f000000000068004b000000000600001900001b0106002041000000000047004b000000000400001900001b010400404100001b010090009c000000000604c019000000000006004b000044a90000613d0000002004200039000000000443034f000000000404043b0000001f0110008a00001b010640019700001b0108100197000000000986013f000000000086004b000000000600001900001b0106004041000000000014004b000000000100001900001b010100804100001b010090009c000000000601c019000000000006004b000044a90000c13d0000000001240019000000000413034f000000000404043b00001ac20040009c000044a90000213d0000000008450049000000200610003900001b010180019700001b0109600197000000000a19013f000000000019004b000000000100001900001b0101004041000000000086004b000000000800001900001b010800204100001b0100a0009c000000000108c019000000000001004b000044a90000c13d000000400100043d00001aa80010009c000044ab0000213d00000000072700190000000008750049000000a002100039000100000002001d000000400020043f00001b030080009c000044a90000213d000001600080008c000044a90000413d00001b270010009c000044ab0000213d0000020002100039000000400020043f000000000273034f000000000202043b00001a9b0020009c000044a90000213d000000010800002900000000002804350000002008700039000000000283034f000000000902043b00001a9b0090009c000044a90000213d000000c00210003900000000009204350000002002800039000000000223034f000000000202043b00001ac20020009c000044a90000213d000000000a7200190000001f02a00039000000000052004b000000000900001900001b010900804100001b010220019700001b0108500197000000000b82013f000000000082004b000000000200001900001b010200404100001b0100b0009c000000000209c019000000000002004b000044a90000c13d0000000002a3034f000000000b02043b00001ac200b0009c000044ab0000213d0000000502b002100000003f0220003900001b0202200197000000400900043d000000000c29001900000000009c004b0000000002000039000000010200403900001ac200c0009c000044ab0000213d0000000100200190000044ab0000c13d000000200aa000390000004000c0043f0000000000b90435000000a002b000c9000000000ba2001900000000005b004b000044a90000213d0000000000ab004b000043e50000a13d000000000c0900190000000002a5004900001b030020009c000044a90000213d000000a00020008c000044a90000413d000000400d00043d00001aa800d0009c000044ab0000213d000000a002d00039000000400020043f0000000002a3034f000000000202043b000000050020008c000044a90000213d000000000f2d0436000000200ea000390000000002e3034f000000000202043b00001a9b0020009c000044a90000213d000000200cc0003900000000002f04350000002002e00039000000000223034f000000000202043b000000400fd0003900000000002f04350000004002e00039000000000223034f000000000202043b000000600fd0003900000000002f04350000006002e00039000000000223034f000000000202043b000000800ed0003900000000002e04350000000000dc0435000000a00aa000390000000000ba004b000043bc0000413d000000e00210003900000000009204350000006002700039000000000223034f000000000202043b00001ac20020009c000044a90000213d00000000097200190000001f02900039000000000052004b000000000a00001900001b010a00804100001b0102200197000000000b82013f000000000082004b000000000200001900001b010200404100001b0100b0009c00000000020ac019000000000002004b000044a90000c13d000000000293034f000000000a02043b00001ac200a0009c000044ab0000213d0000000502a002100000003f0220003900001b0202200197000000400800043d000000000b28001900000000008b004b0000000002000039000000010200403900001ac200b0009c000044ab0000213d0000000100200190000044ab0000c13d00000020099000390000004000b0043f0000000000a80435000000c002a000c9000000000a92001900000000005a004b000044a90000213d00000000009a004b000044440000a13d000000000b080019000000000295004900001b030020009c000044a90000213d000000c00020008c000044a90000413d000000400c00043d00001ac800c0009c000044ab0000213d000000c002c00039000000400020043f000000000293034f000000000202043b000000050020008c000044a90000213d000000000e2c0436000000200d9000390000000002d3034f000000000202043b00001a9b0020009c000044a90000213d00000000002e04350000002002d00039000000000223034f000000000202043b000000400ec0003900000000002e04350000004002d00039000000000223034f000000000202043b000000600ec0003900000000002e04350000006002d00039000000000223034f000000000202043b000000800ec0003900000000002e04350000008002d00039000000000223034f000000000d02043b00001a9b00d0009c000044a90000213d000000200bb00039000000a002c000390000000000d204350000000000cb0435000000c0099000390000000000a9004b000044140000413d000001000210003900000000008204350000008007700039000000000273034f000000000202043b000000040020008c000044a90000213d000001200810003900000000002804350000002002700039000000000223034f000000000202043b000001400810003900000000002804350000004002700039000000000223034f000000000202043b000001600810003900000000002804350000006002700039000000000223034f000000000202043b000001800810003900000000002804350000008002700039000000000223034f000000000202043b000001a0081000390000000000280435000000a002700039000000000223034f000000000202043b000001c0081000390000000000280435000000c002700039000000000223034f000000000202043b0000004007100039000000010800003900000000008704350000002007100039000000000087043500000001070000290000000000710435000001e00710003900000000002704350000001f0240003900001b1f022001970000003f0220003900001b1f07200197000000400200043d0000000007720019000000000027004b0000000009000039000000010900403900001ac20070009c000044ab0000213d0000000100900190000044ab0000c13d000000400070043f00000000074204360000000009640019000000000059004b000044a90000213d000000000563034f00001b1f064001980000001f0840018f00000000036700190000448f0000613d000000000905034f000000000a070019000000009b09043c000000000aba043600000000003a004b0000448b0000c13d000000000008004b0000449c0000613d000000000565034f0000000306800210000000000803043300000000086801cf000000000868022f000000000505043b0000010006600089000000000565022f00000000056501cf000000000585019f00000000005304350000000003470019000000000003043500000060031000390000000000230435000000400200043d00001b2f0020009c000044ab0000213d0000002003200039000000400030043f000000000002043500000080031000390000000000230435000000000001042d000000000100001900006a5c0001043000001b0801000041000000000010043f0000004101000039000000040010043f00001b090100004100006a5c000104300026000000000002000200000004001d001100000003001d001800000002001d0000000002000415001900000002001d000500000001001d0000000012010434001a00000001001d000000c0012000390000000001010433001d00000001001d001c00000002001d000000a0012000390000000001010433001b00000001001d00001b28010000410000000000100443000000000100041400001a980010009c00001a9801008041000000c00110021000001ac7011001c70000800b020000396a5a6a550000040f0000000100200190000051150000613d000000000101043b0000001b03000029000000000013004b0000001d04000029000051590000213d000000000014004b000051590000a13d0000001c0100002900000080011000390000000001010433000000050010008c000051290000813d00000005020000290000004002200039000000000202043300001b13032001970000001a02000029000000000202043300001b1304200197000000040010008c000046190000c13d000000010040008c000051600000c13d000000010030008c000051600000c13d0000001c03000029000001400130003900000000010104330000006002300039001a00000002001d00000000020204330000000002020433000000000012004b000051770000c13d000000050100002900000080011000390000000001010433001b00000001001d000000000103043300001a9b01100197000000000010043f0000000401000039000000200010043f000000000100041400001a980010009c00001a9801008041000000c00110021000001b0b011001c700008010020000396a5a6a550000040f0000000100200190000051040000613d000000000101043b000000000e01041a0000000102e0003a0000510c0000613d000000000021041b0000001c010000290000004001100039001d00000001001d0000000002010433000000004702043400001b250070009c000050fe0000813d00000005067002100000003f0160003900001b0203100197000000400100043d0000000005310019000000000015004b0000000003000039000000010300403900001ac20050009c000050fe0000213d0000000100300190000050fe0000c13d0000001c03000029000000000f0304330000001a030000290000000003030433000000400050043f0000000005710436000000000007004b000045320000613d0000000007000019000000400800043d00001b2e0080009c000050fe0000213d0000008009800039000000400090043f0000006009800039000000000009043500000040098000390000000000090435000000200980003900000000000904350000000000080435000000000975001900000000008904350000002007700039000000000067004b000045210000413d0000000006020433000000000006004b0000455a0000613d000000000600001900000005076002100000000008740019000000000a08043300000000b90a0434000000050090008c000051290000213d000000400800043d00001b2e0080009c000050fe0000213d000000000b0b0433000000400ca00039000000000c0c0433000000600aa00039000000000a0a0433000000800d8000390000004000d0043f000000600d8000390000000000ad0435000000400a8000390000000000ca043500001a9b0ab00197000000200b8000390000000000ab043500000000009804350000000009010433000000000069004b000051060000a13d000000000775001900000000008704350000000007010433000000000067004b000051060000a13d00000001066000390000000007020433000000000076004b000045360000413d000000004703043400001ac20070009c000050fe0000213d00000005067002100000003f0260003900001b0205200197000000400200043d0000000005520019000000000025004b0000000008000039000000010800403900001ac20050009c000050fe0000213d0000000100800190000050fe0000c13d000000400050043f0000000005720436000000000007004b0000457f0000613d0000000007000019000000400800043d00001b2e0080009c000050fe0000213d0000008009800039000000400090043f0000006009800039000000000009043500000040098000390000000000090435000000200980003900000000000904350000000000080435000000000975001900000000008904350000002007700039000000000067004b0000456e0000413d0000000006030433000000000006004b000045a70000613d000000000600001900000005076002100000000008740019000000000a08043300000000b90a0434000000050090008c000051290000213d000000400800043d00001b2e0080009c000050fe0000213d000000000b0b0433000000400ca00039000000000c0c0433000000600aa00039000000000a0a0433000000800d8000390000004000d0043f000000600d8000390000000000ad0435000000400a8000390000000000ca043500001a9b0ab00197000000200b8000390000000000ab043500000000009804350000000009020433000000000069004b000051060000a13d000000000775001900000000008704350000000007020433000000000067004b000051060000a13d00000001066000390000000007030433000000000076004b000045830000413d0000001c030000290000000005030433000000400400043d000000440340003900000080060000390000000000630435000000200340003900001b4b0600004100000000006304350000002406400039000000000700041100000000007604350000000007010433000000a4064000390000000000760435000000c406400039000000000007004b000045cf0000613d00000000080000190000002001100039000000000901043300000000ab0904340000000500b0008c000051290000213d000000000bb60436000000000a0a043300001a9b0aa001970000000000ab0435000000400a900039000000000a0a0433000000400b6000390000000000ab043500000060099000390000000009090433000000600a60003900000000009a043500000080066000390000000108800039000000000078004b000045ba0000413d0000000001460049000000240110008a0000006407400039000000000017043500000000070204330000000001760436000000000007004b000045ed0000613d000000000600001900000020022000390000000008020433000000009a0804340000000500a0008c000051290000213d000000000aa10436000000000909043300001a9b0990019700000000009a043500000040098000390000000009090433000000400a10003900000000009a0435000000600880003900000000080804330000006009100039000000000089043500000080011000390000000106600039000000000076004b000045d80000413d0000000002410049000000240220008a000000840640003900000000002604350000001b0200002900000000620204340000000001210436000000000002004b000045fe0000613d000000000700001900000000081700190000000009760019000000000909043300000000009804350000002007700039000000000027004b000045f70000413d000000000621001900000000000604350000001f0220003900001b1f0220019700000000024200490000000001210019000000200210008a00000000002404350000001f0110003900001b1f021001970000000001420019000000000021004b0000000002000039000000010200403900001ac20010009c000050fe0000213d0000000100200190000050fe0000c13d00001a9b02500197000000400010043f00000000040404330000000001000414000000040020008c000046430000c13d00000001020000390000000101000031000046580000013d000000010240008a000000000032004b000051600000813d001200000003001d001d00000004001d000000000034004b000046220000813d00000001001001900000517a0000613d0000001c010000296a5a563f0000040f000400000001001d000000000010043f0000000301000039000000200010043f000000000100041400001a980010009c00001a9801008041000000c00110021000001b0b011001c700008010020000396a5a6a550000040f0000000100200190000051040000613d000000000601043b000000000406041a0000ff00004001900000517d0000c13d0000008807400270000000100140027000001b130310019800000012020000290000001d050000290000463d0000613d000000000073004b000051800000813d000000ff00400190000048f40000613d00001b470040009c000049080000813d0000001001500210000049420000013d00001a980030009c00001a9803008041000000400330021000001a980040009c00001a98040080410000006004400210000000000334019f00001a980010009c00001a9801008041000000c001100210000000000113019f001c0000000e001d001b0000000f001d6a5a6a500000040f0000001b0f0000290000001c0e000029000000010220018f0003000000010355000000600110027000011a980010019d00001a9801100197000000000001004b0000008009000039000000600a000039000046850000613d00001ac20010009c000050fe0000213d0000001f0310003900001b1f033001970000003f0330003900001b1f03300197000000400a00043d00000000033a00190000000000a3004b0000000004000039000000010400403900001ac20030009c000050fe0000213d0000000100400190000050fe0000c13d000000400030043f00000000091a043600001b1f031001980000001f0410018f00000000013900190000000305000367000046780000613d000000000605034f0000000007090019000000006806043c0000000007870436000000000017004b000046740000c13d000000000004004b000046850000613d000000000335034f0000000304400210000000000501043300000000054501cf000000000545022f000000000303043b0000010004400089000000000343022f00000000034301cf000000000353019f0000000000310435001c00000009001d0000006001f002100004000000e10143000000000002004b000048aa0000613d000000400100043d00001b4c0010009c000050fe0000213d001b0000000a001d000000240210003900001b4d030000410000000000320435000000440210003900000000030004140000006004000039000000000042043500001b4e020000410000000000210435000000640210003900000000000204350000000402100039000000000002043500001a980010009c00001a9801008041000000400110021000001a980030009c00001a9803008041000000c002300210000000000121019f00001b4f011001c700008006020000396a5a6a500000040f0000000100200190000051830000613d000000000101043b000000000001004b0000001c07000029000051890000613d000000400d00043d00001b5002000041000000000e2d04360000000402d00039000000200300003900000000003204350000001b0200002900000000030204330000002402d0003900000000003204350000004404d00039000000000003004b000046c00000613d000000000200001900000000054200190000000006270019000000000606043300000000006504350000002002200039000000000032004b000046b90000413d00000000023400190000000000020435000000000500041400001a9b02100197000000040020008c000046d10000c13d0000000006000415000000260660008a00000005066002100000000005000415000000250550008a000000050550021000000003010003670000000102000031002500000000003d002600000000003d000046f50000013d001b0000000e001d0000001f0130003900001b1f011001970000000001d10049000000000141001900001a980010009c00001a9801008041000000600110021000001a9800d0009c001c0000000d001d00001a980300004100000000030d40190000004003300210000000000131019f00001a980050009c00001a9805008041000000c003500210000000000131019f6a5a6a550000040f0000000006000415000000240660008a00000005066002100000000005000415000000230550008a00000005055002100000000003010019000000600330027000011a980030019d0003000000010355002400000000003d002300000000003d0000000100200190000048aa0000613d00001a98023001970000001c0d0000290000001b0e00002900001b1f042001980000001f0720018f00000000034d0019000046ff0000613d000000000801034f00000000090d0019000000008a08043c0000000009a90436000000000039004b000046fb0000c13d000000000007004b0000470c0000613d000000000141034f0000000304700210000000000703043300000000074701cf000000000747022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000171019f00000000001304350000001f0120003900001b1f031001970000000001d30019000000000031004b0000000003000039000000010300403900001ac20010009c000050fe0000213d0000000100300190000050fe0000c13d000000400010043f00001b030020009c000051040000213d000000400020008c000051040000413d00000000030d043300001ac20030009c000051040000213d0000000003d300190000000007d2001900001b01027001970000001f0430003900001b0108400197000000000928013f000000000028004b000000000800001900001b0108004041000000000074004b000000000400001900001b010400804100001b010090009c000000000804c019000000000008004b000051040000c13d000000003803043400001ac20080009c000050fe0000213d00000005048002100000003f0440003900001b0204400197000000000414001900001ac20040009c000050fe0000213d000000400040043f000000000481043600000007088002100000000008380019000000000078004b000051040000213d000000000083004b0000475e0000813d0000000009040019000000000a37004900001b0300a0009c000051040000213d0000008000a0008c000051040000413d000000400a00043d00001b2e00a0009c000050fe0000213d000000800ba000390000004000b0043f00000000bc0304340000000500c0008c000051040000213d000000000cca0436000000000b0b043300001a9b00b0009c000051040000213d0000000000bc0435000000400b300039000000000b0b0433000000400ca000390000000000bc0435000000600b300039000000000b0b0433000000600ca000390000000000bc04350000000009a904360000008003300039000000000083004b000047400000413d00000000030e043300001ac20030009c000051040000213d0000000003d300190000001f08300039000000000078004b000000000900001900001b010900804100001b0108800197000000000a28013f000000000028004b000000000200001900001b010200404100001b0100a0009c000000000209c019000000000002004b000051040000c13d000000008303043400001ac20030009c000050fe0000213d00000005023002100000003f0220003900001b0202200197000000400a00043d00000000092a0019001c0000000a001d0000000000a9004b0000000002000039000000010200403900001ac20090009c000050fe0000213d0000000100200190000050fe0000c13d000000400090043f0000001c020000290000000002320436001b00000002001d000000a0023000c90000000009820019000000000079004b000051040000213d000000000098004b000047af0000813d0000001c0a000029000000000287004900001b030020009c000051040000213d000000a00020008c000051040000413d000000400300043d00001aa80030009c000050fe0000213d000000a002300039000000400020043f000000002b0804340000000500b0008c000051040000213d000000000bb30436000000000202043300001a9b0020009c000051040000213d00000000002b043500000040028000390000000002020433000000400b30003900000000002b04350000006002300039000000600b800039000000000b0b04330000000000b204350000008002800039000000000202043300001a9b0020009c000051040000213d000000200aa00039000000800b30003900000000002b043500000000003a0435000000a008800039000000000098004b0000478a0000413d0000000502600270000000000201001f00000005025002700000001c0200002f00000000050104330000001d0200002900000000020204330000000006020433000000000056004b000048aa0000213d000000000065004b000047f80000a13d00001ac20050009c000050fe0000213d00000005095002100000003f0290003900001b0202200197000000400700043d0000000003270019000000000073004b0000000002000039000000010200403900001ac20030009c000050fe0000213d0000000100200190000050fe0000c13d000000400030043f00000000085704360000000003000019000000400a00043d00001aa800a0009c000050fe0000213d000000a002a00039000000400020043f0000008002a0003900000000000204350000006002a0003900000000000204350000004002a0003900000000000204350000002002a00039000000000002043500000000000a043500000000028300190000000000a204350000002003300039000000000093004b000047cc0000413d000000000006004b000047f60000613d00000000030000190000001d0200002900000000090204330000000002090433000000000032004b000051060000a13d0000000002070433000000000032004b000051060000a13d0000000502300210000000000a82001900000000029200190000002002200039000000000202043300000000002a04350000000002070433000000000032004b000051060000a13d0000000103300039000000000063004b000047e20000413d0000001d020000290000000000720435000000000006004b000048350000613d00000000070000190000001d0200002900000000030204330000000002030433000000000072004b000051060000a13d0000000002010433000000000072004b000051060000a13d000000050270021000000000033200190000002003300039000000000d030433000000009b0d04340000000500b0008c000051290000213d000000000242001900000000030204330000000400b0008c0000004008d00039000000400a300039000048170000413d0000000002080433000000000002004b000048170000c13d000000020bb0008a0000000000bd043500000000020a04330000000000280435000000600cd0003900000000020c0433000000800dd00039000000000e0d04330000000000e2004b000048aa0000c13d000000600e300039000000000f0e04330000000000f2004b000048aa0000213d0000000032030434000000050020008c000051290000213d00000000002b004b000048aa0000c13d00000000020904330000000003030433000000000223013f00001a9b00200198000048aa0000c13d00000000020a04330000000003080433000000000023004b000048aa0000c13d0000000000fc043500000000020e043300000000002d04350000000107700039000000000067004b000047fb0000413d000000000065004b0000485a0000a13d0000001d0200002900000000030204330000000002030433000000000062004b000051060000a13d0000000002010433000000000062004b000051060000a13d0000000508600210000000000248001900000000070204330000000029070434000000050090008c000051290000213d0000000003380019000000200330003900000000030304330000000008930436000000000202043300001a9b022001970000000000280435000000400270003900000000020204330000004008300039000000000028043500000060027000390000006007300039000000000802043300000000008704350000008003300039000000000202043300000000002304350000000106600039000000000056004b000048370000413d0000001c0100002900000000010104330000001a0200002900000000040204330000000032040434001d00000003001d000000000021004b000048aa0000213d000000000001004b000048b70000613d00000000060000190000486f0000013d00000000003c043500000000020f043300000000002d0435000000000208043300001a9b0220019700000000002704350000000106600039000000000016004b000048b50000813d0000001c020000290000000002020433000000000062004b000051060000a13d0000000002040433000000000062004b000051060000a13d00000005026002100000001d03200029000000000703043300000000ae0704340000000500e0008c000051290000213d0000001b0220002900000000080204330000000300e0008c0000004009700039000000400b800039000048890000a13d0000000002090433000000000002004b000048890000c13d000000020ee0008a0000000000e7043500000000020b04330000000000290435000000600c70003900000000020c0433000000800d70003900000000030d0433000000000032004b000048aa0000c13d000000600f80003900000000030f0433000000000023004b000048aa0000213d0000000025080434000000050050008c000051290000213d00000000005e004b000048aa0000c13d00000000050a04330000000002020433000000000252013f00001a9b00200198000048aa0000c13d00000000020b04330000000005090433000000000025004b000048aa0000c13d0000008008800039000000a007700039000000000207043300001a9b02200198000048660000613d000000000508043300001a9b05500197000000000052004b000048660000613d000000400100043d00001b5102000041000000000021043500000004021000390000000403000029000000000032043500001a980010009c00001a9801008041000000400110021000001b09011001c700006a5c0001043000001ac20010009c000050fe0000213d00000005061002100000003f0260003900001b0203200197000000400200043d0000000003320019000000000023004b0000000005000039000000010500403900001ac20030009c000050fe0000213d0000000100500190000050fe0000c13d000000400030043f0000000003120436000000000001004b000048ef0000613d0000000007000019000000400800043d00001ac80080009c000050fe0000213d000000c005800039000000400050043f000000a0058000390000000000050435000000800580003900000000000504350000006005800039000000000005043500000040058000390000000000050435000000200580003900000000000504350000000000080435000000000537001900000000008504350000002007700039000000000067004b000048c80000413d00000000060000190000000005040433000000000065004b000051060000a13d0000000005020433000000000065004b000051060000a13d000000050560021000000000073500190000001d05500029000000000505043300000000005704350000000005020433000000000065004b000051060000a13d0000000106600039000000000016004b000048de0000413d0000001a010000290000000000210435001000010000003d001200100000002d000049480000013d00000005010000290000006001100039001a00000003001d00000000030104330000001c01000029000000000101043300001a9b011001970000000402000029001c00000006001d001b00000007001d001700000004001d6a5a584c0000040f00000017040000290000001a030000290000001b070000290000001c060000290000001d05000029000000120200002900001b470040009c000046410000413d000000010020008c0000490f0000c13d00000000050700190000000001350019000000000071004b000049150000a13d000049200000013d000000000027004b0000491a0000c13d00000000070200190000000001350019000000000071004b000049200000213d000000000271019f00001b480020009c000049260000813d0000000002070019000049400000013d00000000055700a900000000072700a900000000032300a90000000001350019000000000071004b000049150000a13d000000000537004b0000510c0000413d0000000001070019000000000271019f00001b480020009c000049180000413d000000000007004b000049300000613d00000000030700190000000004010019000000000203001900000000302400d9000000000003004b00000000040200190000492a0000c13d000049330000013d000000000001004b0000000002010019000050f50000613d0000000004050019000000000302001900000000203400d9000000000002004b0000000004030019000049340000c13d00000000013100d900001b130010009c0000510c0000213d00000000023700d900001b130020009c0000510c0000213d00000000053500d9000000100110021000001b3101100197001200000002001d0000008802200210000000000121019f00000001011001bf000000000016041b00101b130050019b00000000010004150000001901100069000000000100000200000018010000290000000021010434001700000002001d001600000001001d000000000001004b000049f60000613d00000005010000290000000001010433001400400010003d001500600010003d00000000020000190000495e0000013d0000000001010433000000000001004b000049f30000c13d0000001a020000290000000102200039000000160020006c000049f60000813d00000018010000290000000001010433000000000021004b000051060000a13d001a00000002001d000000050120021000000017011000290000000001010433000000200210003900000000020204330000000003010433000000000003004b000051270000c13d000000010020008c000051290000213d00000040031000390000000003030433000000000002004b000049770000613d000000150200002900000000020204330000000004020433000000000043004b0000497c0000413d000051350000013d000000140200002900000000020204330000000004020433000000000043004b0000514b0000813d00000005033002100000000002230019000000200220003900000000020204330000000003020433000000050030008c000051290000213d00000040042000390000000005040433000000040030008c0000000303000039000000020300603900000000003204350000006002100039000000000302043300000000003404350000512f0000413d00000080011000390000000001010433000000000005004b000049570000613d001c00000001001d001900000005001d0000000003020433000000400100043d00000020020000390000000002210436000000000032043500001a9c0010009c000050fe0000213d0000004003100039000000400030043f00001a980020009c00001a98020080410000004002200210000000000101043300001a980010009c00001a98010080410000006001100210000000000121019f000000000200041400001a980020009c00001a9802008041000000c002200210000000000112019f00001ac1011001c700008010020000396a5a6a550000040f0000000100200190000051040000613d000000000101043b0000001c020000290000000032020434001b00000003001d000000000002004b000049f10000613d0000000003000019001d00000003001d00000005023002100000001b05200029000000400200043d000000400420003900000020032000390000000005050433000000000051004b000049d00000a13d000000000053043500000000001404350000004001000039000000000012043500001ac50020009c000050fe0000213d0000006001200039000000400010043f00001a980030009c00001a98030080410000004001300210000000000202043300001a980020009c00001a98020080410000006002200210000000000112019f0000000002000414000049e10000013d000000000013043500000000005404350000004001000039000000000012043500001ac50020009c000050fe0000213d0000006001200039000000400010043f00001a980030009c00001a98030080410000004001300210000000000202043300001a980020009c00001a98020080410000006002200210000000000112019f000000000200041400001a980020009c00001a9802008041000000c002200210000000000112019f00001ac1011001c700008010020000396a5a6a550000040f0000000100200190000051040000613d000000000101043b0000001d0300002900000001033000390000001c020000290000000002020433000000000023004b000049b50000413d000000190010006c0000495a0000613d000000400100043d00001b5702000041000051530000013d00000005010000290000000001010433000600000001001d0000006001100039001600000001001d00000000010104330000000021010434000000000001004b00004a0b0000613d00000000030000190000000504300210000000000442001900000000040404330000000004040433000000050040008c000051290000213d000000030040008c000051160000213d0000000103300039000000000013004b00004a000000413d00000006010000290000004001100039001900000001001d00000000010104330000000021010434000000000001004b00004a1e0000613d00000000030000190000000504300210000000000442001900000000040404330000000004040433000000050040008c000051290000213d000000030040008c0000511b0000213d0000000103300039000000000013004b00004a130000413d002200060000002d000000400100043d00001b060010009c000050fe0000213d000000e002100039000000400020043f000000c00210003900000060030000390000000000320435000000a00210003900000000003204350000004002100039001700000002001d00000000003204350000002002100039001800000002001d000000000032043500000080021000390000000000020435000000600210003900000000000204350000000000010435000000400100043d001c00000001001d00001aa80010009c000050fe0000213d0000000602000029000000a0012000390000000001010433000000c00220003900000000020204330000001c04000029000000a003400039000000400030043f0000008003400039000e00000003001d00000000002304350000006002400039000d00000002001d000000000012043500000040024000390000001101000029001300000002001d000000000012043500000010010000290000000001140436001b00000001001d00000012020000290000000000210435000000400100043d001a00000001001d00001a9c0010009c000050fe0000213d0000001a030000290000004001300039000000400010043f00000020023000390000006001000039000300000002001d0000000000120435000000000003043500000019010000290000000001010433000000000501043300001ac20050009c000050fe0000213d00000005015002100000003f0210003900001b0203200197000000400200043d0000000004320019000000000024004b0000000003000039000000010300403900001ac20040009c000050fe0000213d0000000100300190000050fe0000c13d000000060600002900000120036000390000000003030433001400000003001d0000000063060434000100000006001d000000400040043f0000000004520436000000000005004b00004a880000613d0000000005000019000000400600043d00001b2e0060009c000050fe0000213d0000008007600039000000400070043f0000006007600039000000000007043500000040076000390000000000070435000000200760003900000000000704350000000000060435000000000754001900000000006704350000002005500039000000000015004b00004a770000413d00000018010000290000000000210435000000190100002900000000010104330000000002010433000000000002004b0000000602000029000700800020003d00004be20000613d00121a9b0030019b000000020200002900151a9b0020019b000000000b00001900004aa60000013d00000000050304330000000002020433000000000106043300001a9b0110019700001a9b03200197000000120200002900000014060000290000001a070000296a5a541c0000040f0000001d0b000029000000010bb0003900000019010000290000000001010433000000000201043300000000002b004b00004be20000813d0000000502b00210000000200c20003900000000011c001900000000080104330000000091080434000000050010008c000051290000213d000000000001004b00004ab40000c13d00000007020000290000000002020433000000040020008c000051290000213d0000514e0000c13d0000001b0200002900000000030204330000001c0200002900000000020204330000008004800039000000000504043300000060048000390000000004040433000000000054004b001d0000000b001d00004ac30000c13d000000000032004b00004acb0000c13d000000000d04001900004b460000013d0000000006000415000000210660008a0000000506600210000000000032004b00004ae00000c13d000000000d040019000000000705001900004b070000013d00000000054200a9000000000004004b00004ad10000613d00000000064500d9000000000026004b0000510c0000c13d000000000003004b000050f80000613d000000000d3500d900000000063d00a9000000000035004b00004ada0000413d0000000005d600d9000000000035004b0000510c0000c13d000000000002004b000050f80000613d00000000022600d9000000000042004b00004b460000613d000051120000013d00000000064200a9000000000004004b00004ae60000613d00000000074600d9000000000027004b0000510c0000c13d000000000003004b000050f80000613d000000000d3600d900000000073d00a9000000000036004b00004aef0000413d0000000006d700d9000000000036004b0000510c0000c13d000000000002004b000050f80000613d00000000062700d9000000000046004b000051120000c13d00000000045200a9000000000005004b00004afa0000613d00000000065400d9000000000026004b0000510c0000c13d00000000073400d900000000063700a9000000000034004b00004b010000413d00000000047600d9000000000034004b0000510c0000c13d00000000022600d90000000006000415000000200660008a0000000506600210000000000052004b000051120000c13d0000000502600270000000000207001f00000000007d004b00004b460000613d0000000e0100002900000000020104330000000d010000290000000003010433000800000002001d000000000132004b0000510c0000413d000900000003001d000a00000001001d000b00000007001d000c0000000d001d000f00000008001d001000000009001d00110000000c001d00001b28010000410000000000100443000000000100041400001a980010009c00001a9801008041000000c00110021000001ac7011001c70000800b020000396a5a6a550000040f0000000100200190000051150000613d000000000101043b0000000907000029000000000171004b0000001d0b000029000000110c00002900000010090000290000000f080000290000000c040000290000000b050000290000000a060000290000510c0000413d000000000316004b0000510c0000413d00000000024300a9000000000004004b00004b370000613d00000000044200d9000000000034004b0000510c0000c13d00000000035100a9000000000005004b00004b3d0000613d00000000045300d9000000000014004b0000510c0000c13d000000000032001a0000510c0000413d000000080070006b000050f80000613d0000000001080433000000050010008c000051290000213d0000000002320019000000000d6200d9000000400400043d00001aa80040009c000050fe0000213d00000040028000390000000008020433000000000209043300001a9b07200197000000a002400039000000400020043f00000080024000390000001503000029000000000032043500000060034000390000000000d304350000004005400039000000000085043500000000061404360000000000760435000000400900043d00001b2e0090009c000050fe0000213d000000800a9000390000004000a0043f000000600a9000390000000000da0435000000400a90003900000000008a04350000002008900039000000000078043500000000001904350000001801000029000000000101043300000000070104330000000000b7004b000051060000a13d00000000071c0019000000000097043500000000010104330000000000b1004b000051060000a13d0000000001040433000000050010008c000051290000213d0000000004050433000000000001004b00004b8e0000613d000000010010008c00004b820000613d000000020010008c00004a960000613d00000000050304330000000002020433000000000106043300001a9b0110019700001a9b03200197000000120200002900000014060000290000001a070000296a5a51eb0000040f00004a9f0000013d000000000004004b000051320000c13d00000000040304330000000002020433000000000106043300001a9b0110019700001a9b03200197000000120200002900000014050000290000001a060000296a5a5c060000040f00004a9f0000013d000000000106043300001a9b0110019700000000004101a0000051320000c13d0000000003030433000000000003004b000051380000613d000000000102043300001a9b041001970000000001000414000000040040008c001100000003001d001000000004001d00004ba10000c13d00000001010000310000000102000039000000000001004b00004bb00000c13d00004bd70000013d00001a980010009c00001a9801008041000000c00110021000001ac1011001c7000080090200003900000000050000196a5a6a500000040f0000001d0b000029000000010220018f0003000000010355000000600110027000011a980010019d00001a9801100197000000000001004b00004bd70000613d00001ac20010009c000050fe0000213d0000001f0310003900001b1f033001970000003f0330003900001b1f04300197000000400300043d0000000004430019000000000034004b0000000005000039000000010500403900001ac20040009c000050fe0000213d0000000100500190000050fe0000c13d000000400040043f000000000613043600001b1f041001980000000003460019000000030500036700004bca0000613d000000000705034f000000007807043c0000000006860436000000000036004b00004bc60000c13d0000001f0110019000004bd70000613d000000000445034f0000000301100210000000000503043300000000051501cf000000000515022f000000000404043b0000010001100089000000000414022f00000000011401cf000000000151019f0000000000130435000000000002004b00004aa00000c13d000000400100043d00000024021000390000001103000029000000000032043500001b340200004100000000002104350000000402100039000000100300002900004d710000013d00000016010000290000000001010433000000000401043300001ac20040009c000050fe0000213d00000005014002100000003f0210003900001b0203200197000000400200043d0000000003320019000000000023004b0000000005000039000000010500403900001ac20030009c000050fe0000213d0000000100500190000050fe0000c13d000000400030043f0000000003420436000000000004004b00004c0b0000613d0000000004000019000000400500043d00001aa80050009c000050fe0000213d000000a006500039000000400060043f000000800650003900000000000604350000006006500039000000000006043500000040065000390000000000060435000000200650003900000000000604350000000000050435000000000643001900000000005604350000002004400039000000000014004b00004bf80000413d00000017010000290000000000210435000000160100002900000000030104330000000001030433000000000001004b00004d730000613d0000000001000411001500000001001d000000000900001900004c250000013d00000000050504330000000002080433000000000103043300001a9b0110019700001a9b0320019700000015020000290000001a070000296a5a541c0000040f0000001d090000290000000109900039000000160100002900000000030104330000000001030433000000000019004b00004d730000813d0000001b0100002900000000020104330000001c01000029000000000101043300000005079002100000000003730019000000200330003900000000080304330000008003800039000000000403043300000060038000390000000003030433000000000043004b001d00000009001d00004c380000c13d000000000021004b00004c400000c13d000000000a03001900004cba0000013d00000000050004150000001f0550008a0000000505500210000000000021004b00004c550000c13d000000000a030019000000000604001900004c7c0000013d00000000043100a9000000000003004b00004c460000613d00000000053400d9000000000015004b0000510c0000c13d000000000002004b000050f80000613d000000000a2400d900000000052a00a9000000000024004b00004c4f0000413d0000000004a500d9000000000024004b0000510c0000c13d000000000001004b000050f80000613d00000000011500d9000000000031004b00004cba0000613d000051120000013d00000000053100a9000000000003004b00004c5b0000613d00000000063500d9000000000016004b0000510c0000c13d000000000002004b000050f80000613d000000000a2500d900000000062a00a9000000000025004b00004c640000413d0000000005a600d9000000000025004b0000510c0000c13d000000000001004b000050f80000613d00000000051600d9000000000035004b000051120000c13d00000000034100a9000000000004004b00004c6f0000613d00000000054300d9000000000015004b0000510c0000c13d00000000062300d900000000052600a9000000000023004b00004c760000413d00000000036500d9000000000023004b0000510c0000c13d00000000011500d900000000050004150000001e0550008a0000000505500210000000000041004b000051120000c13d0000000501500270000000000106001f00000000006a004b00004cba0000613d0000000e0100002900000000020104330000000d010000290000000003010433000c00000002001d000000000132004b0000510c0000413d000f00000003001d001000000001001d001100000006001d00190000000a001d001200000008001d001400000007001d00001b28010000410000000000100443000000000100041400001a980010009c00001a9801008041000000c00110021000001ac7011001c70000800b020000396a5a6a550000040f0000000100200190000051150000613d000000000101043b0000000f0a0000290000000001a1004b0000001d09000029000000140700002900000012080000290000001904000029000000110500002900000010060000290000510c0000413d000000000316004b0000510c0000413d0000000c00a0006b0000510c0000613d00000000024300a9000000000004004b00004cac0000613d00000000044200d9000000000034004b0000510c0000c13d00000000035100a9000000000005004b00004cb20000613d00000000045300d9000000000014004b0000510c0000c13d000000000032001a0000510c0000413d000000010160008a0000000002320019000000000021001a0000510c0000413d0000000001210019000000000a6100d90000000021080434000000050010008c000051290000213d000000400600043d00001aa80060009c000050fe0000213d000000000202043300000040038000390000000003030433000000a0048000390000000004040433000000a005600039000000400050043f00001a9b044001970000008008600039000000000048043500000060056000390000000000a5043500000040046000390000000000340435000000000316043600001a9b012001970000000000130435000000170100002900000000010104330000000002010433000000000092004b000051060000a13d0000000002170019000000200220003900000000006204350000000001010433000000000091004b000051060000a13d0000000001060433000000050010008c000051290000213d000000000001004b00004d000000c13d000f00000004001d001000000006001d001100000003001d001200000005001d001400000008001d00190000000a001d00001b6201000041000000000010044300000000010004100000000400100443000000000100041400001a980010009c00001a9801008041000000c00110021000001b1b011001c70000800a020000396a5a6a550000040f0000000100200190000051150000613d000000000101043b000000190010006b0000001d0900002900000014080000290000001205000029000000110300002900000010010000290000000f04000029000051510000213d0000000001010433000000050010008c000051290000213d0000000004040433000000000001004b00004d120000613d00000013020000290000000006020433000000010010008c00004d250000613d000000020010008c00004c160000613d00000000050504330000000002080433000000000103043300001a9b0110019700001a9b0320019700000015020000290000001a070000296a5a51eb0000040f00004c1e0000013d000000000103043300001a9b0110019700000000004101a0000051320000c13d0000000003050433000000000003004b000051380000613d000000000108043300001a9b041001970000000001000414000000040040008c001900000003001d001400000004001d00004d310000c13d00000001010000310000000102000039000000000001004b00004d400000c13d00004d670000013d000000000004004b000051320000c13d00000000040504330000000002080433000000000103043300001a9b0110019700001a9b03200197000000150200002900000000050600190000001a060000296a5a5c060000040f00004c1e0000013d00001a980010009c00001a9801008041000000c00110021000001ac1011001c7000080090200003900000000050000196a5a6a500000040f0000001d09000029000000010220018f0003000000010355000000600110027000011a980010019d00001a9801100197000000000001004b00004d670000613d00001ac20010009c000050fe0000213d0000001f0310003900001b1f033001970000003f0330003900001b1f04300197000000400300043d0000000004430019000000000034004b0000000005000039000000010500403900001ac20040009c000050fe0000213d0000000100500190000050fe0000c13d000000400040043f000000000613043600001b1f041001980000000003460019000000030500036700004d5a0000613d000000000705034f000000007807043c0000000006860436000000000036004b00004d560000c13d0000001f0110019000004d670000613d000000000445034f0000000301100210000000000503043300000000051501cf000000000515022f000000000404043b0000010001100089000000000414022f00000000011401cf000000000151019f0000000000130435000000000002004b00004c1f0000c13d000000400100043d00000024021000390000001903000029000000000032043500001b34020000410000000000210435000000040210003900000014030000290000000000320435000051220000013d000000030100002900000000010104330000000001010433000000000001004b00004e550000613d0000001a010000290000000001010433001c00000001001d000000400100043d001d00000001001d000000200210003900001b3501000041001b00000002001d000000000012043500001b040100004100000000001004430000000001000412000000040010044300000120010000390000002400100443000000000100041400001a980010009c00001a9801008041000000c00110021000001b05011001c700008005020000396a5a6a550000040f0000000100200190000051150000613d000000000101043b0000001d0400002900000060024000390000001c030000290000000000320435000000400240003900001a9b01100197000000000012043500001b040100004100000000001004430000000001000412000000040010044300000160010000390000002400100443000000000100041400001a980010009c00001a9801008041000000c00110021000001b05011001c700008005020000396a5a6a550000040f0000000100200190000051150000613d000000000101043b0000001d04000029000000a00240003900001b3603000041000000000032043500000080024000390000000000120435000000a001000039000000000014043500001ac80040009c000050fe0000213d0000001d02000029000000c001200039000000400010043f0000001b0100002900001a980010009c00001a98010080410000004001100210000000000202043300001a980020009c00001a98020080410000006002200210000000000112019f000000000200041400001a980020009c00001a9802008041000000c002200210000000000112019f00001ac1011001c700008010020000396a5a6a550000040f0000000100200190000051040000613d000000000101043b00001b3702000041000000000020044300001a9b01100197001d00000001001d0000000400100443000000000100041400001a980010009c00001a9801008041000000c00110021000001b1b011001c700008002020000396a5a6a550000040f0000000100200190000051150000613d000000400b00043d0000002404b000390000000403b00039000000000101043b000000000001004b000051630000613d0000000301000029000000000201043300001b380100004100000000001b043500000020010000390000000000130435000000000302043300000000003404350000004401b00039000000000003004b00004e080000613d0000000004000019000000200220003900000000050204330000000067050434000000040070008c000051290000813d0000000007710436000000000606043300001a9b0660019700000000006704350000004006500039000000000606043300001a9b06600197000000400710003900000000006704350000006006500039000000000606043300001a9b06600197000000600710003900000000006704350000008006500039000000000606043300000080071000390000000000670435000000a0055000390000000005050433000000a0061000390000000000560435000000c0011000390000000104400039000000000034004b00004de90000413d00000000040004140000001d02000029000000040020008c00004e110000c13d0000000103000031000000200030008c0000002004000039000000000403401900004e420000013d0000000001b1004900001a980010009c00001a9801008041000000600110021000001a9800b0009c00001a980300004100000000030b40190000004003300210000000000131019f00001a980040009c00001a9804008041000000c003400210000000000131019f001d0000000b001d6a5a6a500000040f0000001d0b0000290000000003010019000000600330027000001a9803300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b001900004e310000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b00004e2d0000c13d000000000006004b00004e3e0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000100000003001f00030000000103550000000100200190000051ab0000613d0000001f01400039000000600210018f0000000001b20019000000000021004b0000000002000039000000010200403900001ac20010009c000050fe0000213d0000000100200190000050fe0000c13d000000400010043f000000200030008c000051040000413d00000000010b043300001b3900100198000051040000c13d00000060010000390000000302000029000000000012043500001b6201000041000000000010044300000000010004100000000400100443000000000100041400001a980010009c00001a9801008041000000c00110021000001b1b011001c70000800a020000396a5a6a550000040f0000000100200190000051150000613d000000000101043b000000000001004b00004eb90000613d00001b6201000041000000000010044300000000010004100000000400100443000000000100041400001a980010009c00001a9801008041000000c00110021000001b1b011001c70000800a020000396a5a6a550000040f0000000100200190000051150000613d000000000301043b000000000003004b000051380000613d0000000001000414000000000200041100001a9b04200197000000040040008c001d00000003001d001c00000004001d00004e810000c13d00000001020000390000000101000031000000000001004b00004e8f0000c13d00004eb70000013d00001a980010009c00001a9801008041000000c00110021000001ac1011001c7000080090200003900000000050000196a5a6a500000040f000000010220018f0003000000010355000000600110027000011a980010019d00001a9801100197000000000001004b00004eb70000613d00001ac20010009c000050fe0000213d0000001f0310003900001b1f033001970000003f0330003900001b1f04300197000000400300043d0000000004430019000000000034004b0000000005000039000000010500403900001ac20040009c000050fe0000213d0000000100500190000050fe0000c13d000000400040043f000000000613043600001b1f031001980000001f0410018f0000000001360019000000030500036700004eaa0000613d000000000705034f000000007807043c0000000006860436000000000016004b00004ea60000c13d000000000004004b00004eb70000613d000000000335034f0000000304400210000000000501043300000000054501cf000000000545022f000000000303043b0000010004400089000000000343022f00000000034301cf000000000353019f0000000000310435000000000002004b0000516e0000613d000000400100043d00001a9c0010009c000050fe0000213d0000004002100039000000400020043f0000002002100039000000040300002900000000003204350000000102000039000000000021043500000007020000290000000002020433000000040020008c000051290000213d00001b6504200197000000400d00043d0000000603000029000000000303043300001a9b03300197000000020040008c00004f870000c13d0000000104000029000000000204043300001a9b022001970000000009000411000000000029004b000050900000613d00001b3b00d0009c000050fe0000213d0000000604000029000000e00440003900000000050404330000001804000029000000000a0404330000001704000029000000000b0404330000000506000029000000800460003900000000080404330000000004060433000000a0064000390000000007060433000000c00440003900000000060404330000014004d00039000000400040043f0000012004d0003900000000005404350000010005d000390000000000650435000000e006d000390000000000760435000000c007d000390000000000170435000000a001d0003900000000008104350000008008d000390000000000b80435000000600bd000390000000000ab0435000000400ad0003900000000003a04350000002003d000390000000000930435000000040900002900000000009d043500001b3c09000041000000400f00043d00000000009f04350000000409f00039000000200c0000390000000000c9043500000000090d0433000000240cf0003900000000009c0435000000000303043300001a9b033001970000004409f00039000000000039043500000000030a043300001a9b033001970000006409f00039000000000039043500000000090b04330000014003000039000000840af0003900000000003a04350000016403f00039000000000a0904330000000000a304350000018403f0003900000000000a004b00004f2c0000613d000000000b0000190000002009900039000000000c09043300000000de0c04340000000500e0008c000051290000213d000000000ee30436000000000d0d043300001a9b0dd001970000000000de0435000000400dc00039000000000d0d0433000000400e3000390000000000de0435000000600cc00039000000000c0c0433000000600d3000390000000000cd04350000008003300039000000010bb000390000000000ab004b00004f170000413d0000000009f30049000000240990008a0000000008080433000000a40af0003900000000009a043500000000090804330000000003930436000000000009004b00004f500000613d000000000a0000190000002008800039000000000b08043300000000cd0b04340000000500d0008c000051290000213d000000000dd30436000000000c0c043300001a9b0cc001970000000000cd0435000000400cb00039000000000c0c0433000000400d3000390000000000cd0435000000600cb00039000000000c0c0433000000600d3000390000000000cd0435000000800bb00039000000000b0b043300001a9b0bb00197000000800c3000390000000000bc0435000000a003300039000000010aa0003900000000009a004b00004f360000413d0000000008f30049000000240880008a0000000001010433000000c409f00039000000000089043500000000980104340000000001830436000000000008004b00004f610000613d0000000003000019000000000a130019000000000b390019000000000b0b04330000000000ba04350000002003300039000000000083004b00004f5a0000413d000000000381001900000000000304350000001f0380003900001b1f0330019700000000013100190000000003f10049000000240830008a0000000003070433000000e407f00039000000000087043500000000070304330000000001710436000000000007004b00004f760000613d00000000080000190000002003300039000000000903043300000000019104360000000108800039000000000078004b00004f700000413d00000000030604330000010406f00039000000000036043500000000030504330000012405f0003900000000003504350000014403f00039000000000404043300000000004304350000000003000414000000040020008c0000504b0000c13d0000000103000031000000200030008c000000200400003900000000040340190000507c0000013d000000040020008c0000508f0000c13d000000170200002900000000040204330000000502000029000000800220003900000000020204330000001805000029000000000605043300001b630500004100000000005d04350000000405d00039000000a0070000390000000000750435000000a405d0003900000000070604330000000000750435000000c405d00039000000000007004b00004fb10000613d00000000080000190000002006600039000000000906043300000000ab0904340000000500b0008c000051290000213d000000000bb50436000000000a0a043300001a9b0aa001970000000000ab0435000000400a900039000000000a0a0433000000400b5000390000000000ab043500000060099000390000000009090433000000600a50003900000000009a043500000080055000390000000108800039000000000078004b00004f9c0000413d0000000006d50049000000040660008a0000002407d00039000000000067043500000000060404330000000005650436000000000006004b00004fd40000613d000000000700001900000020044000390000000008040433000000009a0804340000000500a0008c000051290000213d000000000aa50436000000000909043300001a9b0990019700000000009a043500000040098000390000000009090433000000400a50003900000000009a043500000060098000390000000009090433000000600a50003900000000009a04350000008008800039000000000808043300001a9b0880019700000080095000390000000000890435000000a0055000390000000107700039000000000067004b00004fba0000413d0000000004d50049000000040440008a0000004406d00039000000000046043500000000640204340000000002450436000000000004004b00004fe40000613d000000000500001900000000072500190000000008560019000000000808043300000000008704350000002005500039000000000045004b00004fdd0000413d000000000542001900000000000504350000001f0440003900001b1f0440019700000000024200190000000004d20049000000040440008a0000006405d00039000000000045043500000000040104330000000002420436000000000004004b00004ff80000613d00000000050000190000002001100039000000000601043300000000026204360000000105500039000000000045004b00004ff20000413d000000040100002900001b64011001970000008404d0003900000000001404350000000001000414000000040030008c000050040000c13d0000000103000031000000200030008c00000020040000390000000004034019000050360000013d0000000002d2004900001a980020009c00001a9802008041000000600220021000001a9800d0009c00001a980400004100000000040d40190000004004400210000000000242019f00001a980010009c00001a9801008041000000c001100210000000000112019f0000000002030019001d0000000d001d6a5a6a500000040f0000001d0d0000290000000003010019000000600330027000001a9803300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057d0019000050250000613d000000000801034f00000000090d0019000000008a08043c0000000009a90436000000000059004b000050210000c13d000000000006004b000050320000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000100000003001f00030000000103550000000100200190000051c10000613d0000001f01400039000000600210018f0000000001d20019000000000021004b0000000002000039000000010200403900001ac20010009c000050fe0000213d0000000100200190000050fe0000c13d000000400010043f000000200030008c000051040000413d00000000020d043300001b3900200198000051040000c13d00001b3d0220019700001b630020009c000048ab0000c13d000000000d0100190000508f0000013d0000000001f1004900001a980010009c00001a9801008041000000600110021000001a9800f0009c00001a980400004100000000040f40190000004004400210000000000141019f00001a980030009c00001a9803008041000000c003300210000000000113019f001d0000000f001d6a5a6a500000040f0000001d0f0000290000000003010019000000600330027000001a9803300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057f00190000506b0000613d000000000801034f00000000090f0019000000008a08043c0000000009a90436000000000059004b000050670000c13d000000000006004b000050780000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000100000003001f00030000000103550000000100200190000051cd0000613d0000001f01400039000000600110018f000000000df1001900000000001d004b0000000001000039000000010100403900001ac200d0009c000050fe0000213d0000000100100190000050fe0000c13d0000004000d0043f000000200030008c000051040000413d00000000010f043300001b3900100198000051040000c13d00001b3d0110019700001b3c0010009c000051b70000c13d000000010400002900000017010000290000000003010433000000220100002900000000010104330000000002040433000000180400002900000000040404330000004005d0003900000080060000390000000000650435000000020500002900001a9b055001970000002006d000390000000000560435000000040500002900000000005d04350000008005d0003900000000060404330000000000650435000000a005d00039000000000006004b000050bc0000613d000000000700001900000020044000390000000008040433000000009a0804340000000500a0008c000051290000213d000000000aa50436000000000909043300001a9b0990019700000000009a043500000040098000390000000009090433000000400a50003900000000009a0435000000600880003900000000080804330000006009500039000000000089043500000080055000390000000107700039000000000067004b000050a70000413d0000000004d500490000006006d00039000000000046043500000000060304330000000004650436000000000006004b000050de0000613d0000000005000019000000200330003900000000070304330000000089070434000000050090008c000051290000213d0000000009940436000000000808043300001a9b088001970000000000890435000000400870003900000000080804330000004009400039000000000089043500000060087000390000000008080433000000600940003900000000008904350000008007700039000000000707043300001a9b0770019700000080084000390000000000780435000000a0044000390000000105500039000000000065004b000050c40000413d00001a9b0620019700001a9b051001970000000001d4004900001a980010009c00001a9801008041000000600110021000001a9800d0009c00001a980d0080410000004002d00210000000000121019f000000000200041400001a980020009c00001a9802008041000000c002200210000000000121019f00001ac1011001c70000800d02000039000000030300003900001b30040000416a5a6a500000040f0000000100200190000051040000613d000000000001042d000000000005004b0000000003050019000049390000c13d00001b0801000041000000000010043f0000001201000039000000040010043f00001b090100004100006a5c0001043000001b0801000041000000000010043f0000004101000039000000040010043f00001b090100004100006a5c00010430000000000100001900006a5c0001043000001b0801000041000000000010043f0000003201000039000000040010043f00001b090100004100006a5c0001043000001b0801000041000000000010043f0000001101000039000000040010043f00001b090100004100006a5c00010430000000400100043d00001b5202000041000051530000013d000000000001042f000000400100043d0000002402100039000000000032043500001b5a020000410000511f0000013d000000400100043d0000002402100039000000000032043500001b590200004100000000002104350000000402100039000000000002043500001a980010009c00001a9801008041000000400110021000001b2a011001c700006a5c00010430000000010020008c0000513b0000a13d00001b0801000041000000000010043f0000002101000039000000040010043f00001b090100004100006a5c00010430000000400100043d00001b5802000041000051530000013d000000400100043d00001b4102000041000051530000013d000000400100043d00001b5502000041000051530000013d000000400100043d00001b3f02000041000051530000013d000000400300043d001d00000003001d00001b5401000041000000000013043500000004013000396a5a5b690000040f0000001d02000029000000000121004900001a980010009c00001a9801008041000000600110021000001a980020009c00001a98020080410000004002200210000000000121019f00006a5c00010430000000400100043d00001b5602000041000051530000013d000000400100043d00001b5302000041000051530000013d000000400100043d00001b4002000041000000000021043500001a980010009c00001a9801008041000000400110021000001aca011001c700006a5c00010430000000400100043d0000002402100039000000000042043500001b29020000410000000000210435000000040210003900004d710000013d000000400100043d00001b4a02000041000051530000013d00001b3a0100004100000000001b04350000001c0100002900000000001304350000001d01000029000000000014043500001a9800b0009c00001a980b0080410000004001b0021000001b2a011001c700006a5c00010430000000400100043d00000024021000390000001d03000029000000000032043500001b3402000041000000000021043500000004021000390000001c0300002900004d710000013d000000400100043d00001b1502000041000051530000013d000000400100043d00001b4902000041000051530000013d000000400100043d00001b1202000041000048ac0000013d000000400100043d00001b1402000041000048ac0000013d00030000000103550000000002010019000000600220027000011a980020019d00001a98022001970000518b0000013d0000000301000367000000010200003100001b1f052001980000001f0620018f000000400300043d0000000004530019000051960000613d000000000701034f0000000008030019000000007907043c0000000008980436000000000048004b000051920000c13d000000000006004b000051a30000613d000000000151034f0000000305600210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f000000000014043500001a980020009c00001a9802008041000000600120021000001a980030009c00001a98030080410000004002300210000000000112019f00006a5c000104300000001f0530018f00001a9a06300198000000400200043d0000000004620019000051d80000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000051b20000c13d000051d80000013d00001b3e0100004100000000001d04350000000401d000390000000402000029000000000021043500001a9800d0009c00001a980d0080410000004001d0021000001b09011001c700006a5c000104300000001f0530018f00001a9a06300198000000400200043d0000000004620019000051d80000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000051c80000c13d000051d80000013d0000001f0530018f00001a9a06300198000000400200043d0000000004620019000051d80000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000051d40000c13d000000000005004b000051e50000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f0000000000140435000000600130021000001a980020009c00001a98020080410000004002200210000000000112019f00006a5c00010430000b000000000002000700000004001d000800000003001d000900000002001d000a00000001001d000600000005001d000000000005004b000053ce0000613d0000000012070434000b00000001001d000000000062004b000052db0000613d0000000b0100002900000000010104330000000001010433000000000001004b000052db0000613d000400000002001d000100000006001d000200000007001d000000400100043d000500000001001d000000200210003900001b3501000041000300000002001d000000000012043500001b040100004100000000001004430000000001000412000000040010044300000120010000390000002400100443000000000100041400001a980010009c00001a9801008041000000c00110021000001b05011001c700008005020000396a5a6a550000040f0000000100200190000053cb0000613d000000000101043b0000000504000029000000600240003900000004030000290000000000320435000000400240003900001a9b01100197000000000012043500001b040100004100000000001004430000000001000412000000040010044300000160010000390000002400100443000000000100041400001a980010009c00001a9801008041000000c00110021000001b05011001c700008005020000396a5a6a550000040f0000000100200190000053cb0000613d000000000101043b0000000504000029000000a00240003900001b3603000041000000000032043500000080024000390000000000120435000000a001000039000000000014043500001b660040009c000053bf0000813d0000000502000029000000c001200039000000400010043f000000030100002900001a980010009c00001a98010080410000004001100210000000000202043300001a980020009c00001a98020080410000006002200210000000000112019f000000000200041400001a980020009c00001a9802008041000000c002200210000000000112019f00001ac1011001c700008010020000396a5a6a550000040f0000000100200190000053cc0000613d000000000101043b00001b3702000041000000000020044300001a9b01100197000500000001001d0000000400100443000000000100041400001a980010009c00001a9801008041000000c00110021000001b1b011001c700008002020000396a5a6a550000040f0000000100200190000053cb0000613d000000400b00043d0000002404b000390000000403b00039000000000101043b000000000001004b000053e00000613d0000000b01000029000000000201043300001b380100004100000000001b043500000020010000390000000000130435000000000302043300000000003404350000004401b00039000000000003004b0000528c0000613d0000000004000019000000200220003900000000050204330000000067050434000000040070008c000053c50000813d0000000007710436000000000606043300001a9b0660019700000000006704350000004006500039000000000606043300001a9b06600197000000400710003900000000006704350000006006500039000000000606043300001a9b06600197000000600710003900000000006704350000008006500039000000000606043300000080071000390000000000670435000000a0055000390000000005050433000000a0061000390000000000560435000000c0011000390000000104400039000000000034004b0000526d0000413d00000000040004140000000502000029000000040020008c000052950000c13d0000000103000031000000200030008c00000020040000390000000004034019000052c60000013d0000000001b1004900001a980010009c00001a9801008041000000600110021000001a9800b0009c00001a980300004100000000030b40190000004003300210000000000131019f00001a980040009c00001a9804008041000000c003400210000000000131019f00050000000b001d6a5a6a500000040f000000050b0000290000000003010019000000600330027000001a9803300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b0019000052b50000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b000052b10000c13d000000000006004b000052c20000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000100000003001f00030000000103550000000100200190000053f80000613d0000001f01400039000000600210018f0000000001b20019000000000021004b0000000002000039000000010200403900001ac20010009c000053bf0000213d0000000100200190000053bf0000c13d000000400010043f000000200030008c000053cc0000413d00000000010b043300001b3900100198000053cc0000c13d00000060010000390000000b02000029000000000012043500000002070000290000000106000029000000000006004b000053670000613d000000000f060019000000000e0700190000000b0100002900000000010104330000000001010433000000010010003a000054160000413d000000010310003900001ac20030009c000053bf0000213d00000005043002100000003f0240003900001b0205200197000000400200043d0000000005520019000000000025004b0000000006000039000000010600403900001ac20050009c000053bf0000213d0000000100600190000053bf0000c13d000000400050043f00000000033204360000000005000019000000400600043d00001ac80060009c000053bf0000213d000000c007600039000000400070043f000000a0076000390000000000070435000000800760003900000000000704350000006007600039000000000007043500000040076000390000000000070435000000200760003900000000000704350000000000060435000000000753001900000000006704350000002005500039000000000045004b000052f60000413d000000000001004b000053410000613d00000000040000190000000b0500002900000000060504330000000005060433000000000045004b000053b90000a13d00000005054002100000000006650019000000200660003900000000080604330000000097080434000000030070008c000053c50000213d000000400600043d00001ac80060009c000053bf0000213d0000000009090433000000400a800039000000000a0a0433000000600b800039000000000b0b0433000000800c800039000000000c0c0433000000a0088000390000000008080433000000c00d6000390000004000d0043f000000a00d60003900000000008d043500000080086000390000000000c8043500001a9b08b00197000000600b60003900000000008b043500001a9b08a00197000000400a60003900000000008a043500001a9b089001970000002009600039000000000089043500000000007604350000000007020433000000000047004b000053b90000a13d000000000553001900000000006504350000000005020433000000000045004b000053b90000a13d0000000104400039000000000014004b0000530e0000413d000000400400043d00001ac80040009c000053bf0000213d000000c005400039000000400050043f000000a00540003900000006060000290000000000650435000000800540003900000007060000290000000000650435000000080500002900001a9b0550019700000060064000390000000000560435000000090500002900001a9b05500197000000400640003900000000005604350000000a0500002900001a9b0550019700000020064000390000000000560435000000030500003900000000005404350000000005020433000000000015004b000053b90000a13d0000000505100210000000000353001900000000004304350000000003020433000000000013004b000053b90000a13d0000000b0100002900000000002104350000000000fe0435000000000001042d00001b370100004100000000001004430000000a010000290000000400100443000000000100041400001a980010009c00001a9801008041000000c00110021000001b1b011001c700008002020000396a5a6a550000040f0000000100200190000053cb0000613d0000000a0200002900001a9b03200197000000000101043b000000000001004b000053d60000613d00001b37010000410000000000100443000b00000003001d0000000400300443000000000100041400001a980010009c00001a9801008041000000c00110021000001b1b011001c700008002020000396a5a6a550000040f0000000100200190000053cb0000613d000000000101043b000000000001004b000053cc0000613d000000400400043d0000008401400039000000a0020000390000000000210435000000640140003900000006020000290000000000210435000000440140003900000007020000290000000000210435000000080100002900001a9b011001970000002402400039000000000012043500001b67010000410000000000140435000000090100002900001a9b0110019700000004024000390000000000120435000000a401400039000000000001043500000000010004140000000b02000029000000040020008c000053b50000613d00001a980040009c00001a98030000410000000003044019000000400330021000001a980010009c00001a9801008041000000c001100210000000000131019f00001b68011001c7000b00000004001d6a5a6a500000040f0000000b040000290000000003010019000000600330027000011a980030019d00030000000103550000000100200190000053eb0000613d00001ac20040009c000053bf0000213d000000400040043f000000000001042d00001b0801000041000000000010043f0000003201000039000000040010043f00001b090100004100006a5c0001043000001b0801000041000000000010043f0000004101000039000000040010043f00001b090100004100006a5c0001043000001b0801000041000000000010043f0000002101000039000000040010043f00001b090100004100006a5c00010430000000000001042f000000000100001900006a5c00010430000000400100043d00001b3f02000041000000000021043500001a980010009c00001a9801008041000000400110021000001aca011001c700006a5c00010430000000400100043d00001b690200004100000000002104350000000402100039000000000032043500001a980010009c00001a9801008041000000400110021000001b09011001c700006a5c0001043000001b3a0100004100000000001b0435000000040100002900000000001304350000000501000029000000000014043500001a9800b0009c00001a980b0080410000004001b0021000001b2a011001c700006a5c0001043000001a98033001970000001f0530018f00001a9a06300198000000400200043d0000000004620019000054030000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000053f30000c13d000054030000013d0000001f0530018f00001a9a06300198000000400200043d0000000004620019000054030000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000053ff0000c13d000000000005004b000054100000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f0000000000140435000000600130021000001a980020009c00001a98020080410000004002200210000000000112019f00006a5c0001043000001b0801000041000000000010043f0000001101000039000000040010043f00001b090100004100006a5c00010430000b000000000002000800000004001d000900000003001d000a00000002001d000b00000001001d000600000007001d00000000f2070434000000000062004b000700000006001d000055090000613d00000000010f04330000000001010433000000000001004b000055090000613d000300000002001d000100000005001d00040000000f001d000000400100043d000500000001001d000000200210003900001b3501000041000200000002001d000000000012043500001b040100004100000000001004430000000001000412000000040010044300000120010000390000002400100443000000000100041400001a980010009c00001a9801008041000000c00110021000001b05011001c700008005020000396a5a6a550000040f0000000100200190000055f00000613d000000000101043b0000000504000029000000600240003900000003030000290000000000320435000000400240003900001a9b01100197000000000012043500001b040100004100000000001004430000000001000412000000040010044300000160010000390000002400100443000000000100041400001a980010009c00001a9801008041000000c00110021000001b05011001c700008005020000396a5a6a550000040f0000000100200190000055f00000613d000000000101043b0000000504000029000000a00240003900001b3603000041000000000032043500000080024000390000000000120435000000a001000039000000000014043500001b660040009c000055e40000813d0000000502000029000000c001200039000000400010043f000000020100002900001a980010009c00001a98010080410000004001100210000000000202043300001a980020009c00001a98020080410000006002200210000000000112019f000000000200041400001a980020009c00001a9802008041000000c002200210000000000112019f00001ac1011001c700008010020000396a5a6a550000040f0000000100200190000055f10000613d000000000101043b00001b3702000041000000000020044300001a9b01100197000500000001001d0000000400100443000000000100041400001a980010009c00001a9801008041000000c00110021000001b1b011001c700008002020000396a5a6a550000040f0000000100200190000055f00000613d000000400b00043d0000002404b000390000000403b00039000000000101043b000000000001004b000056030000613d0000000401000029000000000201043300001b380100004100000000001b043500000020010000390000000000130435000000000302043300000000003404350000004401b00039000000000003004b000054ba0000613d0000000004000019000000200220003900000000050204330000000067050434000000040070008c000055ea0000813d0000000007710436000000000606043300001a9b0660019700000000006704350000004006500039000000000606043300001a9b06600197000000400710003900000000006704350000006006500039000000000606043300001a9b06600197000000600710003900000000006704350000008006500039000000000606043300000080071000390000000000670435000000a0055000390000000005050433000000a0061000390000000000560435000000c0011000390000000104400039000000000034004b0000549b0000413d00000000040004140000000502000029000000040020008c000054c30000c13d0000000103000031000000200030008c00000020040000390000000004034019000054f40000013d0000000001b1004900001a980010009c00001a9801008041000000600110021000001a9800b0009c00001a980300004100000000030b40190000004003300210000000000131019f00001a980040009c00001a9804008041000000c003400210000000000131019f00050000000b001d6a5a6a500000040f000000050b0000290000000003010019000000600330027000001a9803300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b0019000054e30000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b000054df0000c13d000000000006004b000054f00000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000100000003001f000300000001035500000001002001900000561b0000613d0000001f01400039000000600210018f0000000001b20019000000000021004b0000000002000039000000010200403900001ac20010009c000055e40000213d0000000100200190000055e40000c13d000000400010043f000000200030008c000055f10000413d00000000010b043300001b3900100198000055f10000c13d0000006001000039000000040f00002900000000001f043500000007060000290000000105000029000000000006004b000055920000613d000000000e05001900000000010f04330000000001010433000000010010003a000056390000413d000000010310003900001ac20030009c000055e40000213d00000005043002100000003f0240003900001b0205200197000000400200043d0000000005520019000000000025004b0000000006000039000000010600403900001ac20050009c000055e40000213d0000000100600190000055e40000c13d000000400050043f00000000033204360000000005000019000000400600043d00001ac80060009c000055e40000213d000000c007600039000000400070043f000000a0076000390000000000070435000000800760003900000000000704350000006007600039000000000007043500000040076000390000000000070435000000200760003900000000000704350000000000060435000000000753001900000000006704350000002005500039000000000045004b000055220000413d000000000001004b0000556c0000613d000000000400001900000000060f04330000000005060433000000000045004b000055de0000a13d00000005054002100000000006650019000000200660003900000000080604330000000097080434000000030070008c000055ea0000213d000000400600043d00001ac80060009c000055e40000213d0000000009090433000000400a800039000000000a0a0433000000600b800039000000000b0b0433000000800c800039000000000c0c0433000000a0088000390000000008080433000000c00d6000390000004000d0043f000000a00d60003900000000008d043500000080086000390000000000c8043500001a9b08b00197000000600b60003900000000008b043500001a9b08a00197000000400a60003900000000008a043500001a9b089001970000002009600039000000000089043500000000007604350000000007020433000000000047004b000055de0000a13d000000000553001900000000006504350000000005020433000000000045004b000055de0000a13d0000000104400039000000000014004b0000553a0000413d000000400400043d00001ac80040009c000055e40000213d000000c005400039000000400050043f000000a0054000390000000000e50435000000800540003900000008060000290000000000650435000000090500002900001a9b05500197000000600640003900000000005604350000000a0500002900001a9b05500197000000400640003900000000005604350000000b0500002900001a9b0550019700000020064000390000000000560435000000020500003900000000005404350000000005020433000000000015004b000055de0000a13d0000000505100210000000000353001900000000004304350000000003020433000000000013004b000055de0000a13d00000000002f0435000000060100002900000007020000290000000000210435000000000001042d000000010050008c000055f30000c13d00001b370100004100000000001004430000000b010000290000000400100443000000000100041400001a980010009c00001a9801008041000000c00110021000001b1b011001c700008002020000396a5a6a550000040f0000000100200190000055f00000613d0000000b0200002900001a9b03200197000000000101043b000000000001004b000055f90000613d00001b37010000410000000000100443000b00000003001d0000000400300443000000000100041400001a980010009c00001a9801008041000000c00110021000001b1b011001c700008002020000396a5a6a550000040f0000000100200190000055f00000613d000000000101043b000000000001004b000055f10000613d000000400400043d000000440140003900000008020000290000000000210435000000090100002900001a9b011001970000002402400039000000000012043500001b6b0100004100000000001404350000000a0100002900001a9b011001970000000402400039000000000012043500000000010004140000000b02000029000000040020008c000055da0000613d00001a980040009c00001a98030000410000000003044019000000400330021000001a980010009c00001a9801008041000000c001100210000000000131019f00001b6c011001c7000b00000004001d6a5a6a500000040f0000000b040000290000000003010019000000600330027000011a980030019d000300000001035500000001002001900000560e0000613d00001ac20040009c000055e40000213d000000400040043f000000000001042d00001b0801000041000000000010043f0000003201000039000000040010043f00001b090100004100006a5c0001043000001b0801000041000000000010043f0000004101000039000000040010043f00001b090100004100006a5c0001043000001b0801000041000000000010043f0000002101000039000000040010043f00001b090100004100006a5c00010430000000000001042f000000000100001900006a5c00010430000000400100043d00001b6a02000041000000000021043500000004021000390000000000520435000055fe0000013d000000400100043d00001b690200004100000000002104350000000402100039000000000032043500001a980010009c00001a9801008041000000400110021000001b09011001c700006a5c0001043000001b3a0100004100000000001b0435000000030100002900000000001304350000000501000029000000000014043500001a9800b0009c00001a980b0080410000004001b0021000001b2a011001c700006a5c0001043000001a98033001970000001f0530018f00001a9a06300198000000400200043d0000000004620019000056260000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000056160000c13d000056260000013d0000001f0530018f00001a9a06300198000000400200043d0000000004620019000056260000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000056220000c13d000000000005004b000056330000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f0000000000140435000000600130021000001a980020009c00001a98020080410000004002200210000000000112019f00006a5c0001043000001b0801000041000000000010043f0000001101000039000000040010043f00001b090100004100006a5c00010430000d0000000000020000014002100039000a00000002001d00000000030204330000006002100039000400000002001d00000000020204330000000002020433000000000032004b000058440000413d000300000001001d0000000021010434000200000002001d00001a9b01100197000000000010043f0000000201000039000000200010043f000000000100041400001a980010009c00001a9801008041000000c00110021000001b0b011001c700008010020000396a5a6a550000040f00000001002001900000583b0000613d000000000101043b00000003020000290000004002200039000900000002001d0000000002020433000000000302043300001b250030009c000058350000813d00000005023002100000003f0420003900001b0204400197000000400700043d0000000004470019000000000074004b0000000005000039000000010500403900001ac20040009c000058350000213d0000000100500190000058350000c13d000000000101041a000100000001001d000000400040043f0000000001370436000700000001001d0000001f0320018f00000000010000310000000201100367000000000002004b0000567e0000613d00000007050000290000000002250019000000000401034f000000004604043c0000000005650436000000000025004b0000567a0000c13d000000000003004b0000000a02000029000000000302043300001ac20030009c000058350000213d00000005023002100000003f0420003900001b0204400197000000400600043d0000000004460019000000000064004b0000000005000039000000010500403900001ac20040009c000058350000213d0000000100500190000058350000c13d000000400040043f0000000003360436000600000003001d0000001f0320018f000000000002004b0000569b0000613d00000006040000290000000002240019000000001501043c0000000004540436000000000024004b000056970000c13d000d00000007001d000800000006001d000000000003004b00001b040100004100000000001004430000000001000412000000040010044300000060010000390000002400100443000000000100041400001a980010009c00001a9801008041000000c00110021000001b05011001c700008005020000396a5a6a550000040f0000000100200190000058430000613d000000000101043b000500000001001d000000090100002900000000010104330000000002010433000000000002004b000056fa0000613d0000000004000019000b0005004002180000000b01100029000000200110003900000000010104330000000032010434000000060020008c0000583d0000813d000c00000004001d0000000003030433000000400410003900000000040404330000006005100039000000000505043300000080011000390000000006010433000000400100043d000000c0071000390000000000670435000000a0061000390000000000560435000000800510003900000000004504350000004004100039000000000024043500001a9b0230019700000060031000390000000000230435000000200210003900000005030000290000000000320435000000c003000039000000000031043500001b060010009c000058350000213d000000e003100039000000400030043f00001a980020009c00001a98020080410000004002200210000000000101043300001a980010009c00001a98010080410000006001100210000000000121019f000000000200041400001a980020009c00001a9802008041000000c002200210000000000112019f00001ac1011001c700008010020000396a5a6a550000040f00000001002001900000583b0000613d0000000d0200002900000000020204330000000c04000029000000000042004b0000582f0000a13d0000000b030000290000000702300029000000000101043b00000000001204350000000104400039000000090100002900000000010104330000000002010433000000000024004b000056b50000413d00001b040100004100000000001004430000000001000412000000040010044300000080010000390000002400100443000000000100041400001a980010009c00001a9801008041000000c00110021000001b05011001c700008005020000396a5a6a550000040f0000000100200190000058430000613d000000000101043b000900000001001d0000000a010000290000000001010433000000000001004b0000000d07000029000057600000613d0000000004000019000000040100002900000000010104330000000002010433000000000042004b0000582f0000a13d000b0005004002180000000b01100029000000200110003900000000010104330000000032010434000000050020008c0000583d0000213d000c00000004001d0000000003030433000000a0041000390000000004040433000000400510003900000000050504330000006006100039000000000606043300000080011000390000000007010433000000400100043d000000c0081000390000000000780435000000a0071000390000000000670435000000800610003900000000005604350000004005100039000000000025043500001a9b02400197000000e004100039000000000024043500001a9b0230019700000060031000390000000000230435000000200210003900000009030000290000000000320435000000e003000039000000000031043500001b070010009c000058350000213d0000010003100039000000400030043f00001a980020009c00001a98020080410000004002200210000000000101043300001a980010009c00001a98010080410000006001100210000000000121019f000000000200041400001a980020009c00001a9802008041000000c002200210000000000112019f00001ac1011001c700008010020000396a5a6a550000040f00000001002001900000583b0000613d000000080200002900000000020204330000000c04000029000000000042004b0000000d070000290000582f0000a13d0000000b030000290000000602300029000000000101043b000000000012043500000001044000390000000a010000290000000001010433000000000014004b000057110000413d000000400100043d000000200210003900000003030000290000000003030433000d00000003001d00000002030000290000000003030433000c00000003001d0000000003070433000000000003004b0000000004020019000057740000613d000000000500001900000000040200190000002007700039000000000607043300000000046404360000000105500039000000000035004b0000576e0000413d0000000003140049000000200430008a00000000004104350000001f0330003900001b1f043001970000000003140019000000000043004b0000000004000039000000010400403900001ac20030009c000058350000213d0000000100400190000058350000c13d000000400030043f00001a980020009c00001a98020080410000004002200210000000000101043300001a980010009c00001a98010080410000006001100210000000000121019f000000000200041400001a980020009c00001a9802008041000000c002200210000000000112019f00001ac1011001c700008010020000396a5a6a550000040f00000001002001900000583b0000613d000000400200043d0000002003200039000000000101043b000b00000001001d00000008070000290000000001070433000000000001004b0000000004030019000057a50000613d000000000500001900000000040300190000002007700039000000000607043300000000046404360000000105500039000000000015004b0000579f0000413d0000000001240049000000200410008a00000000004204350000001f0110003900001b1f041001970000000001240019000000000041004b0000000004000039000000010400403900001ac20010009c000058350000213d0000000100400190000058350000c13d000000400010043f00001a980030009c00001a98030080410000004001300210000000000202043300001a980020009c00001a98020080410000006002200210000000000112019f000000000200041400001a980020009c00001a9802008041000000c002200210000000000112019f00001ac1011001c700008010020000396a5a6a550000040f00000001002001900000583b0000613d000000000101043b000a00000001001d000000030100002900000080011000390000000001010433000900000001001d000000040010008c0000583d0000213d000000030200002900000120012000390000000001010433000200000001001d00000100012000390000000001010433000400000001001d000000e0012000390000000001010433000500000001001d000000c0012000390000000001010433000600000001001d000000a0012000390000000001010433000700000001001d000000400100043d000800000001001d00001b0401000041000000000010044300000000010004120000000400100443000000a0010000390000002400100443000000000100041400001a980010009c00001a9801008041000000c00110021000001b05011001c700008005020000396a5a6a550000040f0000000100200190000058430000613d0000000d0200002900001a9b022001970000000c0300002900001a9b03300197000000000401043b0000000806000029000001800160003900000001050000290000000000510435000001600160003900000002050000290000000000510435000001400160003900000004050000290000000000510435000001200160003900000005050000290000000000510435000001000160003900000006050000290000000000510435000000e00160003900000007050000290000000000510435000000c00160003900000009050000290000000000510435000000a0016000390000000a05000029000000000051043500000080016000390000000b0500002900000000005104350000006001600039000000000031043500000040016000390000000000210435000000200160003900000000004104350000018002000039000000000026043500001b0a0060009c000058350000213d000001a002600039000000400020043f00001a980010009c00001a98010080410000004001100210000000000206043300001a980020009c00001a98020080410000006002200210000000000112019f000000000200041400001a980020009c00001a9802008041000000c002200210000000000112019f00001ac1011001c700008010020000396a5a6a550000040f00000001002001900000583b0000613d000000000101043b000000000001042d00001b0801000041000000000010043f0000003201000039000000040010043f00001b090100004100006a5c0001043000001b0801000041000000000010043f0000004101000039000000040010043f00001b090100004100006a5c00010430000000000100001900006a5c0001043000001b0801000041000000000010043f0000002101000039000000040010043f00001b090100004100006a5c00010430000000000001042f000000400100043d00001b4202000041000000000021043500001a980010009c00001a9801008041000000400110021000001aca011001c700006a5c00010430000a000000000002000003800030043f00001a9b041001970000000003000411000000000034004b00005b140000613d000900000002001d000400000001001d000300000004001d00001b0401000041000000000010044300000000010004120000000400100443000000e0010000390000002400100443000000000100041400001a980010009c00001a9801008041000000c00110021000001b05011001c700008005020000396a5a6a550000040f000000010020019000005b230000613d000000000101043b000a00000001001d00001ac6010000410000000000100443000000000100041400001a980010009c00001a9801008041000000c00110021000001ac7011001c70000800b020000396a5a6a550000040f000000010020019000005b230000613d000000000201043b00001b04010000410000000000100443000000000100041200000004001004430000000a0020006c0000004001000039000058850000c13d00000100010000390000002400100443000000000100041400001a980010009c00001a9801008041000000c00110021000001b05011001c700008005020000396a5a6a550000040f0000000100200190000058dc0000c13d00005b230000013d000800000002001d000000400200043d000a00000002001d0000002400100443000000000100041400001a980010009c00001a9801008041000000c00110021000001b05011001c700008005020000396a5a6a550000040f000000010020019000005b230000613d0000000a020000290000002002200039000000000101043b000700000002001d000000000012043500001b04010000410000000000100443000000000100041200000004001004430000002400000443000000000100041400001a980010009c00001a9801008041000000c00110021000001b05011001c700008005020000396a5a6a550000040f000000010020019000005b230000613d000000000101043b0000000a020000290000004002200039000000000012043500001b040100004100000000001004430000000001000412000000040010044300000020010000390000002400100443000000000100041400001a980010009c00001a9801008041000000c00110021000001b05011001c700008005020000396a5a6a550000040f000000010020019000005b230000613d000000000101043b0000000a04000029000000a0024000390000000003000410000000000032043500000080024000390000000803000029000000000032043500000060024000390000000000120435000000a001000039000000000014043500001b660040009c00005b1d0000813d0000000a02000029000000c001200039000000400010043f000000070100002900001a980010009c00001a98010080410000004001100210000000000202043300001a980020009c00001a98020080410000006002200210000000000112019f000000000200041400001a980020009c00001a9802008041000000c002200210000000000112019f00001ac1011001c700008010020000396a5a6a550000040f000000010020019000005b1b0000613d000000000401043b000000400100043d000000420210003900000009030000290000000000320435000000200210003900001b6d030000410000000000320435000000420300003900000000003104350000002203100039000100000004001d000000000043043500001b2e0010009c00005b1d0000213d0000008003100039000000400030043f00001a980020009c00001a98020080410000004002200210000000000101043300001a980010009c00001a98010080410000006001100210000000000121019f000000000200041400001a980020009c00001a9802008041000000c002200210000000000112019f00001ac1011001c700008010020000396a5a6a550000040f000000010020019000005b1b0000613d000000000401043b000003800500043d0000000001050433000003450210008a00001b780020009c000200000004001d000059080000813d000a00000005001d00005a450000013d0000001d021000390000001e00200190000a00000005001d000000040200002900005a460000c13d000000010110018f000000410210015f0000001f01200039000000600110018f0000003f03100039000000e00330018f000000400400043d0000000003340019000a00000004001d000000000043004b0000000004000039000000010400403900001ac20030009c00005b1d0000213d000000010040019000005b1d0000c13d000000400030043f0000000a030000290000000003230436000000000413001900000000010000310000000201100367000000000501034f0000000006030019000000005705043c0000000006760436000000000046004b000059250000c13d0000000004000019000003800500043d0000000006050433000000000046004b00005b150000a13d0000000a060000290000000006060433000000000046004b00005b150000a13d0000000006340019000000000706043300001b6e0770019700000000055400190000002005500039000000000505043300001b6f05500197000000000557019f00000000005604350000000104400039000000000024004b0000592a0000413d000003800300043d0000000034030434000000000624004b00005b150000a13d0000000105200039000000000054004b00005b150000a13d00000002072001bf000000000074004b00005b150000a13d00001b710060009c00005b1d0000213d00001b1f086001970000003f0480003900001b0204400197000000400a00043d00000000094a001900080000000a001d0000000000a9004b0000000004000039000000010400403900001ac20090009c00005b1d0000213d000000010040019000005b1d0000c13d000000000423001900000000040404330000000005530019000000000505043300000000037300190000000003030433000000050a600270000000400090043f000000080700002900060000000a001d0000000007a70436000700000007001d000000000008004b0000596c0000613d00000007090000290000000007890019000000000801034f000000008a08043c0000000009a90436000000000079004b000059680000c13d000000200060008c000059a60000413d0000000302200039000000200600003900000000070000190000000508700210000000000007004b000059770000613d00000000097800d9000000200090008c00005b240000c13d000000000028001a00005b240000413d000000400a00043d00001a9c00a0009c00005b1d0000213d000000000b2800190000004009a00039000000400090043f00000000096a0436000000000c01043b0000000000c90435000000000c000019000000000dbc0019000003800e00043d000000000f0e04330000000000df004b00005b150000a13d000000000f0a04330000000000cf004b00005b150000a13d000000000ded0019000000000e9c0019000000000f0e043300001b6e0ff00197000000200dd00039000000000d0d043300001b6f0dd00197000000000ddf019f0000000000de04350000001f00c0008c000000010cc00039000059830000413d000000000a0a043300001b0300a0009c00005b1b0000213d0000002000a0008c00005b1b0000413d000000080a000029000000000a0a043300000000007a004b00005b150000a13d0000000708800029000000000909043300000000009804350000000107700039000000060070006c000059710000413d00000008010000290000000001010433000000000001004b000059f30000613d000000e801400270000000f00250027000001b70011001970000ff000220018f000000000112019f000000f80230027000050000002101a30000000008000019000000090600002900000005018002100000000704100029000000400100043d000000400310003900000020021000390000000004040433000000ff0080008c000900000008001d000059d10000213d000000010580020f0000000500500180000059d10000613d000000000042043500000000006304350000004003000039000000000031043500001ac50010009c00005b1d0000213d0000006003100039000000400030043f00001a980020009c00001a98020080410000004002200210000000000101043300001a980010009c00001a98010080410000006001100210000000000121019f0000000002000414000059e20000013d000000000062043500000000004304350000004003000039000000000031043500001ac50010009c00005b1d0000213d0000006003100039000000400030043f00001a980020009c00001a98020080410000004002200210000000000101043300001a980010009c00001a98010080410000006001100210000000000121019f000000000200041400001a980020009c00001a9802008041000000c002200210000000000112019f00001ac1011001c700008010020000396a5a6a550000040f000000010020019000005b1b0000613d0000000908000029000000000601043b000000010880003900000008010000290000000001010433000000000018004b000059b30000413d000059f40000013d0000000906000029000900000006001d0000000601000029000000000010043f000000200000043f000000000100041400001a980010009c00001a9801008041000000c00110021000001b0b011001c700008010020000396a5a6a550000040f000000010020019000005b1b0000613d000000000101043b000000000301041a000000400100043d000000400210003900000009040000290000000000420435000000200210003900000000003204350000004003000039000000000031043500001ac50010009c00005b1d0000213d0000006003100039000000400030043f00001a980020009c00001a98020080410000004002200210000000000101043300001a980010009c00001a98010080410000006001100210000000000121019f000000000200041400001a980020009c00001a9802008041000000c002200210000000000112019f00001ac1011001c700008010020000396a5a6a550000040f000000010020019000005b1b0000613d000000000201043b000000400100043d00000042031000390000000000230435000000200210003900001b6d0300004100000000003204350000002203100039000000010400002900000000004304350000004203000039000000000031043500001b2e0010009c00005b1d0000213d0000008003100039000000400030043f00001a980020009c00001a98020080410000004002200210000000000101043300001a980010009c00001a98010080410000006001100210000000000121019f000000000200041400001a980020009c00001a9802008041000000c002200210000000000112019f00001ac1011001c700008010020000396a5a6a550000040f000000010020019000005b1b0000613d000003800500043d000000000401043b0000000402000029000900000005001d000800000004001d00001b370100004100000000001004430000000400200443000000000100041400001a980010009c00001a9801008041000000c00110021000001b1b011001c700008002020000396a5a6a550000040f000000010020019000005b230000613d000000000101043b000000000001004b000000020300002900005a7a0000613d000000400b00043d0000002401b000390000004002000039000000000021043500001b720100004100000000001b04350000000401b000390000000000310435000000090100002900000000370104340000004401b0003900000000007104350000006401b00039000000000007004b00005a6f0000613d000000000400001900000000051400190000000006430019000000000606043300000000006504350000002004400039000000000074004b00005a680000413d0000000003710019000000000003043500000000030004140000000302000029000000040020008c00005a8a0000c13d0000000103000031000000200030008c0000002004000039000000000403401900005abe0000013d0000000a030000290000000012030434000000400020008c00005ad30000613d000000410020008c00005b570000c13d00000060023000390000000002020433000000f80220027000000000050300190000001d0320008a00001b790030009c00005b5f0000a13d0000004003500039000000000303043300005ad80000013d0000001f0570003900001b1f045001970000000004b40049000000000114001900001a980010009c00001a9801008041000000600110021000001a9800b0009c00001a980400004100000000040b40190000004004400210000000000141019f00001a980030009c00001a9803008041000000c003300210000000000131019f000a0000000b001d6a5a6a550000040f0000000a0b0000290000000003010019000000600330027000001a9803300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b001900005aad0000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b00005aa90000c13d000000000006004b00005aba0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000100000003001f0003000000010355000000010020019000005b390000613d0000001f01400039000000600210018f0000000001b20019000000000021004b0000000002000039000000010200403900001ac20010009c00005b1d0000213d000000010020019000005b1d0000c13d000000400010043f000000200030008c00005b1b0000413d00000000020b043300001b390020019800005b1b0000c13d00001b3d0220019700001b720020009c00005b140000613d00001b730200004100005b590000013d0000004002300039000000000202043300001b0303200197000000ff022002700000001b022000390000000001010433000000400400043d00000060054000390000000000350435000000400340003900000000001304350000002001400039000000000021043500000008010000290000000000140435000000000000043f00001a980040009c00001a98040080410000004001400210000000000200041400001a980020009c00001a9802008041000000c002200210000000000112019f00001b75011001c700000001020000396a5a6a550000040f0000000003010019000000600330027000001a9803300197000000200030008c000000200400003900000000040340190000001f0540018f000000200440019000005afd0000613d000000000601034f0000000007000019000000006806043c0000000007870436000000000047004b00005af90000c13d000000000005004b00005b0a0000613d000000000641034f0000000305500210000000000704043300000000075701cf000000000757022f000000000606043b0000010005500089000000000656022f00000000055601cf000000000575019f0000000000540435000100000003001f0003000000010355000000010020019000005b2a0000613d000000000100043d00001a9b01100198000000030200002900005b360000613d000000000021004b00005b360000c13d000000000001042d00001b0801000041000000000010043f0000003201000039000000040010043f00001b090100004100006a5c00010430000000000100001900006a5c0001043000001b0801000041000000000010043f0000004101000039000000040010043f00001b090100004100006a5c00010430000000000001042f00001b0801000041000000000010043f0000001101000039000000040010043f00001b090100004100006a5c000104300000001f0530018f00001a9a06300198000000400200043d000000000462001900005b440000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00005b310000c13d00005b440000013d000000400100043d00001b760200004100005b590000013d0000001f0530018f00001a9a06300198000000400200043d000000000462001900005b440000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00005b400000c13d000000000005004b00005b510000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f0000000000140435000000600130021000001a980020009c00001a98020080410000004002200210000000000112019f00006a5c00010430000000400100043d00001b7702000041000000000021043500001a980010009c00001a9801008041000000400110021000001aca011001c700006a5c00010430000000400100043d00001b740300004100000000003104350000000403100039000000000023043500001a980010009c00001a9801008041000000400110021000001b09011001c700006a5c00010430000000020020008c00005b6d0000813d0000000001210436000000000001042d00001b0801000041000000000010043f0000002101000039000000040010043f00001b090100004100006a5c00010430000300000000000200001b0401000041000000000010044300000000010004120000000400100443000000e0010000390000002400100443000000000100041400001a980010009c00001a9801008041000000c00110021000001b05011001c700008005020000396a5a6a550000040f000000010020019000005bfd0000613d000000000101043b000300000001001d00001ac6010000410000000000100443000000000100041400001a980010009c00001a9801008041000000c00110021000001ac7011001c70000800b020000396a5a6a550000040f000000010020019000005bfd0000613d000000000201043b00001b0401000041000000000010044300000000010004120000000400100443000000030020006c00005ba30000c13d00000100010000390000002400100443000000000100041400001a980010009c00001a9801008041000000c00110021000001b05011001c700008005020000396a5a6a550000040f000000010020019000005bfb0000c13d00005bfd0000013d000200000002001d000000400100043d000300000001001d00000040010000390000002400100443000000000100041400001a980010009c00001a9801008041000000c00110021000001b05011001c700008005020000396a5a6a550000040f000000010020019000005bfd0000613d00000003020000290000002002200039000000000101043b000100000002001d000000000012043500001b04010000410000000000100443000000000100041200000004001004430000002400000443000000000100041400001a980010009c00001a9801008041000000c00110021000001b05011001c700008005020000396a5a6a550000040f000000010020019000005bfd0000613d000000000101043b00000003020000290000004002200039000000000012043500001b040100004100000000001004430000000001000412000000040010044300000020010000390000002400100443000000000100041400001a980010009c00001a9801008041000000c00110021000001b05011001c700008005020000396a5a6a550000040f000000010020019000005bfd0000613d000000000101043b0000000304000029000000a0024000390000000003000410000000000032043500000080024000390000000203000029000000000032043500000060024000390000000000120435000000a001000039000000000014043500001b660040009c00005bfe0000813d0000000302000029000000c001200039000000400010043f000000010100002900001a980010009c00001a98010080410000004001100210000000000202043300001a980020009c00001a98020080410000006002200210000000000112019f000000000200041400001a980020009c00001a9802008041000000c002200210000000000112019f00001ac1011001c700008010020000396a5a6a550000040f000000010020019000005c040000613d000000000101043b000000000001042d000000000001042f00001b0801000041000000000010043f0000004101000039000000040010043f00001b090100004100006a5c00010430000000000100001900006a5c00010430000a000000000002000600000003001d000700000002001d000800000004001d000000000004004b00005e180000613d0000000023060434000a00000002001d000000000053004b000900000001001d00005cf60000613d0000000a0200002900000000020204330000000002020433000000000002004b00005cf60000613d000400000003001d000100000005001d000200000006001d000000400100043d000500000001001d000000200210003900001b3501000041000300000002001d000000000012043500001b040100004100000000001004430000000001000412000000040010044300000120010000390000002400100443000000000100041400001a980010009c00001a9801008041000000c00110021000001b05011001c700008005020000396a5a6a550000040f000000010020019000005e150000613d000000000101043b0000000504000029000000600240003900000004030000290000000000320435000000400240003900001a9b01100197000000000012043500001b040100004100000000001004430000000001000412000000040010044300000160010000390000002400100443000000000100041400001a980010009c00001a9801008041000000c00110021000001b05011001c700008005020000396a5a6a550000040f000000010020019000005e150000613d000000000101043b0000000504000029000000a00240003900001b3603000041000000000032043500000080024000390000000000120435000000a001000039000000000014043500001b660040009c00005e090000813d0000000502000029000000c001200039000000400010043f000000030100002900001a980010009c00001a98010080410000004001100210000000000202043300001a980020009c00001a98020080410000006002200210000000000112019f000000000200041400001a980020009c00001a9802008041000000c002200210000000000112019f00001ac1011001c700008010020000396a5a6a550000040f000000010020019000005e160000613d000000000101043b00001b3702000041000000000020044300001a9b01100197000500000001001d0000000400100443000000000100041400001a980010009c00001a9801008041000000c00110021000001b1b011001c700008002020000396a5a6a550000040f000000010020019000005e150000613d000000400b00043d0000002404b000390000000403b00039000000000101043b000000000001004b00005e400000613d0000000a01000029000000000201043300001b380100004100000000001b043500000020010000390000000000130435000000000302043300000000003404350000004401b00039000000000003004b00005ca60000613d0000000004000019000000200220003900000000050204330000000067050434000000040070008c00005e0f0000813d0000000007710436000000000606043300001a9b0660019700000000006704350000004006500039000000000606043300001a9b06600197000000400710003900000000006704350000006006500039000000000606043300001a9b06600197000000600710003900000000006704350000008006500039000000000606043300000080071000390000000000670435000000a0055000390000000005050433000000a0061000390000000000560435000000c0011000390000000104400039000000000034004b00005c870000413d00000000040004140000000502000029000000040020008c00005caf0000c13d0000000103000031000000200030008c0000002004000039000000000403401900005ce00000013d0000000001b1004900001a980010009c00001a9801008041000000600110021000001a9800b0009c00001a980300004100000000030b40190000004003300210000000000131019f00001a980040009c00001a9804008041000000c003400210000000000131019f00050000000b001d6a5a6a500000040f000000050b0000290000000003010019000000600330027000001a9803300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b001900005ccf0000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b00005ccb0000c13d000000000006004b00005cdc0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000100000003001f0003000000010355000000010020019000005e5e0000613d0000001f01400039000000600210018f0000000001b20019000000000021004b0000000002000039000000010200403900001ac20010009c00005e090000213d000000010020019000005e090000c13d000000400010043f000000200030008c00005e160000413d00000000010b043300001b390010019800005e160000c13d00000060010000390000000a020000290000000000120435000000090100002900000002060000290000000105000029000000000005004b00005d810000613d000000000f050019000000000e0600190000000a0100002900000000010104330000000001010433000000010010003a00005e7c0000413d000000010310003900001ac20030009c00005e090000213d00000005043002100000003f0240003900001b0205200197000000400200043d0000000005520019000000000025004b0000000006000039000000010600403900001ac20050009c00005e090000213d000000010060019000005e090000c13d000000400050043f00000000033204360000000005000019000000400600043d00001ac80060009c00005e090000213d000000c007600039000000400070043f000000a0076000390000000000070435000000800760003900000000000704350000006007600039000000000007043500000040076000390000000000070435000000200760003900000000000704350000000000060435000000000753001900000000006704350000002005500039000000000045004b00005d110000413d000000000001004b00005d5c0000613d00000000040000190000000a0500002900000000060504330000000005060433000000000045004b00005e030000a13d00000005054002100000000006650019000000200660003900000000080604330000000097080434000000030070008c00005e0f0000213d000000400600043d00001ac80060009c00005e090000213d0000000009090433000000400a800039000000000a0a0433000000600b800039000000000b0b0433000000800c800039000000000c0c0433000000a0088000390000000008080433000000c00d6000390000004000d0043f000000a00d60003900000000008d043500000080086000390000000000c8043500001a9b08b00197000000600b60003900000000008b043500001a9b08a00197000000400a60003900000000008a043500001a9b089001970000002009600039000000000089043500000000007604350000000007020433000000000047004b00005e030000a13d000000000553001900000000006504350000000005020433000000000045004b00005e030000a13d0000000104400039000000000014004b00005d290000413d000000400400043d00001ac80040009c00005e090000213d000000c005400039000000400050043f000000a00540003900000008060000290000000000650435000000060500002900001a9b0550019700000060064000390000000000560435000000070500002900001a9b0550019700000040064000390000000000560435000000090500002900001a9b055001970000002006400039000000000056043500000001050000390000000000540435000000800540003900000000000504350000000005020433000000000015004b00005e030000a13d0000000505100210000000000353001900000000004304350000000003020433000000000013004b00005e030000a13d0000000a0100002900000000002104350000000000fe0435000000000001042d00001b370200004100000000002004430000000400100443000000000100041400001a980010009c00001a9801008041000000c00110021000001b1b011001c700008002020000396a5a6a550000040f000000010020019000005e150000613d000000400200043d000000000101043b000000000001004b00005e200000613d000000640120003900000008030000290000000000310435000000200120003900001b6b03000041000000000031043500000064030000390000000000320435000000060300002900001a9b0c30019700000044032000390000000000c30435000000070300002900001a9b0b30019700000024032000390000000000b3043500001aa80020009c00005e090000213d000000a003200039000000400030043f000000000302043300000000040004140000000902000029000000040020008c00005dd80000c13d00000001040000310000000002000019000000000004004b00005def0000613d00001ac20040009c00005e090000213d0000001f0140003900001b1f011001970000003f0110003900001b1f03100197000000400100043d0000000003310019000000000013004b0000000006000039000000010600403900001ac20030009c00005e090000213d000000010060019000005e090000c13d000000400030043f000000000341043600001b1f054001980000001f0640018f0000000004530019000000030700036700005dca0000613d000000000807034f0000000009030019000000008a08043c0000000009a90436000000000049004b00005dc60000c13d000000000006004b00005df10000613d000000000557034f0000000306600210000000000704043300000000076701cf000000000767022f000000000505043b0000010006600089000000000565022f00000000056501cf000000000575019f000000000054043500005df10000013d00001a980010009c00001a9801008041000000400110021000001a980030009c00001a98030080410000006003300210000000000113019f00001a980040009c00001a9804008041000000c003400210000000000131019f000a0000000b001d00070000000c001d6a5a6a500000040f000000070c0000290000000a0b000029000000010220015f0003000000010355000000600110027000011a980010019d00001a9804100197000000000004004b00005dae0000c13d00000060010000390000008003000039000000010020019000005e2b0000c13d0000000001010433000000200010008c00005e020000413d00001b030010009c00005e160000213d000000200010008c00005e160000413d0000000001030433000000000001004b0000000002000039000000010200c039000000000021004b00005e160000c13d000000000001004b00005e4b0000613d000000000001042d00001b0801000041000000000010043f0000003201000039000000040010043f00001b090100004100006a5c0001043000001b0801000041000000000010043f0000004101000039000000040010043f00001b090100004100006a5c0001043000001b0801000041000000000010043f0000002101000039000000040010043f00001b090100004100006a5c00010430000000000001042f000000000100001900006a5c00010430000000400100043d00001b3f02000041000000000021043500001a980010009c00001a9801008041000000400110021000001aca011001c700006a5c0001043000001b69010000410000000000120435000000090100002900001a9b011001970000000403200039000000000013043500001a980020009c00001a9802008041000000400120021000001b09011001c700006a5c00010430000000400100043d00000084021000390000000803000029000000000032043500000044021000390000000000c2043500000024021000390000000000b2043500001b7c020000410000000000210435000000090200002900001a9b02200197000000040310003900000000002304350000006402100039000000000002043500001a980010009c00001a9801008041000000400110021000001b7d011001c700006a5c0001043000001b3a0100004100000000001b0435000000040100002900000000001304350000000501000029000000000014043500001a9800b0009c00001a980b0080410000004001b0021000001b2a011001c700006a5c00010430000000400100043d00000064021000390000000803000029000000000032043500000044021000390000000000c2043500000024021000390000000000b2043500001b7a020000410000000000210435000000090200002900001a9b022001970000000403100039000000000023043500001a980010009c00001a9801008041000000400110021000001b7b011001c700006a5c000104300000001f0530018f00001a9a06300198000000400200043d000000000462001900005e690000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00005e650000c13d000000000005004b00005e760000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f0000000000140435000000600130021000001a980020009c00001a98020080410000004002200210000000000112019f00006a5c0001043000001b0801000041000000000010043f0000001101000039000000040010043f00001b090100004100006a5c00010430001d000000000002000100000006001d001500000005001d000200000004001d001c00000003001d000a00000002001d000600000001001d0000000012010434000500000001001d00001b250020009c000068fa0000813d00000005012002100000003f0310003900001b0203300197000000400400043d0000000003340019000400000004001d000000000043004b0000000004000039000000010400403900001ac20030009c000068fa0000213d0000000100400190000068fa0000c13d000000400030043f00000004030000290000000002230436000300000002001d0000001f0210018f000000000001004b00005ea90000613d0000000304000029000000000114001900000000030000310000000203300367000000003503043c0000000004540436000000000014004b00005ea50000c13d000000000002004b000000400100043d001300000001001d00001a9c0010009c000068fa0000213d00000013020000290000004001200039000000400010043f000000200e200039000000600100003900000000001e043500000000000204350000001c010000290000000021010434001b00000002001d000000000001004b00120000000e001d00005f6f0000613d000000000200001900005ecd0000013d0000006001700039000000000501043300000080017000390000000003010433000000000108043300001a9b0110019700001a9b0330019700000013070000296a5a541c0000040f000000120e0000290000001d0200002900000001022000390000001c010000290000000001010433000000000012004b00005f6f0000813d001d00000002001d00000005012002100000001b01100029000000000501043300000000370504340000000081070434000000060010008c000069000000813d000000000001004b00005ef40000c13d001600000005001d001700000003001d001800000008001d001900000007001d00000060017000390000000001010433001a00000001001d00001b6201000041000000000010044300000000010004100000000400100443000000000100041400001a980010009c00001a9801008041000000c00110021000001b1b011001c70000800a020000396a5a6a550000040f0000000100200190000069150000613d000000000101043b0000001a0010006b000069720000213d00000019070000290000000001070433000000120e000029000000180800002900000017030000290000001605000029000000050010008c000069000000213d00000040027000390000000004020433000000000001004b00005f0c0000613d00000040025000390000000006020433000000000203043300001a9b02200197000000010010008c00005f210000613d000000020010008c00005ebd0000613d0000006001700039000000000501043300000080017000390000000003010433000000000108043300001a9b0110019700001a9b0330019700000013070000296a5a51eb0000040f00005ec60000013d000000000108043300001a9b0110019700000000004101a00000691b0000c13d00000060017000390000000003010433000000000003004b000069180000613d0000008001700039000000000101043300001a9b041001970000000001000414000000040040008c001a00000003001d001900000004001d00005f2e0000c13d00000001010000310000000102000039000000000001004b00005f3d0000c13d00005f640000013d000000000004004b0000691b0000c13d0000006001700039000000000401043300000080017000390000000003010433000000000108043300001a9b0110019700001a9b03300197000000000506001900000013060000296a5a5c060000040f00005ec60000013d00001a980010009c00001a9801008041000000c00110021000001ac1011001c7000080090200003900000000050000196a5a6a500000040f000000120e000029000000010220018f0003000000010355000000600110027000011a980010019d00001a9801100197000000000001004b00005f640000613d00001ac20010009c000068fa0000213d0000001f0310003900001b1f033001970000003f0330003900001b1f04300197000000400300043d0000000004430019000000000034004b0000000005000039000000010500403900001ac20040009c000068fa0000213d0000000100500190000068fa0000c13d000000400040043f000000000613043600001b1f041001980000000003460019000000030500036700005f570000613d000000000705034f000000007807043c0000000006860436000000000036004b00005f530000c13d0000001f0110019000005f640000613d000000000445034f0000000301100210000000000503043300000000051501cf000000000515022f000000000404043b0000010001100089000000000414022f00000000011401cf000000000151019f0000000000130435000000000002004b00005ec70000c13d000000400100043d00000024021000390000001a03000029000000000032043500001b34020000410000000000210435000000040210003900000019030000290000692b0000013d0000000a010000290000000021010434000900000002001d000000000001004b000065b20000613d000000150100002900171a9b0010019b000000000200001900005f7e0000013d0000000d0200002900000001022000390000000a010000290000000001010433000000000012004b000065b20000813d000d00000002001d0000000501200210000000090210002900000000030204330000008002300039000000000202043300001b130020019800005f780000613d000b00000003001d000000040200002900000000020204330000000d0020006c000068f40000a13d000000030210002900000001030000390000000000320435000000060200002900000000020204330000000d0020006c000068f40000a13d000000050110002900000000010104330000000001010433001000000001001d000000400110003900000000010104330000000001010433001500000001001d000000000001004b0000000b02000029001800200020003d001b00a00020003d0000657f0000613d0000001001000029000f01200010003d000000000500001900005faa0000013d0000001d050000290000001a030000290000001c0100002900000000003104350000000105500039000000150050006c0000657f0000813d000000180100002900000000010104330000000002010433001d00000005001d000000000052004b000068f40000a13d0000001b02000029000000000302043300000000020304330000001d0020006c000068f40000a13d0000001d050000290000000502500210000000200420003900000000011400190000000002010433000000600620003900000000013400190000000003010433001c00000006001d0000000001060433000000000001004b00005fa50000613d001a00000003001d000000400100043d00001aa80010009c000068fa0000213d000000a003100039000000400030043f0000008003100039000000000003043500000060031000390000000000030435000000400310003900000000000304350000002003100039000000000003043500000000000104350000000041020434000000050010008c000069000000213d000000400600043d00001aa80060009c000068fa0000213d0000001c05000029000000000305043300000040022000390000000007020433000000000204043300001a9b05200197000000a002600039000000400020043f0000008002600039000000170400002900000000004204350000006002600039000000000032043500000040026000390000000000720435000000200260003900000000005204350000000000160435000000000001004b001600000003001d0000613a0000613d0000000f02000029000000000f0204330000001002000029000000000202043300141a9b0020019b000000010010008c001900000005001d000060960000613d000000020010008c001100000007001d000061460000c13d000000130100002900000000020104330000000000f2004b000062680000613d00000000010e04330000000001010433000000000001004b000062680000613d000800000002001d000e0000000f001d000000400100043d000c00000001001d000000200210003900001b3501000041000700000002001d000000000012043500001b040100004100000000001004430000000001000412000000040010044300000120010000390000002400100443000000000100041400001a980010009c00001a9801008041000000c00110021000001b05011001c700008005020000396a5a6a550000040f0000000100200190000069150000613d000000000101043b0000000c04000029000000600240003900000008030000290000000000320435000000400240003900001a9b01100197000000000012043500001b040100004100000000001004430000000001000412000000040010044300000160010000390000002400100443000000000100041400001a980010009c00001a9801008041000000c00110021000001b05011001c700008005020000396a5a6a550000040f0000000100200190000069150000613d000000000101043b0000000c04000029000000a00240003900001b3603000041000000000032043500000080024000390000000000120435000000a001000039000000000014043500001ac80040009c000068fa0000213d0000000c02000029000000c001200039000000400010043f000000070100002900001a980010009c00001a98010080410000004001100210000000000202043300001a980020009c00001a98020080410000006002200210000000000112019f000000000200041400001a980020009c00001a9802008041000000c002200210000000000112019f00001ac1011001c700008010020000396a5a6a550000040f0000000100200190000069160000613d000000000101043b00001b3702000041000000000020044300001a9b01100197000c00000001001d0000000400100443000000000100041400001a980010009c00001a9801008041000000c00110021000001b1b011001c700008002020000396a5a6a550000040f0000000100200190000069150000613d000000400a00043d0000002404a000390000000403a00039000000000101043b000000000001004b000069370000613d000000120e00002900000000020e043300001b380100004100000000001a043500000020010000390000000000130435000000000302043300000000003404350000004401a00039000000000003004b0000608d0000613d0000000004000019000000200220003900000000050204330000000067050434000000040070008c000069000000813d0000000007710436000000000606043300001a9b0660019700000000006704350000004006500039000000000606043300001a9b06600197000000400710003900000000006704350000006006500039000000000606043300001a9b06600197000000600710003900000000006704350000008006500039000000000606043300000080071000390000000000670435000000a0055000390000000005050433000000a0061000390000000000560435000000c0011000390000000104400039000000000034004b0000606e0000413d00000000040004140000000c02000029000000040020008c000062230000c13d0000000103000031000000200030008c00000020040000390000000004034019000062540000013d000000000007004b0000691b0000c13d000000000003004b000069180000613d000000130100002900000000020104330000000000f2004b0000647c0000613d00000000010e04330000000001010433000000000001004b0000647c0000613d000c00000002001d000e0000000f001d000000400100043d001100000001001d000000200210003900001b3501000041000800000002001d000000000012043500001b040100004100000000001004430000000001000412000000040010044300000120010000390000002400100443000000000100041400001a980010009c00001a9801008041000000c00110021000001b05011001c700008005020000396a5a6a550000040f0000000100200190000069150000613d000000000101043b000000110400002900000060024000390000000c030000290000000000320435000000400240003900001a9b01100197000000000012043500001b040100004100000000001004430000000001000412000000040010044300000160010000390000002400100443000000000100041400001a980010009c00001a9801008041000000c00110021000001b05011001c700008005020000396a5a6a550000040f0000000100200190000069150000613d000000000101043b0000001104000029000000a00240003900001b3603000041000000000032043500000080024000390000000000120435000000a001000039000000000014043500001ac80040009c000068fa0000213d0000001102000029000000c001200039000000400010043f000000080100002900001a980010009c00001a98010080410000004001100210000000000202043300001a980020009c00001a98020080410000006002200210000000000112019f000000000200041400001a980020009c00001a9802008041000000c002200210000000000112019f00001ac1011001c700008010020000396a5a6a550000040f0000000100200190000069160000613d000000000101043b00001b3702000041000000000020044300001a9b01100197001100000001001d0000000400100443000000000100041400001a980010009c00001a9801008041000000c00110021000001b1b011001c700008002020000396a5a6a550000040f0000000100200190000069150000613d000000400a00043d0000002404a000390000000403a00039000000000101043b000000000001004b000069670000613d000000120e00002900000000020e043300001b380100004100000000001a043500000020010000390000000000130435000000000302043300000000003404350000004401a00039000000000003004b000061310000613d0000000004000019000000200220003900000000050204330000000067050434000000040070008c000069000000813d0000000007710436000000000606043300001a9b0660019700000000006704350000004006500039000000000606043300001a9b06600197000000400710003900000000006704350000006006500039000000000606043300001a9b06600197000000600710003900000000006704350000008006500039000000000606043300000080071000390000000000670435000000a0055000390000000005050433000000a0061000390000000000560435000000c0011000390000000104400039000000000034004b000061120000413d00000000040004140000001102000029000000040020008c000064370000c13d0000000103000031000000200030008c00000020040000390000000004034019000064680000013d00000000007501a00000691b0000c13d000000000003004b000069180000613d0000000001000414000000040040008c000061e80000c13d00000001010000310000000102000039000000000001004b000061f70000c13d0000621e0000013d000000000003004b000069180000613d000000130100002900000000020104330000000000f2004b0000636c0000613d00000000010e04330000000001010433000000000001004b0000636c0000613d000800000002001d000e0000000f001d000000400100043d000c00000001001d000000200210003900001b3501000041000700000002001d000000000012043500001b040100004100000000001004430000000001000412000000040010044300000120010000390000002400100443000000000100041400001a980010009c00001a9801008041000000c00110021000001b05011001c700008005020000396a5a6a550000040f0000000100200190000069150000613d000000000101043b0000000c04000029000000600240003900000008030000290000000000320435000000400240003900001a9b01100197000000000012043500001b040100004100000000001004430000000001000412000000040010044300000160010000390000002400100443000000000100041400001a980010009c00001a9801008041000000c00110021000001b05011001c700008005020000396a5a6a550000040f0000000100200190000069150000613d000000000101043b0000000c04000029000000a00240003900001b3603000041000000000032043500000080024000390000000000120435000000a001000039000000000014043500001ac80040009c000068fa0000213d0000000c02000029000000c001200039000000400010043f000000070100002900001a980010009c00001a98010080410000004001100210000000000202043300001a980020009c00001a98020080410000006002200210000000000112019f000000000200041400001a980020009c00001a9802008041000000c002200210000000000112019f00001ac1011001c700008010020000396a5a6a550000040f0000000100200190000069160000613d000000000101043b00001b3702000041000000000020044300001a9b01100197000c00000001001d0000000400100443000000000100041400001a980010009c00001a9801008041000000c00110021000001b1b011001c700008002020000396a5a6a550000040f0000000100200190000069150000613d000000400a00043d0000002404a000390000000403a00039000000000101043b000000000001004b000069370000613d000000120e00002900000000020e043300001b380100004100000000001a043500000020010000390000000000130435000000000302043300000000003404350000004401a00039000000000003004b000061df0000613d0000000004000019000000200220003900000000050204330000000067050434000000040070008c000069000000813d0000000007710436000000000606043300001a9b0660019700000000006704350000004006500039000000000606043300001a9b06600197000000400710003900000000006704350000006006500039000000000606043300001a9b06600197000000600710003900000000006704350000008006500039000000000606043300000080071000390000000000670435000000a0055000390000000005050433000000a0061000390000000000560435000000c0011000390000000104400039000000000034004b000061c00000413d00000000040004140000000c02000029000000040020008c000063270000c13d0000000103000031000000200030008c00000020040000390000000004034019000063580000013d00001a980010009c00001a9801008041000000c00110021000001ac1011001c7000080090200003900000000050000196a5a6a500000040f000000120e000029000000010220018f0003000000010355000000600110027000011a980010019d00001a9801100197000000000001004b0000621e0000613d00001ac20010009c000068fa0000213d0000001f0310003900001b1f033001970000003f0330003900001b1f04300197000000400300043d0000000004430019000000000034004b0000000005000039000000010500403900001ac20040009c000068fa0000213d0000000100500190000068fa0000c13d000000400040043f000000000613043600001b1f0410019800000000034600190000000305000367000062110000613d000000000705034f000000007807043c0000000006860436000000000036004b0000620d0000c13d0000001f011001900000621e0000613d000000000445034f0000000301100210000000000503043300000000051501cf000000000515022f000000000404043b0000010001100089000000000414022f00000000011401cf000000000151019f0000000000130435000000000002004b0000001d050000290000001a0300002900005fa50000c13d000069230000013d0000000001a1004900001a980010009c00001a9801008041000000600110021000001a9800a0009c00001a980300004100000000030a40190000004003300210000000000131019f00001a980040009c00001a9804008041000000c003400210000000000131019f000c0000000a001d6a5a6a500000040f0000000c0a0000290000000003010019000000600330027000001a9803300197000000200030008c00000020040000390000000004034019000000200640019000000000056a0019000062420000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b0000623e0000c13d0000001f074001900000624f0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000100000003001f00030000000103550000000100200190000000120e000029000069a30000613d0000001f01400039000000600210018f0000000001a20019000000000021004b0000000002000039000000010200403900001ac20010009c000068fa0000213d0000000100200190000068fa0000c13d000000400010043f000000200030008c000069160000413d00000000010a043300001b3900100198000069160000c13d000000600100003900000000001e043500000016030000290000000e0f00002900000000000f004b000062e00000613d00000000010e04330000000001010433000000010010003a00006a160000413d000000010310003900001ac20030009c000068fa0000213d00000005043002100000003f0240003900001b0205200197000000400200043d0000000005520019000000000025004b0000000006000039000000010600403900001ac20050009c000068fa0000213d0000000100600190000068fa0000c13d000000400050043f00000000033204360000000005000019000000400600043d00001ac80060009c000068fa0000213d000000c007600039000000400070043f000000a0076000390000000000070435000000800760003900000000000704350000006007600039000000000007043500000040076000390000000000070435000000200760003900000000000704350000000000060435000000000735001900000000006704350000002005500039000000000045004b000062800000413d000000000001004b000062ca0000613d000000000400001900000000060e04330000000005060433000000000045004b000068f40000a13d00000005054002100000000006650019000000200660003900000000080604330000000097080434000000030070008c000069000000213d000000400600043d00001ac80060009c000068fa0000213d0000000009090433000000400a800039000000000a0a0433000000600b800039000000000b0b0433000000800c800039000000000c0c0433000000a0088000390000000008080433000000c00d6000390000004000d0043f000000a00d60003900000000008d043500000080086000390000000000c8043500001a9b08b00197000000600b60003900000000008b043500001a9b08a00197000000400a60003900000000008a043500001a9b089001970000002009600039000000000089043500000000007604350000000007020433000000000047004b000068f40000a13d000000000535001900000000006504350000000005020433000000000045004b000068f40000a13d0000000104400039000000000014004b000062980000413d000000400400043d00001ac80040009c000068fa0000213d000000c005400039000000400050043f000000a005400039000000160600002900000000006504350000008005400039000000110600002900000000006504350000006005400039000000170600002900000000006504350000004005400039000000140600002900000000006504350000002005400039000000190600002900000000006504350000000205000039000063e30000013d000000010030008c0000693d0000c13d00001b3701000041000000000010044300000019010000290000000400100443000000000100041400001a980010009c00001a9801008041000000c00110021000001b1b011001c700008002020000396a5a6a550000040f0000000100200190000069150000613d000000000101043b000000000001004b000069310000613d00001b3701000041000000000010044300000019010000290000000400100443000000000100041400001a980010009c00001a9801008041000000c00110021000001b1b011001c700008002020000396a5a6a550000040f0000000100200190000069150000613d000000000101043b000000000001004b000000120e0000290000001704000029000069160000613d000000400500043d0000004401500039000000110200002900000000002104350000002401500039000000000041043500001b6b01000041000000000015043500000004015000390000001402000029000000000021043500000000010004140000001902000029000000040020008c000064330000613d00001a980050009c00001a98030000410000000003054019000000400330021000001a980010009c00001a9801008041000000c001100210000000000131019f00001b6c011001c7001900000005001d6a5a6a500000040f0000001905000029000000120e0000290000000003010019000000600330027000011a980030019d00030000000103550000000100200190000064330000c13d000069750000013d0000000001a1004900001a980010009c00001a9801008041000000600110021000001a9800a0009c00001a980300004100000000030a40190000004003300210000000000131019f00001a980040009c00001a9804008041000000c003400210000000000131019f000c0000000a001d6a5a6a500000040f0000000c0a0000290000000003010019000000600330027000001a9803300197000000200030008c00000020040000390000000004034019000000200640019000000000056a0019000063460000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b000063420000c13d0000001f07400190000063530000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000100000003001f00030000000103550000000100200190000000120e000029000069af0000613d0000001f01400039000000600210018f0000000001a20019000000000021004b0000000002000039000000010200403900001ac20010009c000068fa0000213d0000000100200190000068fa0000c13d000000400010043f000000200030008c000069160000413d00000000010a043300001b3900100198000069160000c13d000000600100003900000000001e043500000019050000290000000e0f00002900000000000f004b000063e80000613d00000000010e04330000000001010433000000010010003a00006a160000413d000000010310003900001ac20030009c000068fa0000213d00000005043002100000003f0240003900001b0205200197000000400200043d0000000005520019000000000025004b0000000006000039000000010600403900001ac20050009c000068fa0000213d0000000100600190000068fa0000c13d000000400050043f00000000033204360000000005000019000000400600043d00001ac80060009c000068fa0000213d000000c007600039000000400070043f000000a0076000390000000000070435000000800760003900000000000704350000006007600039000000000007043500000040076000390000000000070435000000200760003900000000000704350000000000060435000000000735001900000000006704350000002005500039000000000045004b000063840000413d000000000001004b000063ce0000613d000000000400001900000000060e04330000000005060433000000000045004b000068f40000a13d00000005054002100000000006650019000000200660003900000000080604330000000097080434000000030070008c000069000000213d000000400600043d00001ac80060009c000068fa0000213d0000000009090433000000400a800039000000000a0a0433000000600b800039000000000b0b0433000000800c800039000000000c0c0433000000a0088000390000000008080433000000c00d6000390000004000d0043f000000a00d60003900000000008d043500000080086000390000000000c8043500001a9b08b00197000000600b60003900000000008b043500001a9b08a00197000000400a60003900000000008a043500001a9b089001970000002009600039000000000089043500000000007604350000000007020433000000000047004b000068f40000a13d000000000535001900000000006504350000000005020433000000000045004b000068f40000a13d0000000104400039000000000014004b0000639c0000413d000000400400043d00001ac80040009c000068fa0000213d000000c005400039000000400050043f000000a00540003900000016060000290000000000650435000000800540003900000011060000290000000000650435000000600540003900000017060000290000000000650435000000400540003900000014060000290000000000650435000000200540003900000019060000290000000000650435000000030500003900000000005404350000000005020433000000000015004b000064f60000213d000068f40000013d00001b370100004100000000001004430000000400500443000000000100041400001a980010009c00001a9801008041000000c00110021000001b1b011001c700008002020000396a5a6a550000040f0000000100200190000069150000613d000000000101043b000000000001004b000069310000613d00001b3701000041000000000010044300000019010000290000000400100443000000000100041400001a980010009c00001a9801008041000000c00110021000001b1b011001c700008002020000396a5a6a550000040f0000000100200190000069150000613d000000000101043b000000000001004b000000120e0000290000001704000029000069160000613d000000400500043d0000008401500039000000a00200003900000000002104350000006401500039000000160200002900000000002104350000004401500039000000110200002900000000002104350000002401500039000000000041043500001b67010000410000000000150435000000040150003900000014020000290000000000210435000000a401500039000000000001043500000000010004140000001902000029000000040020008c000064330000613d00001a980050009c00001a98030000410000000003054019000000400330021000001a980010009c00001a9801008041000000c001100210000000000131019f00001b68011001c7001900000005001d6a5a6a500000040f0000001905000029000000120e0000290000000003010019000000600330027000011a980030019d00030000000103550000000100200190000069820000613d00001ac20050009c000068fa0000213d000000400050043f00005fa30000013d0000000001a1004900001a980010009c00001a9801008041000000600110021000001a9800a0009c00001a980300004100000000030a40190000004003300210000000000131019f00001a980040009c00001a9804008041000000c003400210000000000131019f00110000000a001d6a5a6a500000040f000000110a0000290000000003010019000000600330027000001a9803300197000000200030008c00000020040000390000000004034019000000200640019000000000056a0019000064560000613d000000000701034f00000000080a0019000000007907043c0000000008980436000000000058004b000064520000c13d0000001f07400190000064630000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000100000003001f00030000000103550000000100200190000000120e000029000069bb0000613d0000001f01400039000000600210018f0000000001a20019000000000021004b0000000002000039000000010200403900001ac20010009c000068fa0000213d0000000100200190000068fa0000c13d000000400010043f000000200030008c000069160000413d00000000010a043300001b3900100198000069160000c13d000000600100003900000000001e043500000019050000290000000e0f00002900000000000f004b000065000000613d00000000010e04330000000001010433000000010010003a00006a160000413d000000010310003900001ac20030009c000068fa0000213d00000005043002100000003f0240003900001b0205200197000000400200043d0000000005520019000000000025004b0000000006000039000000010600403900001ac20050009c000068fa0000213d0000000100600190000068fa0000c13d000000400050043f00000000033204360000000005000019000000400600043d00001ac80060009c000068fa0000213d000000c007600039000000400070043f000000a0076000390000000000070435000000800760003900000000000704350000006007600039000000000007043500000040076000390000000000070435000000200760003900000000000704350000000000060435000000000735001900000000006704350000002005500039000000000045004b000064940000413d000000000001004b000064de0000613d000000000400001900000000060e04330000000005060433000000000045004b000068f40000a13d00000005054002100000000006650019000000200660003900000000080604330000000097080434000000030070008c000069000000213d000000400600043d00001ac80060009c000068fa0000213d0000000009090433000000400a800039000000000a0a0433000000600b800039000000000b0b0433000000800c800039000000000c0c0433000000a0088000390000000008080433000000c00d6000390000004000d0043f000000a00d60003900000000008d043500000080086000390000000000c8043500001a9b08b00197000000600b60003900000000008b043500001a9b08a00197000000400a60003900000000008a043500001a9b089001970000002009600039000000000089043500000000007604350000000007020433000000000047004b000068f40000a13d000000000535001900000000006504350000000005020433000000000045004b000068f40000a13d0000000104400039000000000014004b000064ac0000413d000000400400043d00001ac80040009c000068fa0000213d000000c005400039000000400050043f000000a0054000390000001606000029000000000065043500000060054000390000001706000029000000000065043500000040054000390000001406000029000000000065043500000020054000390000001906000029000000000065043500000001050000390000000000540435000000800540003900000000000504350000000005020433000000000015004b000068f40000a13d0000000505100210000000000353001900000000004304350000000003020433000000000013004b000068f40000a13d00000000002e043500000013010000290000000000f1043500005fa30000013d00001b370100004100000000001004430000000400500443000000000100041400001a980010009c00001a9801008041000000c00110021000001b1b011001c700008002020000396a5a6a550000040f0000000100200190000069150000613d000000400200043d000000000101043b000000000001004b000069470000613d000000640120003900000016030000290000000000310435000000440120003900000017030000290000000000310435000000200120003900001b6b0300004100000000003104350000002403200039000000140400002900000000004304350000006403000039000000000032043500001aa80020009c000000120e000029000068fa0000213d000000a003200039000000400030043f000000000302043300000000040004140000001902000029000000040020008c0000652b0000c13d000000010400003100000000020000190000653d0000013d00001a980010009c00001a9801008041000000400110021000001a980030009c00001a98030080410000006003300210000000000113019f00001a980040009c00001a9804008041000000c003400210000000000131019f6a5a6a500000040f000000120e000029000000010220015f0003000000010355000000600110027000011a980010019d00001a9804100197000000000004004b00000080010000390000006003000039000065690000613d00001ac20040009c000068fa0000213d0000001f0140003900001b1f011001970000003f0110003900001b1f01100197000000400300043d0000000001130019000000000031004b0000000005000039000000010500403900001ac20010009c000068fa0000213d0000000100500190000068fa0000c13d000000400010043f000000000143043600001b1f06400198000000000561001900000003070003670000655c0000613d000000000807034f0000000009010019000000008a08043c0000000009a90436000000000059004b000065580000c13d0000001f04400190000065690000613d000000000667034f0000000304400210000000000705043300000000074701cf000000000747022f000000000606043b0000010004400089000000000646022f00000000044601cf000000000474019f00000000004504350000000100200190000069510000c13d0000000002030433000000200020008c0000001d050000290000001a0300002900005fa50000413d00001b030020009c000069160000213d000000200020008c000069160000413d0000000001010433000000000001004b0000000002000039000000010200c039000000000021004b000069160000c13d000000000001004b0000001d050000290000001a0300002900005fa50000c13d0000698f0000013d0000000b04000029000000400140003900000000010104330000000023010434000000000003004b0000659a0000613d000000c004400039000000000300001900000005053002100000000006520019000000000606043300000060066000390000000007060433000000000007004b000069060000c13d00000000070404330000000008070433000000000038004b000068f40000a13d000000000575001900000020055000390000000005050433000000000056043500000001033000390000000005010433000000000053004b000065870000413d000000180100002900000000010104330000000002010433000000000002004b00005f780000613d00000000020000190000001b0300002900000000030304330000000004030433000000000024004b000068f40000a13d0000000504200210000000200440003900000000033400190000000003030433000000000414001900000000040404330000006004400039000000000034043500000001022000390000000003010433000000000032004b000065a00000413d00005f780000013d00000000010e04330000000001010433000000000001004b000066930000613d00000013010000290000000001010433001c00000001001d000000400100043d001d00000001001d000000200210003900001b3501000041001b00000002001d000000000012043500001b040100004100000000001004430000000001000412000000040010044300000120010000390000002400100443000000000100041400001a980010009c00001a9801008041000000c00110021000001b05011001c700008005020000396a5a6a550000040f0000000100200190000069150000613d000000000101043b0000001d0400002900000060024000390000001c030000290000000000320435000000400240003900001a9b01100197000000000012043500001b040100004100000000001004430000000001000412000000040010044300000160010000390000002400100443000000000100041400001a980010009c00001a9801008041000000c00110021000001b05011001c700008005020000396a5a6a550000040f0000000100200190000069150000613d000000000101043b0000001d04000029000000a00240003900001b3603000041000000000032043500000080024000390000000000120435000000a001000039000000000014043500001ac80040009c000068fa0000213d0000001d02000029000000c001200039000000400010043f0000001b0100002900001a980010009c00001a98010080410000004001100210000000000202043300001a980020009c00001a98020080410000006002200210000000000112019f000000000200041400001a980020009c00001a9802008041000000c002200210000000000112019f00001ac1011001c700008010020000396a5a6a550000040f0000000100200190000069160000613d000000000101043b00001b3702000041000000000020044300001a9b01100197001d00000001001d0000000400100443000000000100041400001a980010009c00001a9801008041000000c00110021000001b1b011001c700008002020000396a5a6a550000040f0000000100200190000069150000613d000000400b00043d0000002404b000390000000403b00039000000000101043b000000000001004b000069f60000613d0000001208000029000000000208043300001b380100004100000000001b043500000020010000390000000000130435000000000302043300000000003404350000004401b00039000000000003004b000066460000613d0000000004000019000000200220003900000000050204330000000067050434000000040070008c000069000000813d0000000007710436000000000606043300001a9b0660019700000000006704350000004006500039000000000606043300001a9b06600197000000400710003900000000006704350000006006500039000000000606043300001a9b06600197000000600710003900000000006704350000008006500039000000000606043300000080071000390000000000670435000000a0055000390000000005050433000000a0061000390000000000560435000000c0011000390000000104400039000000000034004b000066270000413d00000000040004140000001d02000029000000040020008c0000664f0000c13d0000000103000031000000200030008c00000020040000390000000004034019000066810000013d0000000001b1004900001a980010009c00001a9801008041000000600110021000001a9800b0009c00001a980300004100000000030b40190000004003300210000000000131019f00001a980040009c00001a9804008041000000c003400210000000000131019f001d0000000b001d6a5a6a500000040f0000001d0b0000290000000003010019000000600330027000001a9803300197000000200030008c000000200400003900000000040340190000001f0640018f000000200740019000000000057b00190000666f0000613d000000000801034f00000000090b0019000000008a08043c0000000009a90436000000000059004b0000666b0000c13d000000000006004b0000667c0000613d000000000771034f0000000306600210000000000805043300000000086801cf000000000868022f000000000707043b0000010006600089000000000767022f00000000066701cf000000000686019f0000000000650435000100000003001f00030000000103550000000100200190000000120800002900006a0a0000613d0000001f01400039000000600210018f0000000001b20019000000000021004b0000000002000039000000010200403900001ac20010009c000068fa0000213d0000000100200190000068fa0000c13d000000400010043f000000200030008c000069160000413d00000000010b043300001b3900100198000069160000c13d0000006001000039000000000018043500001b6201000041000000000010044300000000010004100000000400100443000000000100041400001a980010009c00001a9801008041000000c00110021000001b1b011001c70000800a020000396a5a6a550000040f0000000100200190000069150000613d000000000101043b000000000001004b000000000f000411000066f90000613d00001b6201000041000000000010044300000000010004100000000400100443000000000100041400001a980010009c00001a9801008041000000c00110021000001b1b011001c70000800a020000396a5a6a550000040f0000000100200190000069150000613d000000000301043b000000000003004b000000000f000411000069180000613d000000000100041400001a9b04f00197000000040040008c001d00000003001d001c00000004001d000066c00000c13d00000001020000390000000101000031000000000001004b000066cf0000c13d000066f70000013d00001a980010009c00001a9801008041000000c00110021000001ac1011001c7000080090200003900000000050000196a5a6a500000040f000000000f000411000000010220018f0003000000010355000000600110027000011a980010019d00001a9801100197000000000001004b000066f70000613d00001ac20010009c000068fa0000213d0000001f0310003900001b1f033001970000003f0330003900001b1f04300197000000400300043d0000000004430019000000000034004b0000000005000039000000010500403900001ac20040009c000068fa0000213d0000000100500190000068fa0000c13d000000400040043f000000000613043600001b1f031001980000001f0410018f00000000013600190000000305000367000066ea0000613d000000000705034f000000007807043c0000000006860436000000000016004b000066e60000c13d000000000004004b000066f70000613d000000000335034f0000000304400210000000000501043300000000054501cf000000000545022f000000000303043b0000010004400089000000000343022f00000000034301cf000000000353019f0000000000310435000000000002004b00006a010000613d000000010000006b000068f20000613d0000000a010000290000000001010433000000000001004b000068f20000613d0000000201000029001b00200010003d0000000007000019000067080000013d00000001077000390000000a010000290000000001010433000000000017004b000068f20000813d0000000502700210000000090120002900000000040104330000008001400039000000000101043300001b1300100198000067030000613d00000006010000290000000001010433000000000071004b000068f40000a13d00000002010000290000000001010433000000000071004b000068f40000a13d001d00000007001d00000005012000290000000005010433000000000105043300000080031000390000000007030433000000040070008c000069000000213d0000001b02200029000000000c02043300001b6502700197000000006304043400001a9b03300197000000020020008c000067e10000c13d0000002002100039000000000202043300001a9b0220019700000000002f004b0000001d07000029000067030000613d000000400900043d00001b3b0090009c000068fa0000213d000000e007100039000000000707043300000080055000390000004004400039000000000a060433000000000b0404330000000008050433000000a0041000390000000006040433000000c00110003900000000050104330000014001900039000000400010043f0000012001900039000000000071043500000100049000390000000000540435000000e0059000390000000000650435000000c00690003900000002070000290000000000760435000000a007900039000000000087043500000080089000390000000000b80435000000600b9000390000000000ab0435000000400a90003900000000003a043500000020039000390000000000f30435001c0000000c001d0000000000c90435000000400e00043d00001b3c0c0000410000000000ce0435000000040ce00039000000200d0000390000000000dc04350000000009090433000000240ce0003900000000009c0435000000000303043300001a9b033001970000004409e00039000000000039043500000000030a043300001a9b033001970000006409e00039000000000039043500000000090b04330000008403e00039000001400a0000390000000000a304350000016403e00039000000000a0904330000000000a30435001a0000000e001d0000018403e0003900000000000a004b000067830000613d000000000b0000190000002009900039000000000c09043300000000de0c04340000000500e0008c000069000000213d000000000ee30436000000000d0d043300001a9b0dd001970000000000de0435000000400dc00039000000000d0d0433000000400e3000390000000000de0435000000600cc00039000000000c0c0433000000600d3000390000000000cd04350000008003300039000000010bb000390000000000ab004b0000676e0000413d0000001a0a0000290000000009a30049000000240990008a0000000008080433000000a40aa0003900000000009a043500000000090804330000000003930436000000000009004b000067a80000613d000000000a0000190000002008800039000000000b08043300000000cd0b04340000000500d0008c000069000000213d000000000dd30436000000000c0c043300001a9b0cc001970000000000cd0435000000400cb00039000000000c0c0433000000400d3000390000000000cd0435000000600cb00039000000000c0c0433000000600d3000390000000000cd0435000000800bb00039000000000b0b043300001a9b0bb00197000000800c3000390000000000bc0435000000a003300039000000010aa0003900000000009a004b0000678e0000413d0000001a0c0000290000000008c30049000000240880008a0000000007070433000000c409c00039000000000089043500000000870704340000000003730436000000000007004b000067ba0000613d0000000009000019000000000a390019000000000b980019000000000b0b04330000000000ba04350000002009900039000000000079004b000067b30000413d000000000873001900000000000804350000001f0770003900001b1f0770019700000000037300190000000007c30049000000240770008a0000000006060433000000e408c00039000000000078043500000000070604330000000003730436000000000007004b000067cf0000613d00000000080000190000002006600039000000000906043300000000039304360000000108800039000000000078004b000067c90000413d00000000050504330000010406c00039000000000056043500000000040404330000012405c0003900000000004504350000014404c00039000000000101043300000000001404350000000001000414000000040020008c000068a80000c13d0000000103000031000000200030008c000000200400003900000000040340190000001c05000029000068d90000013d000000040070008c0000001d07000029000067030000c13d001c0000000c001d00000080015000390000000001010433000000400240003900000000020204330000000005060433000000400b00043d00001b630400004100000000004b04350000000404b00039000000a0060000390000000000640435000000a404b0003900000000060504330000000000640435000000c404b00039000000000006004b0000680c0000613d000000000700001900000020055000390000000008050433000000009a0804340000000500a0008c000069000000213d000000000aa40436000000000909043300001a9b0990019700000000009a043500000040098000390000000009090433000000400a40003900000000009a0435000000600880003900000000080804330000006009400039000000000089043500000080044000390000000107700039000000000067004b000067f70000413d0000000005b40049000000040550008a0000002406b00039000000000056043500000000050204330000000004540436000000000005004b0000682f0000613d0000000006000019000000200220003900000000070204330000000089070434000000050090008c000069000000213d0000000009940436000000000808043300001a9b088001970000000000890435000000400870003900000000080804330000004009400039000000000089043500000060087000390000000008080433000000600940003900000000008904350000008007700039000000000707043300001a9b0770019700000080084000390000000000780435000000a0044000390000000106600039000000000056004b000068150000413d0000000002b40049000000040220008a0000004405b00039000000000025043500000000520104340000000001240436000000000002004b0000683f0000613d000000000400001900000000061400190000000007450019000000000707043300000000007604350000002004400039000000000024004b000068380000413d000000000421001900000000000404350000001f0220003900001b1f0220019700000000012100190000000002b10049000000040220008a0000006404b000390000000000240435000000020500002900000000020504330000000001210436000000000002004b0000001c08000029000068550000613d00000000040000190000002005500039000000000605043300000000016104360000000104400039000000000024004b0000684f0000413d00001b64028001970000008404b0003900000000002404350000000002000414000000040030008c000068600000c13d0000000103000031000000200030008c00000020040000390000000004034019000068930000013d0000000001b1004900001a980010009c00001a9801008041000000600110021000001a9800b0009c00001a980400004100000000040b40190000004004400210000000000141019f00001a980020009c00001a9802008041000000c002200210000000000121019f0000000002030019001a0000000b001d6a5a6a500000040f0000001a0b0000290000000003010019000000600330027000001a9803300197000000200030008c00000020040000390000000004034019000000200640019000000000056b0019000068800000613d000000000701034f00000000080b0019000000007907043c0000000008980436000000000058004b0000687c0000c13d0000001f074001900000688d0000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000100000003001f00030000000103550000000100200190000000000f0004110000001c08000029000069de0000613d0000001f01400039000000600210018f0000000001b20019000000000021004b0000000002000039000000010200403900001ac20010009c000068fa0000213d0000000100200190000068fa0000c13d000000400010043f000000200030008c000069160000413d00000000020b043300001b3900200198000069160000c13d00001b3d0220019700001b630020009c0000001d07000029000067030000613d000069d90000013d0000000003c3004900001a980030009c00001a9803008041000000600330021000001a9800c0009c00001a980400004100000000040c40190000004004400210000000000343019f00001a980010009c00001a9801008041000000c001100210000000000131019f6a5a6a500000040f0000001a0c0000290000000003010019000000600330027000001a9803300197000000200030008c00000020040000390000000004034019000000200640019000000000056c0019000068c60000613d000000000701034f00000000080c0019000000007907043c0000000008980436000000000058004b000068c20000c13d0000001f07400190000068d30000613d000000000661034f0000000307700210000000000805043300000000087801cf000000000878022f000000000606043b0000010007700089000000000676022f00000000067601cf000000000686019f0000000000650435000100000003001f00030000000103550000000100200190000000000f0004110000001c05000029000069ea0000613d0000001f01400039000000600210018f0000000001c20019000000000021004b0000000002000039000000010200403900001ac20010009c000068fa0000213d0000000100200190000068fa0000c13d000000400010043f000000200030008c000069160000413d00000000020c043300001b3900200198000069160000c13d00001b3d0220019700001b3c0020009c0000001d07000029000067030000613d00001b3e02000041000000000021043500000004021000390000000000520435000069420000013d0000000401000029000000000001042d00001b0801000041000000000010043f0000003201000039000000040010043f00001b090100004100006a5c0001043000001b0801000041000000000010043f0000004101000039000000040010043f00001b090100004100006a5c0001043000001b0801000041000000000010043f0000002101000039000000040010043f00001b090100004100006a5c00010430000000400100043d000000440210003900000000007204350000002402100039000000000032043500001b7e02000041000000000021043500000004021000390000000d03000029000000000032043500001a980010009c00001a9801008041000000400110021000001b6c011001c700006a5c00010430000000000001042f000000000100001900006a5c00010430000000400100043d00001b3f020000410000691d0000013d000000400100043d00001b4102000041000000000021043500001a980010009c00001a9801008041000000400110021000001aca011001c700006a5c00010430000000400100043d00000024021000390000001603000029000000000032043500001b3402000041000000000021043500000004021000390000001703000029000000000032043500001a980010009c00001a9801008041000000400110021000001b2a011001c700006a5c00010430000000400100043d00001b6902000041000000000021043500000004021000390000001903000029000069410000013d00001b3a0100004100000000001a0435000000080100002900000000001304350000000c010000290000696c0000013d000000400100043d00001b6a0200004100000000002104350000000402100039000000000032043500001a980010009c00001a9801008041000000400110021000001b09011001c700006a5c0001043000001b6901000041000000000012043500000004012000390000001903000029000000000031043500001a980020009c00001a9802008041000000400120021000001b09011001c700006a5c00010430000000400100043d00000084021000390000001603000029000000000032043500000044021000390000001703000029000000000032043500000024021000390000001403000029000000000032043500001b7c0200004100000000002104350000000402100039000000190300002900000000003204350000006402100039000000000002043500001a980010009c00001a9801008041000000400110021000001b7d011001c700006a5c0001043000001b3a0100004100000000001a04350000000c0100002900000000001304350000001101000029000000000014043500001a9800a0009c00001a980a0080410000004001a0021000001b2a011001c700006a5c00010430000000400100043d00001b40020000410000691d0000013d00001a98033001970000001f0530018f00001a9a06300198000000400200043d0000000004620019000069c60000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b0000697d0000c13d000069c60000013d00001a98033001970000001f0530018f00001a9a06300198000000400200043d0000000004620019000069c60000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b0000698a0000c13d000069c60000013d000000400100043d00000064021000390000001603000029000000000032043500000044021000390000001703000029000000000032043500000024021000390000001403000029000000000032043500001b7a02000041000000000021043500000004021000390000001903000029000000000032043500001a980010009c00001a9801008041000000400110021000001b7b011001c700006a5c000104300000001f0530018f00001a9a06300198000000400200043d0000000004620019000069c60000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000069aa0000c13d000069c60000013d0000001f0530018f00001a9a06300198000000400200043d0000000004620019000069c60000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000069b60000c13d000069c60000013d0000001f0530018f00001a9a06300198000000400200043d0000000004620019000069c60000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000069c20000c13d000000000005004b000069d30000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f0000000000140435000000600130021000001a980020009c00001a98020080410000004002200210000000000112019f00006a5c0001043000001b5102000041000000000021043500000004021000390000000000820435000069420000013d0000001f0530018f00001a9a06300198000000400200043d0000000004620019000069c60000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000069e50000c13d000069c60000013d0000001f0530018f00001a9a06300198000000400200043d0000000004620019000069c60000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000069f10000c13d000069c60000013d00001b3a0100004100000000001b04350000001c0100002900000000001304350000001d01000029000000000014043500001a9800b0009c00001a980b0080410000004001b0021000001b2a011001c700006a5c00010430000000400100043d00000024021000390000001d03000029000000000032043500001b3402000041000000000021043500000004021000390000001c030000290000692b0000013d0000001f0530018f00001a9a06300198000000400200043d0000000004620019000069c60000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b00006a110000c13d000069c60000013d00001b0801000041000000000010043f0000001101000039000000040010043f00001b090100004100006a5c00010430000000000001042f00001a980010009c00001a9801008041000000400110021000001a980020009c00001a98020080410000006002200210000000000112019f000000000200041400001a980020009c00001a9802008041000000c002200210000000000112019f00001ac1011001c700008010020000396a5a6a550000040f000000010020019000006a300000613d000000000101043b000000000001042d000000000100001900006a5c0001043000000000050100190000000000200443000000050030008c00006a400000413d000000040100003900000000020000190000000506200210000000000664001900000005066002700000000006060031000000000161043a0000000102200039000000000031004b00006a380000413d00001a980030009c00001a98030080410000006001300210000000000200041400001a980020009c00001a9802008041000000c002200210000000000112019f00001b7f011001c700000000020500196a5a6a550000040f000000010020019000006a4f0000613d000000000101043b000000000001042d000000000001042f00006a53002104210000000102000039000000000001042d0000000002000019000000000001042d00006a58002104230000000102000039000000000001042d0000000002000019000000000001042d00006a5a0000043200006a5b0001042e00006a5c0001043000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffff00000000000000000000000000000000000000000000000000000001ffffffe000000000000000000000000000000000000000000000000000000000ffffffe0000000000000000000000000ffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000ffffffffffffffbf536561706f7274000000000000000000000000000000000000000000000000000200000000000000000000000000000000000007000000000000000000000000312e35000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000030000000000000000000000004f666665724974656d280000000000000000000000000000000000000000000075696e7438206974656d547970652c00000000000000000000000000000000006164647265737320746f6b656e2c00000000000000000000000000000000000075696e74323536206964656e7469666965724f7243726974657269612c00000075696e74323536207374617274416d6f756e742c00000000000000000000000075696e7432353620656e64416d6f756e740000000000000000000000000000002900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffff5f436f6e73696465726174696f6e4974656d28000000000000000000000000000075696e7432353620656e64416d6f756e742c00000000000000000000000000006164647265737320726563697069656e74000000000000000000000000000000000000000000000000000000000000000000000000000000fffffffffffffe9f6e2c00000000000000000000000000000000000000000000000000000000000075696e7438206f72646572547970652c0000000000000000000000000000000075696e7432353620737461727454696d652c000000000000000000000000000075696e7432353620656e6454696d652c0000000000000000000000000000000062797465733332207a6f6e65486173682c0000000000000000000000000000004f72646572436f6d706f6e656e7473280000000000000000000000000000000061646472657373206f6666657265722c0000000000000000000000000000000075696e743235362073616c742c0000000000000000000000000000000000000061646472657373207a6f6e652c000000000000000000000000000000000000006279746573333220636f6e647569744b65792c000000000000000000000000004f666665724974656d5b5d206f666665722c000000000000000000000000000075696e7432353620636f756e7465720000000000000000000000000000000000436f6e73696465726174696f6e4974656d5b5d20636f6e73696465726174696f000000000000000000000000000000000000000000000000fffffffffffffd9f454950373132446f6d61696e2800000000000000000000000000000000000000737472696e67206e616d652c0000000000000000000000000000000000000000737472696e672076657273696f6e2c000000000000000000000000000000000075696e7432353620636861696e49642c000000000000000000000000000000006164647265737320766572696679696e67436f6e747261637400000000000000000000000000000000000000000000000000000000000000fffffffffffffd1f0200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff325d5b325d5b325d5b325d5b325d20747265652900000000000000000000000042756c6b4f72646572284f72646572436f6d706f6e656e74735b325d5b325d5b000000000000000000000000000000000000000000000000ffffffffffffff9f9a8a0592ac89c5ad3bc6df8224c17b485976f597df104ee20d0df415241f670b0200000200000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffff3f0a96ad390000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000003ca2711d29384747a8f61d60aad3c450405f7aaff5613541dee28df2d6986d32ada5013122d395ba3c54772283fb069b10426056ef8ca54750cb9bb552a59e7dbf8e29b89f29ed9b529c154a63038ffca562f8d7cd1e2545dda53a1b582dde30abbb5caa7dda850e60932de0934eb1f9d0f59695050f761dc64e443e5030a56953c6f6856e13104584dd0797ca2b2779202dc2597c6066a42e0d8fe990b0024d101e368776582e57ab3d116ffe2517c0a585cd5b23174b01e275c2d8329c3d83a02eb7ff164c884e5e2c336dc85f81c6a93329d8e9adf214b32729b894de2af139c9d33c18e050dda0aeb9a8086fb16fc12d5d64536780e1da7405a800b0b9f61c19f71958cdd8f081b4c31f7caf5c010b29d12950be2fa1c95070dc47e30b55ca74fab2fece9a1d58234a274220ad05ca096a92ef6a1ca1750b9d90c948955c7ff98d9d4e55d876c5cfac10b43c04039522f3ddfb0ea9bfe70c68cfb5c7cc14bed7be92d41c56f9e59ac7a6272185299b815ddfabc3f25deb51fe55fe2f9e8ad1d97d1ef5eaa37a4ee5fbf234e6f6d64eb511eb562221cd7edfbdde0848da05896c3f349c4da741c19b37fec49ed2e44d738e775a21d9c9860a69d67a3dae53bb98d87cc12922b83759626c5f07d72266da9702d19ffad6a514c73a89002f5fe6ae19322608dd1f8a8d56aab48ed9c28be489b689f4b6c91268563efc85f20e6b5b04cbae4fcb1a9d78e7b2dfc51a36933d023cf6e347e03d517b472a852590d1eb68309202b7106b891e109739dbbd334a1817fe5d6202c939e75cf5e35ca91da3eed3ecef6ebaa6e5023c057ec2c75150693fd0dac5c90f4a142f9879fde8eee9a1392aa395c7002308119a58f2582777a75e54e0c1d5d5437bd2e8bf6222c3939feff011e53ab8c35ca3370aad54c5df1fc2938cd62543174fa6e7d858770efca7572ac20f5ae84db0e2940674f7eca0a4726fa1060ffc2d18cef54b203d5a4f867d3d458dabecad65f6201ceeaba0096df2d0c491cc32e6ea4e6435001780987079d291feebf21c2230e69add0f283cee0b8be492ca8050b4185a2ff7193bd8cff538aba49a9c374c806d277181e9651624b3e31111bc0624574f8bca1d5d6a3f098a0bc373f808c619b1bb4028208721b3c4f8d6bc8a874d659814eb761d51df90cba8de7637ca3e8fe1e3511d1dc2f23487d05dbdecb781860c21ac1c54cdd369e4e8a8515e52ca72ec816c2101831ad1f18bf44102ed171459c9b4f80000000200000000000000000000000000000340000001000000000000000000a61be9f0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024000003a0000000000000000000000000000000000000000000000000000000000000000000000000a900866a00000000000000000000000000000000000000000000000000000000f07ec37200000000000000000000000000000000000000000000000000000000f47b773f00000000000000000000000000000000000000000000000000000000f47b774000000000000000000000000000000000000000000000000000000000fb0f3ee100000000000000000000000000000000000000000000000000000000fd9f1e1000000000000000000000000000000000000000000000000000000000f07ec37300000000000000000000000000000000000000000000000000000000f2d12b1200000000000000000000000000000000000000000000000000000000e7acab2300000000000000000000000000000000000000000000000000000000e7acab2400000000000000000000000000000000000000000000000000000000ed98a57400000000000000000000000000000000000000000000000000000000a900866b00000000000000000000000000000000000000000000000000000000b3a34c4c0000000000000000000000000000000000000000000000000000000079df72bc0000000000000000000000000000000000000000000000000000000088147731000000000000000000000000000000000000000000000000000000008814773200000000000000000000000000000000000000000000000000000000a81744040000000000000000000000000000000000000000000000000000000079df72bd0000000000000000000000000000000000000000000000000000000087201b410000000000000000000000000000000000000000000000000000000046423aa60000000000000000000000000000000000000000000000000000000046423aa7000000000000000000000000000000000000000000000000000000005b34b9660000000000000000000000000000000000000000000000000000000006fdde0380000000000000000000000000000000000000000000000000000000000000007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff310ab089e4439a4c15d089f94afb7896ff553aecb10793d0ab882de59d99a32e0200000200000000000000000000000000000044000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffff1f000000000000000000000000000000000000000000000000fffffffffffffeff4e487b71000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000024000000000000000000000000000000000000000000000000000000000000000000000000fffffffffffffe5f0200000000000000000000000000000000000040000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000002000000000000000000000000000000000000200000000000000000000000006bacc01dbe442496068f7d234edd811f1a5f833243e0aec824f86ab861f3c90dfed398fc0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020000003a000000000000000001a515574000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffff10fda3e1000000000000000000000000000000000000000000000000000000002165628a00000000000000000000000000000000000000000000000000000000f280791efe782edcf06ce15c8f4dff17601db3b88eb3805a0db7d77faf757f047fa8a987000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000003a0000000000000000042cbb15ccdc3cad6266b0e7a08c0454b23bf29dc2df74b6f3c209e9336465bd180b41246c05cbb406f874e82aa2faf7db11bba9792fe09929e56ef1eee2c2da30200000200000000000000000000000000000024000000000000000000000000721c20121297512b72821b97f5326877ea8ecf4bb9948fea5bfcb6453074d37f0000000000000000000000000000000000000080000003a000000000000000000000000000000000000000000000000000000000000003e00000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff60ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff40ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000fffffffffffffea0000000000000000000000000000000000000000000000000ffffffffffffffe00000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000ffffffffffffff60000000000000000000000000000000000000000000000000fffffffffffffdff796b89b91644bc98cd93958e4c9038275d622183e25ac5af08cc6b5d9553913221ccfeb700000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004400000000000000000000000003fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7000000000000000000000000000000000000000000000000ffffffffffffff20000000000000000000000000000000000000000000000000fffffffffffffffe000000000000000000000000000000000000000000000000ffffffffffffff7f000000000000000000000000000000000000000000000000ffffffffffffffdf9d9af8e38d66c62e2c12f0225249fd9d721c54b83f48d9352c97c6cacdcb6f31000000000000000000000000000000ffffffffffffffffffffffffffffff0000ee9e0e63000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000010001bc806b96000000000000000000000000000000000000000000000000000000002020dba91b30cc0006188af794c2fb30dd8520db7e2c088b7fc7c103c00ca494c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4701806aa1896bbf26568e884a7374b41e002500962caba6a15023a8d90e8508b834ce34aa20000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff1cf99b2600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fffffffffffffebf17b1f94200000000000000000000000000000000000000000000000000000000ffffffff00000000000000000000000000000000000000000000000000000000fb5014fc0000000000000000000000000000000000000000000000000000000091b3e514000000000000000000000000000000000000000000000000000000008ffff980000000000000000000000000000000000000000000000000000000006ab37ce700000000000000000000000000000000000000000000000000000000466aa6160000000000000000000000000000000000000000000000000000000039f3e3fd00000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1a817440400000000000000000000000000000000000000000000000000000000f2d12b120000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000a11b63ff000000000000000000000000000000000000000000000000000000005a052b32000000000000000000000000000000000000000000000000000000009891976500000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffff7b01000057c7e3d549b557d47463addb42966a21423069bb51a0824f0799fc573f9c4d535bdea7cd8a978f128b93471df48c7dbab89d703809115bdc118c235bfd0200000000000000000000000000000000000084000000000000000000000000e5c5e9a3000000000000000000000000000000000000000000000000000000009397928500000000000000000000000000000000000000000000000000000000c63cf0890000000000000000000000000000000000000000000000000000000012d3f5a300000000000000000000000000000000000000000000000000000000133c37c6000000000000000000000000000000000000000000000000000000006088d7de00000000000000000000000000000000000000000000000000000000bfb3f8ce0000000000000000000000000000000000000000000000000000000009bde3390000000000000000000000000000000000000000000000000000000094eb6af600000000000000000000000000000000000000000000000000000000d692933200000000000000000000000000000000000000000000000000000000a8930e9a000000000000000000000000000000000000000000000000000000007fda727900000000000000000000000000000000000000000000000000000000375c24c100000000000000000000000000000000000000000000000000000000d5da9a1b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffff4b9f2d36e1b4c93de62cc077b00b1a91d84b6c31b4a14e012718dcca230689e7bced929d0000000000000000000000000000000000000000000000000000000098e9db6e000000000000000000000000000000000000000000000000000000009cc7f708afc65944829bd487b90b72536b1951864fbfc14e125fc972a6507f39f4dd92ce000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe000000000000000000000000000000000000000000000000ffffffffffffff40f242432a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c40000000000000000000000005f15d6720000000000000000000000000000000000000000000000000000000069f958270000000000000000000000000000000000000000000000000000000023b872dd000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000064000000000000000000000000190100000000000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ff000000000000000000000000000000000000000000000000001fffffffffffffffff1626ba7e000000000000000000000000000000000000000000000000000000004f7fb80d000000000000000000000000000000000000000000000000000000001f003d0a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000815e1d64000000000000000000000000000000000000000000000000000000008baa579f00000000000000000000000000000000000000000000000000000000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd1efffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd98891923000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000084000000000000000000000000f486bc870000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000a4000000000000000000000000a5f54208000000000000000000000000000000000000000000000000000000000200000200000000000000000000000000000000000000000000000000000000fb63bbcaffaecf783de5ef8b903dd9d4cf4061a10144168e083336936ea32b3c
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000001972ddfa941670a9f5fa2a0094f4490347b99d7b
-----Decoded View---------------
Arg [0] : conduitController (address): 0x1972ddFa941670A9F5fa2A0094f4490347B99D7B
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 0000000000000000000000001972ddfa941670a9f5fa2a0094f4490347b99d7b
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$22.02
Net Worth in ETH
0.007501
Token Allocations
ETH
100.00%
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|---|---|---|---|---|
| ETH | 100.00% | $2,935.64 | 0.0075 | $22.02 |
Loading...
Loading
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.