Source Code
Overview
ETH Balance
51.16 ETH
Token Holdings
More Info
ContractCreator
Multi Chain
Multichain Addresses
1 address found via
Latest 25 from a total of 199 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
Value | ||||
---|---|---|---|---|---|---|---|---|---|
Execute Native M... | 8896189 | 153 days 20 hrs ago | IN | 0 ETH | 0.01240799 | ||||
Execute Native M... | 8851074 | 161 days 23 hrs ago | IN | 0 ETH | 0.11405998 | ||||
Execute Native M... | 8850989 | 161 days 23 hrs ago | IN | 0 ETH | 0.20932512 | ||||
Execute Native M... | 8771720 | 176 days 5 hrs ago | IN | 0 ETH | 0.1259396 | ||||
Execute Native M... | 8771645 | 176 days 5 hrs ago | IN | 0 ETH | 0.03430896 | ||||
Execute Native M... | 8771627 | 176 days 5 hrs ago | IN | 0 ETH | 0.0371197 | ||||
Execute Native M... | 8771599 | 176 days 5 hrs ago | IN | 0 ETH | 0.13594129 | ||||
Execute Native M... | 8771575 | 176 days 6 hrs ago | IN | 0 ETH | 0.11666037 | ||||
Execute Native M... | 8771548 | 176 days 6 hrs ago | IN | 0 ETH | 0.02953308 | ||||
Execute Native M... | 8771472 | 176 days 6 hrs ago | IN | 0 ETH | 0.1572729 | ||||
Execute Native M... | 8771435 | 176 days 6 hrs ago | IN | 0 ETH | 0.02195547 | ||||
Execute Native M... | 8771385 | 176 days 6 hrs ago | IN | 0 ETH | 0.02832214 | ||||
Execute Native M... | 8771363 | 176 days 6 hrs ago | IN | 0 ETH | 0.02273453 | ||||
Execute Native M... | 8771300 | 176 days 7 hrs ago | IN | 0 ETH | 0.01884018 | ||||
Execute Native M... | 8771293 | 176 days 7 hrs ago | IN | 0 ETH | 0.0221264 | ||||
Execute Native M... | 8771289 | 176 days 7 hrs ago | IN | 0 ETH | 0.03687752 | ||||
Execute Native M... | 8771273 | 176 days 7 hrs ago | IN | 0 ETH | 0.03686973 | ||||
Execute Native M... | 8771254 | 176 days 7 hrs ago | IN | 0 ETH | 0.02268736 | ||||
Execute Native M... | 8771243 | 176 days 7 hrs ago | IN | 0 ETH | 0.02473723 | ||||
Execute Native M... | 8771232 | 176 days 7 hrs ago | IN | 0 ETH | 0.04627047 | ||||
Execute Native M... | 8767181 | 177 days 18 mins ago | IN | 0 ETH | 0.05018232 | ||||
Execute Native M... | 8767174 | 177 days 20 mins ago | IN | 0 ETH | 0.15383741 | ||||
Execute Native M... | 8767133 | 177 days 31 mins ago | IN | 0 ETH | 0.13186773 | ||||
Execute Native M... | 8767119 | 177 days 34 mins ago | IN | 0 ETH | 0.05716288 | ||||
Execute Native M... | 8767109 | 177 days 37 mins ago | IN | 0 ETH | 0.05414207 |
Latest 25 internal transactions (View All)
Advanced mode:
Parent Txn Hash | Block | From | To | Value | ||
---|---|---|---|---|---|---|
8896189 | 153 days 20 hrs ago | 0 ETH | ||||
8896189 | 153 days 20 hrs ago | 0 ETH | ||||
8896189 | 153 days 20 hrs ago | 0 ETH | ||||
8896189 | 153 days 20 hrs ago | 0 ETH | ||||
8896189 | 153 days 20 hrs ago | 0 ETH | ||||
8896189 | 153 days 20 hrs ago | 0 ETH | ||||
8851074 | 161 days 23 hrs ago | 0 ETH | ||||
8851074 | 161 days 23 hrs ago | 0 ETH | ||||
8851074 | 161 days 23 hrs ago | 0 ETH | ||||
8851074 | 161 days 23 hrs ago | 0 ETH | ||||
8850989 | 161 days 23 hrs ago | 0 ETH | ||||
8850989 | 161 days 23 hrs ago | 0 ETH | ||||
8850989 | 161 days 23 hrs ago | 0 ETH | ||||
8850989 | 161 days 23 hrs ago | 0 ETH | ||||
8850989 | 161 days 23 hrs ago | 0 ETH | ||||
8850989 | 161 days 23 hrs ago | 0 ETH | ||||
8850989 | 161 days 23 hrs ago | 0 ETH | ||||
8771720 | 176 days 5 hrs ago | 0 ETH | ||||
8771720 | 176 days 5 hrs ago | 0 ETH | ||||
8771720 | 176 days 5 hrs ago | 0 ETH | ||||
8771720 | 176 days 5 hrs ago | 0 ETH | ||||
8771720 | 176 days 5 hrs ago | 0 ETH | ||||
8771720 | 176 days 5 hrs ago | 0 ETH | ||||
8771720 | 176 days 5 hrs ago | 0 ETH | ||||
8771645 | 176 days 5 hrs ago | 0 ETH |
Loading...
Loading
Contract Name:
FlowMatchExecutor
Compiler Version
v0.8.14+commit.80d49f37
Optimization Enabled:
Yes with 99999999 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity 0.8.14; import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; import { Pausable } from "@openzeppelin/contracts/security/Pausable.sol"; import { IERC165 } from "@openzeppelin/contracts/interfaces/IERC165.sol"; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import { IERC721 } from "@openzeppelin/contracts/token/ERC721/IERC721.sol"; import { IERC1271 } from "@openzeppelin/contracts/interfaces/IERC1271.sol"; import { IERC721Receiver } from "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol"; import { FlowMatchExecutorTypes } from "../libs/FlowMatchExecutorTypes.sol"; import { OrderTypes } from "../libs/OrderTypes.sol"; import { SignatureChecker } from "../libs/SignatureChecker.sol"; import { IFlowExchange } from "../interfaces/IFlowExchange.sol"; /** @title FlowMatchExecutor @author Joe @notice The contract that is called to execute order matches */ contract FlowMatchExecutor is IERC1271, IERC721Receiver, Ownable, Pausable, SignatureChecker { /*////////////////////////////////////////////////////////////// ADDRESSES //////////////////////////////////////////////////////////////*/ IFlowExchange public immutable exchange; IERC20 public immutable weth; /*////////////////////////////////////////////////////////////// EVENTS //////////////////////////////////////////////////////////////*/ event InitiatorChanged(address indexed oldVal, address indexed newVal); ///@notice admin events event ETHWithdrawn(address indexed destination, uint256 amount); event ERC20Withdrawn( address indexed destination, address indexed currency, uint256 amount ); address public initiator; /*////////////////////////////////////////////////////////////// MODIFIERS //////////////////////////////////////////////////////////////*/ modifier netNonNegative() { uint256 initialBalance = address(this).balance + weth.balanceOf(address(this)); _; uint256 finalBalance = address(this).balance + weth.balanceOf(address(this)); require( finalBalance >= initialBalance, "Transaction not non-negative" ); } modifier onlyInitiator() { require(msg.sender == initiator, "only initiator can call"); _; } /*////////////////////////////////////////////////////////////// CONSTRUCTOR //////////////////////////////////////////////////////////////*/ constructor(IFlowExchange _exchange, address _initiator, address _weth) { exchange = _exchange; initiator = _initiator; weth = IERC20(_weth); } // solhint-disable-next-line no-empty-blocks receive() external payable {} ///////////////////////////////////////////////// OVERRIDES /////////////////////////////////////////////////////// // returns the magic value if the message is signed by the owner of this contract, invalid value otherwise function isValidSignature( bytes32 message, bytes calldata signature ) external view override returns (bytes4) { _assertValidSignatureHelper(initiator, message, signature); return 0x1626ba7e; // EIP-1271 magic value } function onERC721Received( address, address, uint256, bytes calldata ) external pure override returns (bytes4) { return this.onERC721Received.selector; } ///////////////////////////////////////////////// EXTERNAL FUNCTIONS /////////////////////////////////////////////////////// /** * @notice The entry point for executing brokerage matches. Callable only by owner * @param batches The batches of calls to make */ function executeBrokerMatches( FlowMatchExecutorTypes.Batch[] calldata batches ) external whenNotPaused onlyInitiator netNonNegative { uint256 numBatches = batches.length; for (uint256 i; i < numBatches; ) { _broker(batches[i].externalFulfillments); _matchOrders(batches[i].matches); unchecked { ++i; } } } /** * @notice The entry point for executing native matches. Callable only by owner * @param matches The matches to make */ function executeNativeMatches( FlowMatchExecutorTypes.MatchOrders[] calldata matches ) external whenNotPaused onlyInitiator netNonNegative { _matchOrders(matches); } //////////////////////////////////////////////////// INTERNAL FUNCTIONS /////////////////////////////////////////////////////// /** * @notice broker a trade by fulfilling orders on other exchanges and transferring nfts to the intermediary * @param externalFulfillments The specification of the external calls to make and nfts to transfer */ function _broker( FlowMatchExecutorTypes.ExternalFulfillments calldata externalFulfillments ) internal { uint256 numCalls = externalFulfillments.calls.length; if (numCalls > 0) { for (uint256 i; i < numCalls; ) { _call(externalFulfillments.calls[i]); unchecked { ++i; } } } uint256 numNftsToTransfer = externalFulfillments.nftsToTransfer.length; if (numNftsToTransfer > 0) { for (uint256 i; i < numNftsToTransfer; ) { bool isApproved = IERC721( externalFulfillments.nftsToTransfer[i].collection ).isApprovedForAll(address(this), address(exchange)); if (!isApproved) { IERC721(externalFulfillments.nftsToTransfer[i].collection) .setApprovalForAll(address(exchange), true); } unchecked { ++i; } } } } /** * @notice Execute a call to the specified contract * @param params The call to execute */ function _call( FlowMatchExecutorTypes.Call memory params ) internal returns (bytes memory) { (bool _success, bytes memory _result) = params.to.call{ value: params.value }(params.data); require(_success, "external call failed"); return _result; } /** * @notice Function called to execute a batch of matches by calling the exchange contract * @param matches The batch of matches to execute on the exchange */ function _matchOrders( FlowMatchExecutorTypes.MatchOrders[] calldata matches ) internal { uint256 numMatches = matches.length; if (numMatches > 0) { for (uint256 i; i < numMatches; ) { FlowMatchExecutorTypes.MatchOrdersType matchType = matches[i] .matchType; if ( matchType == FlowMatchExecutorTypes.MatchOrdersType.OneToOneSpecific ) { exchange.matchOneToOneOrders( matches[i].buys, matches[i].sells ); } else if ( matchType == FlowMatchExecutorTypes.MatchOrdersType.OneToOneUnspecific ) { exchange.matchOrders( matches[i].sells, matches[i].buys, matches[i].constructs ); } else if ( matchType == FlowMatchExecutorTypes.MatchOrdersType.OneToMany ) { if (matches[i].buys.length == 1) { exchange.matchOneToManyOrders( matches[i].buys[0], matches[i].sells ); } else if (matches[i].sells.length == 1) { exchange.matchOneToManyOrders( matches[i].sells[0], matches[i].buys ); } else { revert("invalid one to many order"); } } else { revert("invalid match type"); } unchecked { ++i; } } } } //////////////////////////////////////////////////// ADMIN FUNCTIONS /////////////////////////////////////////////////////// function withdrawETH(address destination) external onlyOwner { uint256 amount = address(this).balance; (bool sent, ) = destination.call{ value: amount }(""); require(sent, "failed"); emit ETHWithdrawn(destination, amount); } /// @dev Used for withdrawing exchange fees paid to the contract in ERC20 tokens function withdrawTokens( address destination, address currency, uint256 amount ) external onlyOwner { IERC20(currency).transfer(destination, amount); emit ERC20Withdrawn(destination, currency, amount); } function updateInitiator(address _initiator) external onlyOwner { address oldVal = initiator; initiator = _initiator; emit InitiatorChanged(oldVal, _initiator); } /** * @notice Pause the contract */ function pause() external onlyOwner { _pause(); } /** * @notice Unpause the contract */ function unpause() external onlyOwner { _unpause(); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor() { _transferOwnership(_msgSender()); } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(owner() == _msgSender(), "Ownable: caller is not the owner"); _; } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (interfaces/IERC1271.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC1271 standard signature validation method for * contracts as defined in https://eips.ethereum.org/EIPS/eip-1271[ERC-1271]. * * _Available since v4.1._ */ interface IERC1271 { /** * @dev Should return whether the signature provided is valid for the provided data * @param hash Hash of the data to be signed * @param signature Signature byte array associated with _data */ function isValidSignature(bytes32 hash, bytes memory signature) external view returns (bytes4 magicValue); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (interfaces/IERC165.sol) pragma solidity ^0.8.0; import "../utils/introspection/IERC165.sol";
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (security/Pausable.sol) pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which allows children to implement an emergency stop * mechanism that can be triggered by an authorized account. * * This module is used through inheritance. It will make available the * modifiers `whenNotPaused` and `whenPaused`, which can be applied to * the functions of your contract. Note that they will not be pausable by * simply including this module, only once the modifiers are put in place. */ abstract contract Pausable is Context { /** * @dev Emitted when the pause is triggered by `account`. */ event Paused(address account); /** * @dev Emitted when the pause is lifted by `account`. */ event Unpaused(address account); bool private _paused; /** * @dev Initializes the contract in unpaused state. */ constructor() { _paused = false; } /** * @dev Returns true if the contract is paused, and false otherwise. */ function paused() public view virtual returns (bool) { return _paused; } /** * @dev Modifier to make a function callable only when the contract is not paused. * * Requirements: * * - The contract must not be paused. */ modifier whenNotPaused() { require(!paused(), "Pausable: paused"); _; } /** * @dev Modifier to make a function callable only when the contract is paused. * * Requirements: * * - The contract must be paused. */ modifier whenPaused() { require(paused(), "Pausable: not paused"); _; } /** * @dev Triggers stopped state. * * Requirements: * * - The contract must not be paused. */ function _pause() internal virtual whenNotPaused { _paused = true; emit Paused(_msgSender()); } /** * @dev Returns to normal state. * * Requirements: * * - The contract must be paused. */ function _unpause() internal virtual whenPaused { _paused = false; emit Unpaused(_msgSender()); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 amount ) external returns (bool); /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC721/IERC721.sol) pragma solidity ^0.8.0; import "../../utils/introspection/IERC165.sol"; /** * @dev Required interface of an ERC721 compliant contract. */ interface IERC721 is IERC165 { /** * @dev Emitted when `tokenId` token is transferred from `from` to `to`. */ event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token. */ event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets. */ event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /** * @dev Returns the number of tokens in ``owner``'s account. */ function balanceOf(address owner) external view returns (uint256 balance); /** * @dev Returns the owner of the `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function ownerOf(uint256 tokenId) external view returns (address owner); /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients * are aware of the ERC721 protocol to prevent tokens from being forever locked. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Transfers `tokenId` token from `from` to `to`. * * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 tokenId ) external; /** * @dev Gives permission to `to` to transfer `tokenId` token to another account. * The approval is cleared when the token is transferred. * * Only a single account can be approved at a time, so approving the zero address clears previous approvals. * * Requirements: * * - The caller must own the token or be an approved operator. * - `tokenId` must exist. * * Emits an {Approval} event. */ function approve(address to, uint256 tokenId) external; /** * @dev Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) external view returns (address operator); /** * @dev Approve or remove `operator` as an operator for the caller. * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller. * * Requirements: * * - The `operator` cannot be the caller. * * Emits an {ApprovalForAll} event. */ function setApprovalForAll(address operator, bool _approved) external; /** * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`. * * See {setApprovalForAll} */ function isApprovedForAll(address owner, address operator) external view returns (bool); /** * @dev Safely transfers `tokenId` token from `from` to `to`. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId, bytes calldata data ) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC721/IERC721Receiver.sol) pragma solidity ^0.8.0; /** * @title ERC721 token receiver interface * @dev Interface for any contract that wants to support safeTransfers * from ERC721 asset contracts. */ interface IERC721Receiver { /** * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom} * by `operator` from `from`, this function is called. * * It must return its Solidity selector to confirm the token transfer. * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted. * * The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`. */ function onERC721Received( address operator, address from, uint256 tokenId, bytes calldata data ) external returns (bytes4); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCall(target, data, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value ) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract"); (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { require(isContract(target), "Address: delegate call to non-contract"); (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResult(success, returndata, errorMessage); } /** * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.14; import { OrderTypes } from "../libs/OrderTypes.sol"; /** * @title IFlowExchange * @author Joe * @notice Exchange interface that must be implemented by the Flow Exchange */ interface IFlowExchange { function matchOneToOneOrders( OrderTypes.MakerOrder[] calldata makerOrders1, OrderTypes.MakerOrder[] calldata makerOrders2 ) external; function matchOneToManyOrders( OrderTypes.MakerOrder calldata makerOrder, OrderTypes.MakerOrder[] calldata manyMakerOrders ) external; function matchOrders( OrderTypes.MakerOrder[] calldata sells, OrderTypes.MakerOrder[] calldata buys, OrderTypes.OrderItem[][] calldata constructs ) external; function takeMultipleOneOrders( OrderTypes.MakerOrder[] calldata makerOrders ) external payable; function takeOrders( OrderTypes.MakerOrder[] calldata makerOrders, OrderTypes.OrderItem[][] calldata takerNfts ) external payable; function transferMultipleNFTs( address to, OrderTypes.OrderItem[] calldata items ) external; function cancelAllOrders(uint256 minNonce) external; function cancelMultipleOrders(uint256[] calldata orderNonces) external; function isNonceValid( address user, uint256 nonce ) external view returns (bool); }
// SPDX-License-Identifier: MIT pragma solidity 0.8.14; uint256 constant FreeMemoryPointerSlot = 0x40; uint256 constant OneWord = 0x20; uint256 constant OneWordShift = 0x5; uint256 constant ThirtyOneBytes = 0x1f; bytes32 constant EIP2098_allButHighestBitMask = ( 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff ); uint256 constant ExtraGasBuffer = 0x20; uint256 constant CostPerWord = 0x3; uint256 constant MemoryExpansionCoefficientShift = 0x9; uint256 constant BulkOrder_Typehash_Height_One = ( 0x25f1d312acdce9bb5f11c5585e941709b8456695fe5aacf9998bd3acadfd7fec ); uint256 constant BulkOrder_Typehash_Height_Two = ( 0xb7870d22600c57d01e7ff46f87ea8741898e43ce73f7d5bfb269c715ea8d4242 ); uint256 constant BulkOrder_Typehash_Height_Three = ( 0xe9ccc656222762d6d2e94ef74311f23818493f907cde851440e6d8773f56c5fe ); uint256 constant BulkOrder_Typehash_Height_Four = ( 0x14300c4bb2d1850e661a7bb2347e8ac0fa0736fa434a6d0ae1017cb485ce1a7c ); uint256 constant BulkOrder_Typehash_Height_Five = ( 0xd2a9fdbc6e34ad83660cd4ad49310a663134bbdaea7c34c7c6a95cf9aa8618b1 ); uint256 constant BulkOrder_Typehash_Height_Six = ( 0x4c2c782f8c9daf12d0ec87e76fc496ffeed835292ca7ff04ac92375bbc0f4cc7 ); uint256 constant BulkOrder_Typehash_Height_Seven = ( 0xab5bd2a739337f6f3d8743b51df07f176805bae22da4b25be5d8cdd688498382 ); uint256 constant BulkOrder_Typehash_Height_Eight = ( 0x96596fb6c680230945bae686c1776a9920c438436a98dba61ca767f370b6ef0c ); uint256 constant BulkOrder_Typehash_Height_Nine = ( 0x40d250b9c55bcc275a49429cae143a873752d755dfa1072e47e10d5252fb8d3b ); uint256 constant BulkOrder_Typehash_Height_Ten = ( 0xeaf49b43e05b65ffed9bd664ee39555b22fa8ba157aa058f19fc7fee92d386f4 ); uint256 constant BulkOrder_Typehash_Height_Eleven = ( 0x9d5d1c872408322fe8c431a1b66583d09e5dd77e0ac5f99b55131b3fe8363ffb ); uint256 constant BulkOrder_Typehash_Height_Twelve = ( 0xdb50e721ad63671fc79a925f372d22d69adfe998243b341129c4ef29a20c7a74 ); uint256 constant BulkOrder_Typehash_Height_Thirteen = ( 0x908c5a945faf8d6b1d5aba44fc097fb8c22cca14f60bf75bf680224813809637 ); uint256 constant BulkOrder_Typehash_Height_Fourteen = ( 0x7968127d641eabf208fbdc9d69f10fed718855c94a809679d41b7bcf18104b74 ); uint256 constant BulkOrder_Typehash_Height_Fifteen = ( 0x814b44e912b2ccd234edcf03da0b9d37c459baf9d512034ed96bc93032c37bab ); uint256 constant BulkOrder_Typehash_Height_Sixteen = ( 0x3a8ceb52e9851a307cf6bd49c73a2ec0d37712e6c4d68c4dcf84df0ad574f59a ); uint256 constant BulkOrder_Typehash_Height_Seventeen = ( 0xdd2197b5843051f931afa0a534e25a1d824e11ccb5e100c716e9e40406c68b3a ); uint256 constant BulkOrder_Typehash_Height_Eighteen = ( 0x84b50d02c0d7ec2a815ec27a71290ad861c7cd3addd94f5f7c0736df33fe1827 ); uint256 constant BulkOrder_Typehash_Height_Nineteen = ( 0xdaa31608975cb535532462ce63bbb075b6d81235cd756da2117e745baed067c1 ); uint256 constant BulkOrder_Typehash_Height_Twenty = ( 0x5089f7eef268ce27189a0f19e64dd8210ecadff4be5176a5bd4fd1f176f483a1 ); uint256 constant BulkOrder_Typehash_Height_TwentyOne = ( 0x907e1899005168c54e8279a0e7fc8f890b1de622a79e1ea1447bde837732da56 ); uint256 constant BulkOrder_Typehash_Height_TwentyTwo = ( 0x73ea6321c43a7d88f2d0f797219c7dd3405b1208e89c6d00c6df5c2cc833aa1d ); uint256 constant BulkOrder_Typehash_Height_TwentyThree = ( 0xb2036d7869c41d1588416aba4ce6e52b45a330fd934c05995b14653db5db9293 ); uint256 constant BulkOrder_Typehash_Height_TwentyFour = ( 0x99e8d8ff7ddc6198258cce0fe5930c7fe7799405517eca81dbf14c1707c163ad );
// SPDX-License-Identifier: MIT pragma solidity 0.8.14; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import { OrderTypes } from "./OrderTypes.sol"; /** * @title FlowMatchExecutorTyoes * @author Joe * @notice This library contains the match executor types */ library FlowMatchExecutorTypes { struct Call { bytes data; uint256 value; address payable to; } struct ExternalFulfillments { Call[] calls; OrderTypes.OrderItem[] nftsToTransfer; } enum MatchOrdersType { OneToOneSpecific, OneToOneUnspecific, OneToMany } struct MatchOrders { OrderTypes.MakerOrder[] buys; OrderTypes.MakerOrder[] sells; OrderTypes.OrderItem[][] constructs; MatchOrdersType matchType; } struct Batch { ExternalFulfillments externalFulfillments; MatchOrders[] matches; } }
// SPDX-License-Identifier: MIT // solhint-disable no-inline-assembly pragma solidity 0.8.14; import { CostPerWord, ExtraGasBuffer, FreeMemoryPointerSlot, MemoryExpansionCoefficientShift, OneWord, OneWordShift, ThirtyOneBytes } from "./Constants.sol"; /** * @title LowLevelHelpers * @author 0age * @notice LowLevelHelpers contains logic for performing various low-level * operations. */ contract LowLevelHelpers { /** * @dev Internal view function to revert and pass along the revert reason if * data was returned by the last call and that the size of that data * does not exceed the currently allocated memory size. */ function _revertWithReasonIfOneIsReturned() internal view { assembly { // If it returned a message, bubble it up as long as sufficient gas // remains to do so: if returndatasize() { // Ensure that sufficient gas is available to copy returndata // while expanding memory where necessary. Start by computing // the word size of returndata and allocated memory. let returnDataWords := shr( OneWordShift, add(returndatasize(), ThirtyOneBytes) ) // Note: use the free memory pointer in place of msize() to work // around a Yul warning that prevents accessing msize directly // when the IR pipeline is activated. let msizeWords := shr( OneWordShift, mload(FreeMemoryPointerSlot) ) // Next, compute the cost of the returndatacopy. let cost := mul(CostPerWord, returnDataWords) // Then, compute cost of new memory allocation. if gt(returnDataWords, msizeWords) { cost := add( cost, add( mul(sub(returnDataWords, msizeWords), CostPerWord), shr( MemoryExpansionCoefficientShift, sub( mul(returnDataWords, returnDataWords), mul(msizeWords, msizeWords) ) ) ) ) } // Finally, add a small constant and compare to gas remaining; // bubble up the revert data if enough gas is still available. if lt(add(cost, ExtraGasBuffer), gas()) { // Copy returndata to memory; overwrite existing memory. returndatacopy(0, 0, returndatasize()) // Revert, specifying memory region with copied returndata. revert(0, returndatasize()) } } } } /** * @dev Internal view function to branchlessly select either the caller (if * a supplied recipient is equal to zero) or the supplied recipient (if * that recipient is a nonzero value). * * @param recipient The supplied recipient. * * @return updatedRecipient The updated recipient. */ function _substituteCallerForEmptyRecipient( address recipient ) internal view returns (address updatedRecipient) { // Utilize assembly to perform a branchless operation on the recipient. assembly { // Add caller to recipient if recipient equals 0; otherwise add 0. updatedRecipient := add(recipient, mul(iszero(recipient), caller())) } } /** * @dev Internal pure function to cast a `bool` value to a `uint256` value. * * @param b The `bool` value to cast. * * @return u The `uint256` value. */ function _cast(bool b) internal pure returns (uint256 u) { assembly { u := b } } /** * @dev Internal pure function to compare two addresses without first * masking them. Note that dirty upper bits will cause otherwise equal * addresses to be recognized as unequal. * * @param a The first address. * @param b The second address * * @return areEqual A boolean representing whether the addresses are equal. */ function _unmaskedAddressComparison( address a, address b ) internal pure returns (bool areEqual) { // Utilize assembly to perform the comparison without masking. assembly { areEqual := eq(a, b) } } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.14; /** * @title OrderTypes * @author nneverlander. Twitter @nneverlander * @notice This library contains the order types used by the main exchange and complications */ library OrderTypes { /// @dev the tokenId and numTokens (==1 for ERC721) struct TokenInfo { uint256 tokenId; uint256 numTokens; } /// @dev an order item is a collection address and tokens from that collection struct OrderItem { address collection; TokenInfo[] tokens; } struct MakerOrder { ///@dev is order sell or buy bool isSellOrder; ///@dev signer of the order (maker address) address signer; ///@dev Constraints array contains the order constraints. Total constraints: 7. In order: // numItems - min (for buy orders) / max (for sell orders) number of items in the order // start price in wei // end price in wei // start time in block.timestamp // end time in block.timestamp // nonce of the order // max tx.gasprice in wei that a user is willing to pay for gas // 1 for trustedExecution, 0 or non-existent for not trustedExecution uint256[] constraints; ///@dev nfts array contains order items where each item is a collection and its tokenIds OrderItem[] nfts; ///@dev address of complication for trade execution (e.g. FlowOrderBookComplication), address of the currency (e.g., WETH) address[] execParams; ///@dev additional parameters like traits for trait orders, private sale buyer for OTC orders etc bytes extraParams; ///@dev the order signature uint8 v: parameter (27 or 28), bytes32 r, bytes32 s bytes sig; } }
// SPDX-License-Identifier: MIT // solhint-disable no-inline-assembly pragma solidity 0.8.14; import { Address } from "@openzeppelin/contracts/utils/Address.sol"; import { LowLevelHelpers } from "./LowLevelHelpers.sol"; import { IERC1271 } from "@openzeppelin/contracts/interfaces/IERC1271.sol"; import { OrderTypes } from "../libs/OrderTypes.sol"; import { EIP2098_allButHighestBitMask, OneWord, OneWordShift, BulkOrder_Typehash_Height_One, BulkOrder_Typehash_Height_Two, BulkOrder_Typehash_Height_Three, BulkOrder_Typehash_Height_Four, BulkOrder_Typehash_Height_Five, BulkOrder_Typehash_Height_Six, BulkOrder_Typehash_Height_Seven, BulkOrder_Typehash_Height_Eight, BulkOrder_Typehash_Height_Nine, BulkOrder_Typehash_Height_Ten, BulkOrder_Typehash_Height_Eleven, BulkOrder_Typehash_Height_Twelve, BulkOrder_Typehash_Height_Thirteen, BulkOrder_Typehash_Height_Fourteen, BulkOrder_Typehash_Height_Fifteen, BulkOrder_Typehash_Height_Sixteen, BulkOrder_Typehash_Height_Seventeen, BulkOrder_Typehash_Height_Eighteen, BulkOrder_Typehash_Height_Nineteen, BulkOrder_Typehash_Height_Twenty, BulkOrder_Typehash_Height_TwentyOne, BulkOrder_Typehash_Height_TwentyTwo, BulkOrder_Typehash_Height_TwentyThree, BulkOrder_Typehash_Height_TwentyFour } from "./Constants.sol"; /** * @title SignatureChecker * @notice This contract allows verification of signatures for both EOAs and contracts */ contract SignatureChecker is LowLevelHelpers { /** * @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(); /** * @notice Returns whether the signer matches the signed message * @param orderHash the hash containing the signed message * @param signer the signer address to confirm message validity * @param sig the signature * @param domainSeparator parameter to prevent signature being executed in other chains and environments * @return true --> if valid // false --> if invalid */ function verify( bytes32 orderHash, address signer, bytes calldata sig, bytes32 domainSeparator ) internal view returns (bool) { bytes32 originalDigest = keccak256( abi.encodePacked("\x19\x01", domainSeparator, orderHash) ); bytes32 digest; bytes memory extractedSignature; if (_isValidBulkOrderSize(sig)) { (orderHash, extractedSignature) = _computeBulkOrderProof( sig, orderHash ); digest = keccak256( abi.encodePacked("\x19\x01", domainSeparator, orderHash) ); } else { digest = originalDigest; extractedSignature = sig; } _assertValidSignature( signer, digest, originalDigest, sig, extractedSignature ); return true; } /** * @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 pure 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(_lookupBulkOrderTypehash(height), root) ); // Return the signature. return (bulkOrderHash, signature); } /** * @dev Internal pure function to look up one of twenty-four potential bulk * order typehash constants based on the height of the bulk order tree. * Note that values between one and twenty-four are supported, which is * enforced by _isValidBulkOrderSize. * * @param _treeHeight The height of the bulk order tree. The value must be * between one and twenty-four. * * @return _typeHash The EIP-712 typehash for the bulk order type with the * given height. */ function _lookupBulkOrderTypehash( uint256 _treeHeight ) internal pure returns (bytes32 _typeHash) { // Utilize assembly to efficiently retrieve correct bulk order typehash. assembly { // Use a Yul function to enable use of the `leave` keyword // to stop searching once the appropriate type hash is found. function lookupTypeHash(treeHeight) -> typeHash { // Handle tree heights one through eight. if lt(treeHeight, 9) { // Handle tree heights one through four. if lt(treeHeight, 5) { // Handle tree heights one and two. if lt(treeHeight, 3) { // Utilize branchless logic to determine typehash. typeHash := ternary( eq(treeHeight, 1), BulkOrder_Typehash_Height_One, BulkOrder_Typehash_Height_Two ) // Exit the function once typehash has been located. leave } // Handle height three and four via branchless logic. typeHash := ternary( eq(treeHeight, 3), BulkOrder_Typehash_Height_Three, BulkOrder_Typehash_Height_Four ) // Exit the function once typehash has been located. leave } // Handle tree height five and six. if lt(treeHeight, 7) { // Utilize branchless logic to determine typehash. typeHash := ternary( eq(treeHeight, 5), BulkOrder_Typehash_Height_Five, BulkOrder_Typehash_Height_Six ) // Exit the function once typehash has been located. leave } // Handle height seven and eight via branchless logic. typeHash := ternary( eq(treeHeight, 7), BulkOrder_Typehash_Height_Seven, BulkOrder_Typehash_Height_Eight ) // Exit the function once typehash has been located. leave } // Handle tree height nine through sixteen. if lt(treeHeight, 17) { // Handle tree height nine through twelve. if lt(treeHeight, 13) { // Handle tree height nine and ten. if lt(treeHeight, 11) { // Utilize branchless logic to determine typehash. typeHash := ternary( eq(treeHeight, 9), BulkOrder_Typehash_Height_Nine, BulkOrder_Typehash_Height_Ten ) // Exit the function once typehash has been located. leave } // Handle height eleven and twelve via branchless logic. typeHash := ternary( eq(treeHeight, 11), BulkOrder_Typehash_Height_Eleven, BulkOrder_Typehash_Height_Twelve ) // Exit the function once typehash has been located. leave } // Handle tree height thirteen and fourteen. if lt(treeHeight, 15) { // Utilize branchless logic to determine typehash. typeHash := ternary( eq(treeHeight, 13), BulkOrder_Typehash_Height_Thirteen, BulkOrder_Typehash_Height_Fourteen ) // Exit the function once typehash has been located. leave } // Handle height fifteen and sixteen via branchless logic. typeHash := ternary( eq(treeHeight, 15), BulkOrder_Typehash_Height_Fifteen, BulkOrder_Typehash_Height_Sixteen ) // Exit the function once typehash has been located. leave } // Handle tree height seventeen through twenty. if lt(treeHeight, 21) { // Handle tree height seventeen and eighteen. if lt(treeHeight, 19) { // Utilize branchless logic to determine typehash. typeHash := ternary( eq(treeHeight, 17), BulkOrder_Typehash_Height_Seventeen, BulkOrder_Typehash_Height_Eighteen ) // Exit the function once typehash has been located. leave } // Handle height nineteen and twenty via branchless logic. typeHash := ternary( eq(treeHeight, 19), BulkOrder_Typehash_Height_Nineteen, BulkOrder_Typehash_Height_Twenty ) // Exit the function once typehash has been located. leave } // Handle tree height twenty-one and twenty-two. if lt(treeHeight, 23) { // Utilize branchless logic to determine typehash. typeHash := ternary( eq(treeHeight, 21), BulkOrder_Typehash_Height_TwentyOne, BulkOrder_Typehash_Height_TwentyTwo ) // Exit the function once typehash has been located. leave } // Handle height twenty-three & twenty-four w/ branchless logic. typeHash := ternary( eq(treeHeight, 23), BulkOrder_Typehash_Height_TwentyThree, BulkOrder_Typehash_Height_TwentyFour ) // Exit the function once typehash has been located. leave } // Implement ternary conditional using branchless logic. function ternary(cond, ifTrue, ifFalse) -> c { c := xor(ifFalse, mul(cond, xor(ifFalse, ifTrue))) } // Look up the typehash using the supplied tree height. _typeHash := lookupTypeHash(_treeHeight) } } /** * @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 { if (signer.code.length > 0) { // If signer is a contract, try verification via EIP-1271. if ( IERC1271(signer).isValidSignature( originalDigest, originalSignature ) != 0x1626ba7e ) { revert BadContractSignature(); } // Return early if the ERC-1271 signature check succeeded. return; } else { _assertValidSignatureHelper(signer, digest, signature); } } function _assertValidSignatureHelper( address signer, bytes32 digest, bytes memory signature ) internal pure { // Declare r, s, and v signature parameters. bytes32 r; bytes32 s; uint8 v; 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(); } } }
{ "viaIR": true, "optimizer": { "enabled": true, "runs": 99999999 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
[{"inputs":[{"internalType":"contract IFlowExchange","name":"_exchange","type":"address"},{"internalType":"address","name":"_initiator","type":"address"},{"internalType":"address","name":"_weth","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"BadContractSignature","type":"error"},{"inputs":[{"internalType":"uint8","name":"v","type":"uint8"}],"name":"BadSignatureV","type":"error"},{"inputs":[],"name":"InvalidSignature","type":"error"},{"inputs":[],"name":"InvalidSigner","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"destination","type":"address"},{"indexed":true,"internalType":"address","name":"currency","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ERC20Withdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"destination","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ETHWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldVal","type":"address"},{"indexed":true,"internalType":"address","name":"newVal","type":"address"}],"name":"InitiatorChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[],"name":"exchange","outputs":[{"internalType":"contract IFlowExchange","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"components":[{"components":[{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"address payable","name":"to","type":"address"}],"internalType":"struct FlowMatchExecutorTypes.Call[]","name":"calls","type":"tuple[]"},{"components":[{"internalType":"address","name":"collection","type":"address"},{"components":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"numTokens","type":"uint256"}],"internalType":"struct OrderTypes.TokenInfo[]","name":"tokens","type":"tuple[]"}],"internalType":"struct OrderTypes.OrderItem[]","name":"nftsToTransfer","type":"tuple[]"}],"internalType":"struct FlowMatchExecutorTypes.ExternalFulfillments","name":"externalFulfillments","type":"tuple"},{"components":[{"components":[{"internalType":"bool","name":"isSellOrder","type":"bool"},{"internalType":"address","name":"signer","type":"address"},{"internalType":"uint256[]","name":"constraints","type":"uint256[]"},{"components":[{"internalType":"address","name":"collection","type":"address"},{"components":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"numTokens","type":"uint256"}],"internalType":"struct OrderTypes.TokenInfo[]","name":"tokens","type":"tuple[]"}],"internalType":"struct OrderTypes.OrderItem[]","name":"nfts","type":"tuple[]"},{"internalType":"address[]","name":"execParams","type":"address[]"},{"internalType":"bytes","name":"extraParams","type":"bytes"},{"internalType":"bytes","name":"sig","type":"bytes"}],"internalType":"struct OrderTypes.MakerOrder[]","name":"buys","type":"tuple[]"},{"components":[{"internalType":"bool","name":"isSellOrder","type":"bool"},{"internalType":"address","name":"signer","type":"address"},{"internalType":"uint256[]","name":"constraints","type":"uint256[]"},{"components":[{"internalType":"address","name":"collection","type":"address"},{"components":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"numTokens","type":"uint256"}],"internalType":"struct OrderTypes.TokenInfo[]","name":"tokens","type":"tuple[]"}],"internalType":"struct OrderTypes.OrderItem[]","name":"nfts","type":"tuple[]"},{"internalType":"address[]","name":"execParams","type":"address[]"},{"internalType":"bytes","name":"extraParams","type":"bytes"},{"internalType":"bytes","name":"sig","type":"bytes"}],"internalType":"struct OrderTypes.MakerOrder[]","name":"sells","type":"tuple[]"},{"components":[{"internalType":"address","name":"collection","type":"address"},{"components":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"numTokens","type":"uint256"}],"internalType":"struct OrderTypes.TokenInfo[]","name":"tokens","type":"tuple[]"}],"internalType":"struct OrderTypes.OrderItem[][]","name":"constructs","type":"tuple[][]"},{"internalType":"enum FlowMatchExecutorTypes.MatchOrdersType","name":"matchType","type":"uint8"}],"internalType":"struct FlowMatchExecutorTypes.MatchOrders[]","name":"matches","type":"tuple[]"}],"internalType":"struct FlowMatchExecutorTypes.Batch[]","name":"batches","type":"tuple[]"}],"name":"executeBrokerMatches","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"bool","name":"isSellOrder","type":"bool"},{"internalType":"address","name":"signer","type":"address"},{"internalType":"uint256[]","name":"constraints","type":"uint256[]"},{"components":[{"internalType":"address","name":"collection","type":"address"},{"components":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"numTokens","type":"uint256"}],"internalType":"struct OrderTypes.TokenInfo[]","name":"tokens","type":"tuple[]"}],"internalType":"struct OrderTypes.OrderItem[]","name":"nfts","type":"tuple[]"},{"internalType":"address[]","name":"execParams","type":"address[]"},{"internalType":"bytes","name":"extraParams","type":"bytes"},{"internalType":"bytes","name":"sig","type":"bytes"}],"internalType":"struct OrderTypes.MakerOrder[]","name":"buys","type":"tuple[]"},{"components":[{"internalType":"bool","name":"isSellOrder","type":"bool"},{"internalType":"address","name":"signer","type":"address"},{"internalType":"uint256[]","name":"constraints","type":"uint256[]"},{"components":[{"internalType":"address","name":"collection","type":"address"},{"components":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"numTokens","type":"uint256"}],"internalType":"struct OrderTypes.TokenInfo[]","name":"tokens","type":"tuple[]"}],"internalType":"struct OrderTypes.OrderItem[]","name":"nfts","type":"tuple[]"},{"internalType":"address[]","name":"execParams","type":"address[]"},{"internalType":"bytes","name":"extraParams","type":"bytes"},{"internalType":"bytes","name":"sig","type":"bytes"}],"internalType":"struct OrderTypes.MakerOrder[]","name":"sells","type":"tuple[]"},{"components":[{"internalType":"address","name":"collection","type":"address"},{"components":[{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"numTokens","type":"uint256"}],"internalType":"struct OrderTypes.TokenInfo[]","name":"tokens","type":"tuple[]"}],"internalType":"struct OrderTypes.OrderItem[][]","name":"constructs","type":"tuple[][]"},{"internalType":"enum FlowMatchExecutorTypes.MatchOrdersType","name":"matchType","type":"uint8"}],"internalType":"struct FlowMatchExecutorTypes.MatchOrders[]","name":"matches","type":"tuple[]"}],"name":"executeNativeMatches","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"initiator","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"message","type":"bytes32"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"isValidSignature","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC721Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"unpause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_initiator","type":"address"}],"name":"updateInitiator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"weth","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"destination","type":"address"}],"name":"withdrawETH","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"destination","type":"address"},{"internalType":"address","name":"currency","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
60c034620000ce57601f6200247c38819003918201601f19168301916001600160401b03831184841017620000d357808492606094604052833981010312620000ce5780516200007b916200005482620000e9565b60406020820151916200006783620000e9565b0151916200007583620000e9565b620000fb565b60405161230e90816200016e8239608051818181610e920152818161148301528181611eb601528181611fb1015281816120cb015261219f015260a0518181816105a80152818161080901526108b00152f35b600080fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b03811603620000ce57565b91906000549060018060a01b03938492338482167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e06000604051a36001600160a81b0319163360ff60a01b191617600055608052600180546001600160a01b031916929091169190911790551660a05256fe6080604052600436101561001b575b361561001957600080fd5b005b60003560e01c8063150b7a021461015b5780631626ba7e146101525780631c7a67d7146101495780633f4ba83a146101405780633fc8cef31461013757806353316fdc1461012e5780635c39fcc1146101255780635c975abb1461011c5780635e35359e14610113578063690d83201461010a578063715018a6146101015780638456cb59146100f85780638da5cb5b146100ef578063a4f375b2146100e6578063d2f7265a146100dd5763f2fde38b0361000e576100d8610eb6565b61000e565b506100d8610e46565b506100d8610d8b565b506100d8610d38565b506100d8610c6a565b506100d8610bc5565b506100d8610abc565b506100d8610987565b506100d8610942565b506100d86108ef565b506100d861082d565b506100d86107bd565b506100d86106a9565b506100d8610525565b506100d8610254565b506100d86101c2565b73ffffffffffffffffffffffffffffffffffffffff81160361018257565b600080fd5b359061019282610164565b565b9181601f840112156101825782359167ffffffffffffffff8311610182576020838186019501011161018257565b50346101825760807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610182576101fd600435610164565b610208602435610164565b60643567ffffffffffffffff811161018257610228903690600401610194565b505060206040517f150b7a02000000000000000000000000000000000000000000000000000000008152f35b5034610182576040807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101825760243567ffffffffffffffff8111610182576102a5903690600401610194565b906102cc73ffffffffffffffffffffffffffffffffffffffff918260015416933691611159565b80518481036103d6575060006102ec826020808095518301019101612297565b61034861031e7f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83169260ff1c6122c6565b915b8851938493600435859094939260ff6060936080840197845216602083015260408201520152565b838052039060015afa156103c9575b600051169081159182156103be575b505061039557517f1626ba7e000000000000000000000000000000000000000000000000000000008152602090f35b600490517f815e1d64000000000000000000000000000000000000000000000000000000008152fd5b141590503880610366565b6103d1611269565b610357565b6041036104915761040161042d6104276103f96020855186010160208601612297565b9390946122ad565b517fff000000000000000000000000000000000000000000000000000000000000001690565b60f81c90565b9060ff8216601b8114159081610485575b506104525791600091610348602094610320565b85517f1f003d0a00000000000000000000000000000000000000000000000000000000815260ff83166004820152602490fd5b601c915014153861043e565b600484517f8baa579f000000000000000000000000000000000000000000000000000000008152fd5b9060207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8301126101825760043567ffffffffffffffff9283821161018257806023830112156101825781600401359384116101825760248460051b83010111610182576024019190565b50346101825761001961062f61053a366104ba565b61054f60ff60009493945460a01c1615611190565b73ffffffffffffffffffffffffffffffffffffffff90610574826001541633146111f5565b6040517f70a082310000000000000000000000000000000000000000000000000000000080825230600483015260209390927f0000000000000000000000000000000000000000000000000000000000000000909116916105fe91906105f89047878280602481015b0381895afa918215610691575b600092610672575b506112a6565b96611e62565b6040519182523060048301524791908390829060249082905afa928315610665575b600093610636575b50506112a6565b10156112be565b610656929350803d1061065e575b61064e81836110cf565b81019061125a565b903880610628565b503d610644565b61066d611269565b610620565b61068a919250883d8a1161065e5761064e81836110cf565b90386105f2565b610699611269565b6105ea565b600091031261018257565b5034610182576000807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126107ba5780546106fd3373ffffffffffffffffffffffffffffffffffffffff831614610faa565b60ff8160a01c161561075c577fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1681557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa6020604051338152a1604051f35b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f5061757361626c653a206e6f74207061757365640000000000000000000000006044820152fd5b80fd5b50346101825760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261018257602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b50346101825761001961062f610842366104ba565b61085760ff60009493945460a01c1615611190565b73ffffffffffffffffffffffffffffffffffffffff9061087c826001541633146111f5565b6040517f70a082310000000000000000000000000000000000000000000000000000000080825230600483015260209390927f0000000000000000000000000000000000000000000000000000000000000000909116916105fe91906108e99047878280602481016105dd565b96611403565b50346101825760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261018257602073ffffffffffffffffffffffffffffffffffffffff60015416604051908152f35b50346101825760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261018257602060ff60005460a01c166040519015158152f35b50346101825760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610182576004356109c381610164565b602435906109d082610164565b7fbfed55bdcd242e3dd0f60ddd7d1e87c67f61c34cd9527b3e6455d841b1025362610a7c60443573ffffffffffffffffffffffffffffffffffffffff8095610a1d82600054163314610faa565b1694604051947fa9059cbb000000000000000000000000000000000000000000000000000000008652169384600482015281602482015260208160448160008a5af18015610aaf575b610a81575b506040519081529081906020820190565b0390a3005b610aa19060203d8111610aa8575b610a9981836110cf565b810190611782565b5038610a6b565b503d610a8f565b610ab7611269565b610a66565b50346101825760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261018257600435610af881610164565b73ffffffffffffffffffffffffffffffffffffffff610b1c81600054163314610faa565b47916000808060405186855af1610b31611797565b5015610b67577f94b2de810873337ed265c5f8cf98c9cffefa06b8607f9a2f1fbaebdfbcfbef1c916020916040519485521692a2005b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600660248201527f6661696c656400000000000000000000000000000000000000000000000000006044820152fd5b5034610182576000807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126107ba5780547fffffffffffffffffffffffff000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff821691610c3c338414610faa565b16825581604051917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08284a3f35b5034610182576000807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126107ba57740100000000000000000000000000000000000000007fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff8254610cf53373ffffffffffffffffffffffffffffffffffffffff831614610faa565b610d0560ff8260a01c1615611190565b161781557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586020604051338152a1604051f35b50346101825760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261018257602073ffffffffffffffffffffffffffffffffffffffff60005416604051908152f35b50346101825760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610182576000600435610dc981610164565b73ffffffffffffffffffffffffffffffffffffffff610dec818454163314610faa565b80600154921690817fffffffffffffffffffffffff000000000000000000000000000000000000000084161760015560405192167fc3d24be93792ec22f55271a008e9bc0ee41485d33131829279955255eb874d5d8484a3f35b50346101825760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261018257602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b50346101825760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261018257600435610ef281610164565b73ffffffffffffffffffffffffffffffffffffffff610f1681600054163314610faa565b811615610f26576100199061100f565b60846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152fd5b15610fb157565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602060248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152fd5b6000549073ffffffffffffffffffffffffffffffffffffffff80911691827fffffffffffffffffffffffff0000000000000000000000000000000000000000821617600055167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e06000604051a3565b507f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b67ffffffffffffffff81116110c257604052565b6110ca61107e565b604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff8211176110c257604052565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f60209267ffffffffffffffff811161114c575b01160190565b61115461107e565b611146565b92919261116582611110565b9161117360405193846110cf565b829481845281830111610182578281602093846000960137010152565b1561119757565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a20706175736564000000000000000000000000000000006044820152fd5b156111fc57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f6f6e6c7920696e69746961746f722063616e2063616c6c0000000000000000006044820152fd5b90816020910312610182575190565b506040513d6000823e3d90fd5b507f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b811981116112b2570190565b6112ba611276565b0190565b156112c557565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f5472616e73616374696f6e206e6f74206e6f6e2d6e65676174697665000000006044820152fd5b507f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc181360301821215610182570190565b909161139f928110156113a2575b60051b810190611353565b90565b6113aa611323565b611394565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610182570180359067ffffffffffffffff821161018257602001918160051b3603831361018257565b9060005b81811061141357505050565b611427611421828486611386565b80611353565b61143181806113af565b809150611662575b506020908181019061144b82826113af565b80929150611481575b5050509061147b61147560019361146c848789611386565b908101906113af565b90611e62565b01611407565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169260005b8381106114ca575050611454565b6115056114ec6114ec6114e7846114e187896113af565b90611386565b61176e565b73ffffffffffffffffffffffffffffffffffffffff1690565b604080517fe985e9c50000000000000000000000000000000000000000000000000000000081523060048083019190915273ffffffffffffffffffffffffffffffffffffffff891660248301529193928990829060449082905afa908115611655575b600091611638575b5015611582575b5060019150016114bc565b6115996114ec6114ec6114e7856114e1898b6113af565b90813b1561018257876116029260009283600197518096819582947fa22cb4650000000000000000000000000000000000000000000000000000000084528301602060019193929373ffffffffffffffffffffffffffffffffffffffff60408201951681520152565b03925af1801561162b575b15611577578061161f611625926110ae565b8061069e565b38611577565b611633611269565b61160d565b61164f9150893d8b11610aa857610a9981836110cf565b38611570565b61165d611269565b611568565b60005b8181106116725750611439565b8061169961169461168f60019461168988806113af565b906116a0565b6116ee565b6117c7565b5001611665565b91908110156116e1575b60051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa181360301821215610182570190565b6116e9611323565b6116aa565b606081360312610182576040519067ffffffffffffffff6060830181811184821017611761575b60405281359081116101825781019036601f83011215610182576117426040923690602081359101611159565b835260208101356020840152013561175981610164565b604082015290565b61176961107e565b611715565b3561139f81610164565b8015150361018257565b90816020910312610182575161139f81611778565b3d156117c2573d906117a882611110565b916117b660405193846110cf565b82523d6000602084013e565b606090565b6000809173ffffffffffffffffffffffffffffffffffffffff6040820151166020820151915191602083519301915af16117ff611797565b90156118085790565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f65787465726e616c2063616c6c206661696c65640000000000000000000000006044820152fd5b91908110156118a7575b60051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8181360301821215610182570190565b6118af611323565b611870565b600311156118be57565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b3560038110156101825790565b9015611934575b8035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff2181360301821215610182570190565b61193c611323565b611901565b90357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18236030181121561018257016020813591019167ffffffffffffffff8211610182578160051b3603831361018257565b90918281527f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83116101825760209260051b80928483013701016000815290565b9082818152602080910193818360051b82010194846000925b8584106119ff575050505050505090565b909192939495967fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082820301845287357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc1843603018112156101825783016040908183019073ffffffffffffffffffffffffffffffffffffffff8135611a8481610164565b168452888101357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18236030181121561018257019088823592019367ffffffffffffffff8311610182578260061b3603851361018257808385938c96876060950152520193916000915b818310611b0e5750505050806001929901940194019295949391906119ee565b833586528a8401358b870152948501948a945092830192600190920191611aee565b91908082526020809201929160005b828110611b4d575050505090565b90919293828060019273ffffffffffffffffffffffffffffffffffffffff8835611b7681610164565b16815201950193929101611b3f565b90357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18236030181121561018257016020813591019167ffffffffffffffff821161018257813603831361018257565b601f82602094937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0938186528686013760008582860101520116010190565b61139f918135611c2381611778565b15158152611c53611c3660208401610187565b73ffffffffffffffffffffffffffffffffffffffff166020830152565b611cdc611cd1611cb6611c9b611c80611c6f6040880188611941565b60e0604089015260e0880191611994565b611c8d6060880188611941565b9087830360608901526119d5565b611ca86080870187611941565b908683036080880152611b30565b611cc360a0860186611b85565b9085830360a0870152611bd5565b9260c0810190611b85565b9160c0818503910152611bd5565b909182815260208091019283918160051b85019484600080925b858410611d1657505050505050505090565b9091929394959697818103885288357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff2185360301811215611d715786611d6160019387839401611c14565b9a01980196959401929190611d04565b8380fd5b91611d8c61139f9492604085526040850190611c14565b926020818503910152611cea565b959390611db390611dc393606089526060890191611cea565b9060209387830385890152611cea565b93604081860391015281845280840193818360051b82010194846000925b858410611df2575050505050505090565b909192939495968580611e38837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08660019603018852611e328c88611941565b906119d5565b990194019401929594939190611de1565b9290611d8c9061139f9593604086526040860191611cea565b81611e6b575050565b60005b828110611e7a57505050565b611e906060611e8a838686611866565b016118ed565b611e99816118b4565b80611f85575073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690611eeb611ee5828686611866565b806113af565b9290611f05611efb848888611866565b60208101906113af565b92803b156101825760019560008094611f4d604051978896879586947f9d9a0cef00000000000000000000000000000000000000000000000000000000865260048601611e49565b03925af18015611f78575b611f65575b505b01611e6e565b8061161f611f72926110ae565b38611f5d565b611f80611269565b611f58565b611f8e816118b4565b60019080820361208957505073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001690611fe0611efb828686611866565b9290611ff0611ee5848888611866565b92611ffc858989611866565b9561200c604097888101906113af565b94833b1561018257612053600096879360019b51998a98899788967f0df4239c00000000000000000000000000000000000000000000000000000000885260048801611d9a565b03925af1801561207c575b612069575b50611f5f565b8061161f612076926110ae565b38612063565b612084611269565b61205e565b806120956002926118b4565b0361223857806120a9611ee5848787611866565b90501460001461215c575073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906121036120fd611ee5838787611866565b906118fa565b612111611efb838787611866565b849291923b15610182576001946120539360008094604051968795869485937f63f3c03400000000000000000000000000000000000000000000000000000000855260048501611d75565b90612168818585611866565b91612178602093848101906113af565b9050146000146121d9576121cb6120fd73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000169361146c848888611866565b612111611ee5838787611866565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f696e76616c6964206f6e6520746f206d616e79206f72646572000000000000006044820152606490fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f696e76616c6964206d61746368207479706500000000000000000000000000006044820152606490fd5b9190826040910312610182576020825192015190565b6060908051604010156122be570190565b6112ba611323565b60ff601b911660e481116112b257019056fea26469706673582212204579974c3c06aeb3417eb2c70e572cd91cc6bb4b7bafd98e7fa835455993e0dc64736f6c634300080e0033000000000000000000000000a79c18bcdd5c45d4f58317609fe1b6c6a5b623b200000000000000000000000031ae855ca3ee0413da86eca2f877ddd0da30e703000000000000000000000000b4fbf271143f4fbf7b91a5ded31805e42b2208d6
Deployed Bytecode
0x6080604052600436101561001b575b361561001957600080fd5b005b60003560e01c8063150b7a021461015b5780631626ba7e146101525780631c7a67d7146101495780633f4ba83a146101405780633fc8cef31461013757806353316fdc1461012e5780635c39fcc1146101255780635c975abb1461011c5780635e35359e14610113578063690d83201461010a578063715018a6146101015780638456cb59146100f85780638da5cb5b146100ef578063a4f375b2146100e6578063d2f7265a146100dd5763f2fde38b0361000e576100d8610eb6565b61000e565b506100d8610e46565b506100d8610d8b565b506100d8610d38565b506100d8610c6a565b506100d8610bc5565b506100d8610abc565b506100d8610987565b506100d8610942565b506100d86108ef565b506100d861082d565b506100d86107bd565b506100d86106a9565b506100d8610525565b506100d8610254565b506100d86101c2565b73ffffffffffffffffffffffffffffffffffffffff81160361018257565b600080fd5b359061019282610164565b565b9181601f840112156101825782359167ffffffffffffffff8311610182576020838186019501011161018257565b50346101825760807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610182576101fd600435610164565b610208602435610164565b60643567ffffffffffffffff811161018257610228903690600401610194565b505060206040517f150b7a02000000000000000000000000000000000000000000000000000000008152f35b5034610182576040807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101825760243567ffffffffffffffff8111610182576102a5903690600401610194565b906102cc73ffffffffffffffffffffffffffffffffffffffff918260015416933691611159565b80518481036103d6575060006102ec826020808095518301019101612297565b61034861031e7f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83169260ff1c6122c6565b915b8851938493600435859094939260ff6060936080840197845216602083015260408201520152565b838052039060015afa156103c9575b600051169081159182156103be575b505061039557517f1626ba7e000000000000000000000000000000000000000000000000000000008152602090f35b600490517f815e1d64000000000000000000000000000000000000000000000000000000008152fd5b141590503880610366565b6103d1611269565b610357565b6041036104915761040161042d6104276103f96020855186010160208601612297565b9390946122ad565b517fff000000000000000000000000000000000000000000000000000000000000001690565b60f81c90565b9060ff8216601b8114159081610485575b506104525791600091610348602094610320565b85517f1f003d0a00000000000000000000000000000000000000000000000000000000815260ff83166004820152602490fd5b601c915014153861043e565b600484517f8baa579f000000000000000000000000000000000000000000000000000000008152fd5b9060207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8301126101825760043567ffffffffffffffff9283821161018257806023830112156101825781600401359384116101825760248460051b83010111610182576024019190565b50346101825761001961062f61053a366104ba565b61054f60ff60009493945460a01c1615611190565b73ffffffffffffffffffffffffffffffffffffffff90610574826001541633146111f5565b6040517f70a082310000000000000000000000000000000000000000000000000000000080825230600483015260209390927f000000000000000000000000b4fbf271143f4fbf7b91a5ded31805e42b2208d6909116916105fe91906105f89047878280602481015b0381895afa918215610691575b600092610672575b506112a6565b96611e62565b6040519182523060048301524791908390829060249082905afa928315610665575b600093610636575b50506112a6565b10156112be565b610656929350803d1061065e575b61064e81836110cf565b81019061125a565b903880610628565b503d610644565b61066d611269565b610620565b61068a919250883d8a1161065e5761064e81836110cf565b90386105f2565b610699611269565b6105ea565b600091031261018257565b5034610182576000807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126107ba5780546106fd3373ffffffffffffffffffffffffffffffffffffffff831614610faa565b60ff8160a01c161561075c577fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff1681557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa6020604051338152a1604051f35b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f5061757361626c653a206e6f74207061757365640000000000000000000000006044820152fd5b80fd5b50346101825760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261018257602060405173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000b4fbf271143f4fbf7b91a5ded31805e42b2208d6168152f35b50346101825761001961062f610842366104ba565b61085760ff60009493945460a01c1615611190565b73ffffffffffffffffffffffffffffffffffffffff9061087c826001541633146111f5565b6040517f70a082310000000000000000000000000000000000000000000000000000000080825230600483015260209390927f000000000000000000000000b4fbf271143f4fbf7b91a5ded31805e42b2208d6909116916105fe91906108e99047878280602481016105dd565b96611403565b50346101825760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261018257602073ffffffffffffffffffffffffffffffffffffffff60015416604051908152f35b50346101825760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261018257602060ff60005460a01c166040519015158152f35b50346101825760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610182576004356109c381610164565b602435906109d082610164565b7fbfed55bdcd242e3dd0f60ddd7d1e87c67f61c34cd9527b3e6455d841b1025362610a7c60443573ffffffffffffffffffffffffffffffffffffffff8095610a1d82600054163314610faa565b1694604051947fa9059cbb000000000000000000000000000000000000000000000000000000008652169384600482015281602482015260208160448160008a5af18015610aaf575b610a81575b506040519081529081906020820190565b0390a3005b610aa19060203d8111610aa8575b610a9981836110cf565b810190611782565b5038610a6b565b503d610a8f565b610ab7611269565b610a66565b50346101825760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261018257600435610af881610164565b73ffffffffffffffffffffffffffffffffffffffff610b1c81600054163314610faa565b47916000808060405186855af1610b31611797565b5015610b67577f94b2de810873337ed265c5f8cf98c9cffefa06b8607f9a2f1fbaebdfbcfbef1c916020916040519485521692a2005b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600660248201527f6661696c656400000000000000000000000000000000000000000000000000006044820152fd5b5034610182576000807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126107ba5780547fffffffffffffffffffffffff000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff821691610c3c338414610faa565b16825581604051917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08284a3f35b5034610182576000807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126107ba57740100000000000000000000000000000000000000007fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff8254610cf53373ffffffffffffffffffffffffffffffffffffffff831614610faa565b610d0560ff8260a01c1615611190565b161781557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a2586020604051338152a1604051f35b50346101825760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261018257602073ffffffffffffffffffffffffffffffffffffffff60005416604051908152f35b50346101825760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610182576000600435610dc981610164565b73ffffffffffffffffffffffffffffffffffffffff610dec818454163314610faa565b80600154921690817fffffffffffffffffffffffff000000000000000000000000000000000000000084161760015560405192167fc3d24be93792ec22f55271a008e9bc0ee41485d33131829279955255eb874d5d8484a3f35b50346101825760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261018257602060405173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000a79c18bcdd5c45d4f58317609fe1b6c6a5b623b2168152f35b50346101825760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261018257600435610ef281610164565b73ffffffffffffffffffffffffffffffffffffffff610f1681600054163314610faa565b811615610f26576100199061100f565b60846040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152fd5b15610fb157565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602060248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152fd5b6000549073ffffffffffffffffffffffffffffffffffffffff80911691827fffffffffffffffffffffffff0000000000000000000000000000000000000000821617600055167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e06000604051a3565b507f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b67ffffffffffffffff81116110c257604052565b6110ca61107e565b604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff8211176110c257604052565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f60209267ffffffffffffffff811161114c575b01160190565b61115461107e565b611146565b92919261116582611110565b9161117360405193846110cf565b829481845281830111610182578281602093846000960137010152565b1561119757565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601060248201527f5061757361626c653a20706175736564000000000000000000000000000000006044820152fd5b156111fc57565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f6f6e6c7920696e69746961746f722063616e2063616c6c0000000000000000006044820152fd5b90816020910312610182575190565b506040513d6000823e3d90fd5b507f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b811981116112b2570190565b6112ba611276565b0190565b156112c557565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601c60248201527f5472616e73616374696f6e206e6f74206e6f6e2d6e65676174697665000000006044820152fd5b507f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc181360301821215610182570190565b909161139f928110156113a2575b60051b810190611353565b90565b6113aa611323565b611394565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610182570180359067ffffffffffffffff821161018257602001918160051b3603831361018257565b9060005b81811061141357505050565b611427611421828486611386565b80611353565b61143181806113af565b809150611662575b506020908181019061144b82826113af565b80929150611481575b5050509061147b61147560019361146c848789611386565b908101906113af565b90611e62565b01611407565b7f000000000000000000000000a79c18bcdd5c45d4f58317609fe1b6c6a5b623b273ffffffffffffffffffffffffffffffffffffffff169260005b8381106114ca575050611454565b6115056114ec6114ec6114e7846114e187896113af565b90611386565b61176e565b73ffffffffffffffffffffffffffffffffffffffff1690565b604080517fe985e9c50000000000000000000000000000000000000000000000000000000081523060048083019190915273ffffffffffffffffffffffffffffffffffffffff891660248301529193928990829060449082905afa908115611655575b600091611638575b5015611582575b5060019150016114bc565b6115996114ec6114ec6114e7856114e1898b6113af565b90813b1561018257876116029260009283600197518096819582947fa22cb4650000000000000000000000000000000000000000000000000000000084528301602060019193929373ffffffffffffffffffffffffffffffffffffffff60408201951681520152565b03925af1801561162b575b15611577578061161f611625926110ae565b8061069e565b38611577565b611633611269565b61160d565b61164f9150893d8b11610aa857610a9981836110cf565b38611570565b61165d611269565b611568565b60005b8181106116725750611439565b8061169961169461168f60019461168988806113af565b906116a0565b6116ee565b6117c7565b5001611665565b91908110156116e1575b60051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa181360301821215610182570190565b6116e9611323565b6116aa565b606081360312610182576040519067ffffffffffffffff6060830181811184821017611761575b60405281359081116101825781019036601f83011215610182576117426040923690602081359101611159565b835260208101356020840152013561175981610164565b604082015290565b61176961107e565b611715565b3561139f81610164565b8015150361018257565b90816020910312610182575161139f81611778565b3d156117c2573d906117a882611110565b916117b660405193846110cf565b82523d6000602084013e565b606090565b6000809173ffffffffffffffffffffffffffffffffffffffff6040820151166020820151915191602083519301915af16117ff611797565b90156118085790565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f65787465726e616c2063616c6c206661696c65640000000000000000000000006044820152fd5b91908110156118a7575b60051b810135907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8181360301821215610182570190565b6118af611323565b611870565b600311156118be57565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b3560038110156101825790565b9015611934575b8035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff2181360301821215610182570190565b61193c611323565b611901565b90357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18236030181121561018257016020813591019167ffffffffffffffff8211610182578160051b3603831361018257565b90918281527f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff83116101825760209260051b80928483013701016000815290565b9082818152602080910193818360051b82010194846000925b8584106119ff575050505050505090565b909192939495967fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082820301845287357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc1843603018112156101825783016040908183019073ffffffffffffffffffffffffffffffffffffffff8135611a8481610164565b168452888101357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18236030181121561018257019088823592019367ffffffffffffffff8311610182578260061b3603851361018257808385938c96876060950152520193916000915b818310611b0e5750505050806001929901940194019295949391906119ee565b833586528a8401358b870152948501948a945092830192600190920191611aee565b91908082526020809201929160005b828110611b4d575050505090565b90919293828060019273ffffffffffffffffffffffffffffffffffffffff8835611b7681610164565b16815201950193929101611b3f565b90357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe18236030181121561018257016020813591019167ffffffffffffffff821161018257813603831361018257565b601f82602094937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0938186528686013760008582860101520116010190565b61139f918135611c2381611778565b15158152611c53611c3660208401610187565b73ffffffffffffffffffffffffffffffffffffffff166020830152565b611cdc611cd1611cb6611c9b611c80611c6f6040880188611941565b60e0604089015260e0880191611994565b611c8d6060880188611941565b9087830360608901526119d5565b611ca86080870187611941565b908683036080880152611b30565b611cc360a0860186611b85565b9085830360a0870152611bd5565b9260c0810190611b85565b9160c0818503910152611bd5565b909182815260208091019283918160051b85019484600080925b858410611d1657505050505050505090565b9091929394959697818103885288357fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff2185360301811215611d715786611d6160019387839401611c14565b9a01980196959401929190611d04565b8380fd5b91611d8c61139f9492604085526040850190611c14565b926020818503910152611cea565b959390611db390611dc393606089526060890191611cea565b9060209387830385890152611cea565b93604081860391015281845280840193818360051b82010194846000925b858410611df2575050505050505090565b909192939495968580611e38837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08660019603018852611e328c88611941565b906119d5565b990194019401929594939190611de1565b9290611d8c9061139f9593604086526040860191611cea565b81611e6b575050565b60005b828110611e7a57505050565b611e906060611e8a838686611866565b016118ed565b611e99816118b4565b80611f85575073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000a79c18bcdd5c45d4f58317609fe1b6c6a5b623b21690611eeb611ee5828686611866565b806113af565b9290611f05611efb848888611866565b60208101906113af565b92803b156101825760019560008094611f4d604051978896879586947f9d9a0cef00000000000000000000000000000000000000000000000000000000865260048601611e49565b03925af18015611f78575b611f65575b505b01611e6e565b8061161f611f72926110ae565b38611f5d565b611f80611269565b611f58565b611f8e816118b4565b60019080820361208957505073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000a79c18bcdd5c45d4f58317609fe1b6c6a5b623b21690611fe0611efb828686611866565b9290611ff0611ee5848888611866565b92611ffc858989611866565b9561200c604097888101906113af565b94833b1561018257612053600096879360019b51998a98899788967f0df4239c00000000000000000000000000000000000000000000000000000000885260048801611d9a565b03925af1801561207c575b612069575b50611f5f565b8061161f612076926110ae565b38612063565b612084611269565b61205e565b806120956002926118b4565b0361223857806120a9611ee5848787611866565b90501460001461215c575073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000a79c18bcdd5c45d4f58317609fe1b6c6a5b623b216906121036120fd611ee5838787611866565b906118fa565b612111611efb838787611866565b849291923b15610182576001946120539360008094604051968795869485937f63f3c03400000000000000000000000000000000000000000000000000000000855260048501611d75565b90612168818585611866565b91612178602093848101906113af565b9050146000146121d9576121cb6120fd73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000a79c18bcdd5c45d4f58317609fe1b6c6a5b623b2169361146c848888611866565b612111611ee5838787611866565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f696e76616c6964206f6e6520746f206d616e79206f72646572000000000000006044820152606490fd5b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601260248201527f696e76616c6964206d61746368207479706500000000000000000000000000006044820152606490fd5b9190826040910312610182576020825192015190565b6060908051604010156122be570190565b6112ba611323565b60ff601b911660e481116112b257019056fea26469706673582212204579974c3c06aeb3417eb2c70e572cd91cc6bb4b7bafd98e7fa835455993e0dc64736f6c634300080e0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000a79c18bcdd5c45d4f58317609fe1b6c6a5b623b200000000000000000000000031ae855ca3ee0413da86eca2f877ddd0da30e703000000000000000000000000b4fbf271143f4fbf7b91a5ded31805e42b2208d6
-----Decoded View---------------
Arg [0] : _exchange (address): 0xa79C18bCDd5C45d4f58317609fe1B6C6A5B623b2
Arg [1] : _initiator (address): 0x31ae855ca3Ee0413dA86eCA2f877ddd0dA30e703
Arg [2] : _weth (address): 0xB4FBF271143F4FBf7B91A5ded31805e42b2208d6
-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 000000000000000000000000a79c18bcdd5c45d4f58317609fe1b6c6a5b623b2
Arg [1] : 00000000000000000000000031ae855ca3ee0413da86eca2f877ddd0da30e703
Arg [2] : 000000000000000000000000b4fbf271143f4fbf7b91a5ded31805e42b2208d6
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.