Feature Tip: Add private address tag to any address under My Name Tag !
Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
EZAggregatorV1RouterUpgrade
Compiler Version
v0.8.17+commit.8df45f5f
Optimization Enabled:
No with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: GPL-3.0-or-later // ________ ________ ______ __ // / |/ | / \ / | // $$$$$$$$/ $$$$$$$$/ /$$$$$$ | ______ ______ ______ ______ ______ ______ _$$ |_ ______ ______ // $$ |__ /$$/ $$ |__$$ | / \ / \ / \ / \ / \ / \ / $$ | / \ / \ // $$ | /$$/ $$ $$ |/$$$$$$ |/$$$$$$ |/$$$$$$ |/$$$$$$ |/$$$$$$ | $$$$$$ |$$$$$$/ /$$$$$$ |/$$$$$$ | // $$$$$/ /$$/ $$$$$$$$ |$$ | $$ |$$ | $$ |$$ | $$/ $$ $$ |$$ | $$ | / $$ | $$ | __ $$ | $$ |$$ | $$/ // $$ |_____ /$$/____ $$ | $$ |$$ \__$$ |$$ \__$$ |$$ | $$$$$$$$/ $$ \__$$ |/$$$$$$$ | $$ |/ |$$ \__$$ |$$ | // $$ |/$$ |$$ | $$ |$$ $$ |$$ $$ |$$ | $$ |$$ $$ |$$ $$ | $$ $$/ $$ $$/ $$ | // $$$$$$$$/ $$$$$$$$/ $$/ $$/ $$$$$$$ | $$$$$$$ |$$/ $$$$$$$/ $$$$$$$ | $$$$$$$/ $$$$/ $$$$$$/ $$/ // / \__$$ |/ \__$$ | / \__$$ | // $$ $$/ $$ $$/ $$ $$/ // $$$$$$/ $$$$$$/ $$$$$$/ // pragma solidity ^0.8.17; import {Dispatcher} from "./base/Dispatcher.sol"; import {RouterParameters, RouterImmutables} from "./base/RouterImmutables.sol"; import {Constants} from "./libraries/Constants.sol"; import {Commands} from "./libraries/Commands.sol"; import {IUniversalRouter} from "./interfaces/IUniversalRouter.sol"; import {ReentrancyGuardUpgradeable} from "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol"; contract EZAggregatorV1RouterUpgrade is RouterImmutables, IUniversalRouter, Dispatcher, ReentrancyGuardUpgradeable { modifier checkDeadline(uint256 deadline) { if (block.timestamp > deadline) revert TransactionDeadlinePassed(); _; } /// @custom:oz-upgrades-unsafe-allow constructor constructor(RouterParameters memory params) RouterImmutables(params) initializer {} /// @inheritdoc IUniversalRouter function execute( bytes calldata commands, bytes[] calldata inputs, uint256 deadline ) external payable checkDeadline(deadline) { execute(commands, inputs); } /// @inheritdoc IUniversalRouter function execute( bytes calldata commands, bytes[] calldata inputs ) public payable nonReentrant { bool success; bytes memory output; uint256 numCommands = commands.length; if (inputs.length != numCommands) revert LengthMismatch(); // loop through all given commands, execute them and pass along outputs as defined for (uint256 commandIndex = 0; commandIndex < numCommands; ) { bytes1 command = commands[commandIndex]; bytes memory input = inputs[commandIndex]; (success, output) = dispatch(command, input); if (!success && successRequired(command)) { revert ExecutionFailed({ commandIndex: commandIndex, message: output }); } unchecked { commandIndex++; } } } function successRequired(bytes1 command) internal pure returns (bool) { return command & Commands.FLAG_ALLOW_REVERT == 0; } // To receive ETH from WETH and NFT protocols receive() external payable {} }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (proxy/utils/Initializable.sol) pragma solidity ^0.8.2; import "../../utils/AddressUpgradeable.sol"; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in * case an upgrade adds a module that needs to be initialized. * * For example: * * [.hljs-theme-light.nopadding] * ``` * contract MyToken is ERC20Upgradeable { * function initialize() initializer public { * __ERC20_init("MyToken", "MTK"); * } * } * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { * function initializeV2() reinitializer(2) public { * __ERC20Permit_init("MyToken"); * } * } * ``` * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() { * _disableInitializers(); * } * ``` * ==== */ abstract contract Initializable { /** * @dev Indicates that the contract has been initialized. * @custom:oz-retyped-from bool */ uint8 private _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool private _initializing; /** * @dev Triggered when the contract has been initialized or reinitialized. */ event Initialized(uint8 version); /** * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, * `onlyInitializing` functions can be used to initialize parent contracts. * * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a * constructor. * * Emits an {Initialized} event. */ modifier initializer() { bool isTopLevelCall = !_initializing; require( (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1), "Initializable: contract is already initialized" ); _initialized = 1; if (isTopLevelCall) { _initializing = true; } _; if (isTopLevelCall) { _initializing = false; emit Initialized(1); } } /** * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be * used to initialize parent contracts. * * A reinitializer may be used after the original initialization step. This is essential to configure modules that * are added through upgrades and that require initialization. * * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer` * cannot be nested. If one is invoked in the context of another, execution will revert. * * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in * a contract, executing them in the right order is up to the developer or operator. * * WARNING: setting the version to 255 will prevent any future reinitialization. * * Emits an {Initialized} event. */ modifier reinitializer(uint8 version) { require(!_initializing && _initialized < version, "Initializable: contract is already initialized"); _initialized = version; _initializing = true; _; _initializing = false; emit Initialized(version); } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} and {reinitializer} modifiers, directly or indirectly. */ modifier onlyInitializing() { require(_initializing, "Initializable: contract is not initializing"); _; } /** * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized * to any version. It is recommended to use this to lock implementation contracts that are designed to be called * through proxies. * * Emits an {Initialized} event the first time it is successfully executed. */ function _disableInitializers() internal virtual { require(!_initializing, "Initializable: contract is initializing"); if (_initialized < type(uint8).max) { _initialized = type(uint8).max; emit Initialized(type(uint8).max); } } /** * @dev Internal function that returns the initialized version. Returns `_initialized` */ function _getInitializedVersion() internal view returns (uint8) { return _initialized; } /** * @dev Internal function that returns the initialized version. Returns `_initializing` */ function _isInitializing() internal view returns (bool) { return _initializing; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (security/ReentrancyGuard.sol) pragma solidity ^0.8.0; import "../proxy/utils/Initializable.sol"; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuardUpgradeable is Initializable { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; function __ReentrancyGuard_init() internal onlyInitializing { __ReentrancyGuard_init_unchained(); } function __ReentrancyGuard_init_unchained() internal onlyInitializing { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { _nonReentrantBefore(); _; _nonReentrantAfter(); } function _nonReentrantBefore() private { // On the first call to nonReentrant, _status will be _NOT_ENTERED require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; } function _nonReentrantAfter() private { // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } /** * @dev This empty reserved space is put in place to allow future versions to add new * variables without shifting down storage in the inheritance chain. * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps */ uint256[49] private __gap; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library AddressUpgradeable { /** * @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 functionCallWithValue(target, data, 0, "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"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, 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) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or 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 { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // 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 /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol) pragma solidity ^0.8.0; import "../../utils/introspection/IERC165.sol"; /** * @dev _Available since v3.1._ */ interface IERC1155Receiver is IERC165 { /** * @dev Handles the receipt of a single ERC1155 token type. This function is * called at the end of a `safeTransferFrom` after the balance has been updated. * * NOTE: To accept the transfer, this must return * `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` * (i.e. 0xf23a6e61, or its own function selector). * * @param operator The address which initiated the transfer (i.e. msg.sender) * @param from The address which previously owned the token * @param id The ID of the token being transferred * @param value The amount of tokens being transferred * @param data Additional data with no specified format * @return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` if transfer is allowed */ function onERC1155Received( address operator, address from, uint256 id, uint256 value, bytes calldata data ) external returns (bytes4); /** * @dev Handles the receipt of a multiple ERC1155 token types. This function * is called at the end of a `safeBatchTransferFrom` after the balances have * been updated. * * NOTE: To accept the transfer(s), this must return * `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` * (i.e. 0xbc197c81, or its own function selector). * * @param operator The address which initiated the batch transfer (i.e. msg.sender) * @param from The address which previously owned the token * @param ids An array containing ids of each token being transferred (order and length must match values array) * @param values An array containing amounts of each token being transferred (order and length must match ids array) * @param data Additional data with no specified format * @return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` if transfer is allowed */ function onERC1155BatchReceived( address operator, address from, uint256[] calldata ids, uint256[] calldata values, bytes calldata data ) external returns (bytes4); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @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); /** * @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); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (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 `IERC721Receiver.onERC721Received.selector`. */ function onERC721Received( address operator, address from, uint256 tokenId, bytes calldata data ) external returns (bytes4); }
// 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: GPL-3.0-or-later pragma solidity ^0.8.17; import {IERC721Receiver} from '@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol'; import {IERC1155Receiver} from '@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol'; import {IERC165} from '@openzeppelin/contracts/utils/introspection/IERC165.sol'; /// @title ERC Callback Support /// @notice Implements various functions introduced by a variety of ERCs for security reasons. /// All are called by external contracts to ensure that this contract safely supports the ERC in question. contract Callbacks is IERC721Receiver, IERC1155Receiver { function onERC721Received(address, address, uint256, bytes calldata) external pure returns (bytes4) { return this.onERC721Received.selector; } function onERC1155Received(address, address, uint256, uint256, bytes calldata) external pure returns (bytes4) { return this.onERC1155Received.selector; } function onERC1155BatchReceived(address, address, uint256[] calldata, uint256[] calldata, bytes calldata) external pure returns (bytes4) { return this.onERC1155BatchReceived.selector; } function supportsInterface(bytes4 interfaceId) external pure returns (bool) { return interfaceId == type(IERC1155Receiver).interfaceId || interfaceId == type(IERC721Receiver).interfaceId || interfaceId == type(IERC165).interfaceId; } }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.17; import {HandleReservoir} from "../modules/HandleReservoir.sol"; import {HandleLSSVM} from "../modules/HandleLSSVM.sol"; import {Payments} from "../modules/Payments.sol"; import {RouterImmutables} from "../base/RouterImmutables.sol"; import {Callbacks} from "../base/Callbacks.sol"; import {Commands} from "../libraries/Commands.sol"; import {Recipient} from "../libraries/Recipient.sol"; import {ERC721} from "solmate/src/tokens/ERC721.sol"; import {ERC1155} from "solmate/src/tokens/ERC1155.sol"; /// @title Decodes and Executes Commands /// @notice Called by the UniversalRouter contract to efficiently decode and execute a singular command abstract contract Dispatcher is Payments, HandleReservoir, HandleLSSVM, Callbacks { using Recipient for address; error InvalidCommandType(uint256 commandType); error InvalidOwnerERC721(); error InvalidOwnerERC1155(); /// @notice Decodes and executes the given command with the given inputs /// @param commandType The command type to execute /// @param inputs The inputs to execute the command with /// @dev 2 masks are used to enable use of a nested-if statement in execution for efficiency reasons /// @return success True on success of the command, false on failure /// @return output The outputs or error messages, if any, from the command function dispatch( bytes1 commandType, bytes memory inputs ) internal returns (bool success, bytes memory output) { uint256 command = uint8(commandType & Commands.COMMAND_TYPE_MASK); success = true; if (command < 0x10) { // 0x00 <= command < 0x08 if (command < 0x08) { if (command == Commands.RESERVOIR_Buy) { (uint256 value, bytes memory data) = abi.decode( inputs, (uint256, bytes) ); (success, output) = RESERVOIR.call{value: value}(data); } else if (command == Commands.RESERVOIR_Sell) { ReservoirOfferStruct[] memory reservoirOffers = abi.decode( inputs, (ReservoirOfferStruct[]) ); HandleReservoir.handleReservoirSell(reservoirOffers); } else if (command == Commands.WRAP_ETH) { (address recipient, uint256 amountMin) = abi.decode( inputs, (address, uint256) ); Payments.wrapETH(recipient.map(), amountMin); } else if (command == Commands.UNWRAP_WETH) { (address recipient, uint256 amountMin) = abi.decode( inputs, (address, uint256) ); Payments.unwrapWETH9(recipient.map(), amountMin); } else if (command == Commands.SWEEP) { (address token, address recipient, uint256 amountMin) = abi .decode(inputs, (address, address, uint256)); Payments.sweep(token, recipient.map(), amountMin); } else if (command == Commands.TRANSFER) { (address token, address recipient, uint256 value) = abi .decode(inputs, (address, address, uint256)); Payments.pay(token, recipient.map(), value); } else if (command == Commands.PAY_PORTION) { (address token, address recipient, uint256 bips) = abi .decode(inputs, (address, address, uint256)); Payments.payPortion(token, recipient.map(), bips); } else if (command == Commands.COMMAND_PLACEHOLDER_0x07) { // placeholder for a future command revert InvalidCommandType(command); } // 0x08 <= command < 0x10 } else { if (command == Commands.SUDOSWAP_Buy) { (uint256 value, bytes memory data) = abi.decode( inputs, (uint256, bytes) ); (success, output) = SUDOSWAP.call{value: value}(data); } else if (command == Commands.SUDOSWAP_Sell) { ( bytes memory data, address nftOwner, LSSVMSellNftStruct[] memory sellNfts ) = abi.decode( inputs, (bytes, address, LSSVMSellNftStruct[]) ); (success, output) = HandleLSSVM.handleLSSVMSell( SUDOSWAP, data, nftOwner, sellNfts ); } else if (command == Commands.EZSWAP_Buy) { (uint256 value, bytes memory data) = abi.decode( inputs, (uint256, bytes) ); (success, output) = EZSWAP.call{value: value}(data); } else if (command == Commands.EZSWAP_Sell) { ( bytes memory data, address nftOwner, LSSVMSellNftStruct[] memory sellNfts ) = abi.decode( inputs, (bytes, address, LSSVMSellNftStruct[]) ); (success, output) = HandleLSSVM.handleLSSVMSell( EZSWAP, data, nftOwner, sellNfts ); } else if (command == Commands.SWEEP_ERC721) { (address token, address recipient, uint256 id) = abi.decode( inputs, (address, address, uint256) ); Payments.sweepERC721(token, recipient.map(), id); } else if (command == Commands.SWEEP_ERC1155) { ( address token, address recipient, uint256 id, uint256 amount ) = abi.decode( inputs, (address, address, uint256, uint256) ); Payments.sweepERC1155(token, recipient.map(), id, amount); } else if (command == Commands.COMMAND_PLACEHOLDER_0x0e) { // placeholder for a future command revert InvalidCommandType(command); } else if (command == Commands.COMMAND_PLACEHOLDER_0x0f) { // placeholder for a future command revert InvalidCommandType(command); } } // 0x10 <= command } else { // 0x10 <= command < 0x18 // 0x18 <= command < 0x1f // placeholder for a future command revert InvalidCommandType(command); } } }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.17; import {IWETH9} from "../interfaces/IWETH9.sol"; struct RouterParameters { address weth9; address reservoir; address seaportModule; address looksRareModule; address x2y2Module; address sudoswap; address ezswap; } /// @title Router Immutable Storage contract /// @notice Used along with the `RouterParameters` struct for ease of cross-chain deployment contract RouterImmutables { /// @dev WETH9 address /// @custom:oz-upgrades-unsafe-allow state-variable-immutable IWETH9 internal immutable WETH9; /// @dev Reservoir address /// @custom:oz-upgrades-unsafe-allow state-variable-immutable address internal immutable RESERVOIR; /// @dev SeaportModule address /// @custom:oz-upgrades-unsafe-allow state-variable-immutable address internal immutable SEAPORTMODULE; /// @dev LooksRareModule address /// @custom:oz-upgrades-unsafe-allow state-variable-immutable address internal immutable LOOKSRAREMODULE; /// @dev X2Y2Module address /// @custom:oz-upgrades-unsafe-allow state-variable-immutable address internal immutable X2Y2MODULE; // @dev Sudoswap's router address /// @custom:oz-upgrades-unsafe-allow state-variable-immutable address internal immutable SUDOSWAP; // @dev EZ's router address /// @custom:oz-upgrades-unsafe-allow state-variable-immutable address internal immutable EZSWAP; /// @custom:oz-upgrades-unsafe-allow constructor constructor(RouterParameters memory params) { WETH9 = IWETH9(params.weth9); RESERVOIR = params.reservoir; SEAPORTMODULE = params.seaportModule; LOOKSRAREMODULE = params.looksRareModule; X2Y2MODULE = params.x2y2Module; SUDOSWAP = params.sudoswap; EZSWAP = params.ezswap; } }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.17; import {IERC721Receiver} from '@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol'; import {IERC1155Receiver} from '@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol'; interface IUniversalRouter is IERC721Receiver, IERC1155Receiver { /// @notice Thrown when a required command has failed error ExecutionFailed(uint256 commandIndex, bytes message); /// @notice Thrown when attempting to send ETH directly to the contract error ETHNotAccepted(); /// @notice Thrown executing commands with an expired deadline error TransactionDeadlinePassed(); /// @notice Thrown executing commands with an expired deadline error LengthMismatch(); /// @notice Executes encoded commands along with provided inputs. Reverts if deadline has expired. /// @param commands A set of concatenated commands, each 1 byte in length /// @param inputs An array of byte strings containing abi encoded inputs for each command /// @param deadline The deadline by which the transaction must be executed function execute(bytes calldata commands, bytes[] calldata inputs, uint256 deadline) external payable; /// @notice Executes encoded commands along with provided inputs. /// @param commands A set of concatenated commands, each 1 byte in length /// @param inputs An array of byte strings containing abi encoded inputs for each command function execute(bytes calldata commands, bytes[] calldata inputs) external payable; }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.4; import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol'; /// @title Interface for WETH9 interface IWETH9 is IERC20 { /// @notice Deposit ether to get wrapped ether function deposit() external payable; /// @notice Withdraw wrapped ether to get ether function withdraw(uint256) external; }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.17; /// @title Commands /// @notice Command Flags used to decode commands library Commands { // Masks to extract certain bits of commands bytes1 internal constant FLAG_ALLOW_REVERT = 0x80; bytes1 internal constant COMMAND_TYPE_MASK = 0x1f; bytes1 internal constant NFT_TYPE_MASK = 0x10; bytes1 internal constant SUB_IF_BRANCH_MASK = 0x08; // Command Types. Maximum supported command at this moment is 0x1F. // Command Types where value<0x08, executed in the first nested-if block uint256 constant RESERVOIR_Buy = 0x00; uint256 constant RESERVOIR_Sell = 0x01; uint256 constant WRAP_ETH = 0x02; uint256 constant UNWRAP_WETH = 0x03; uint256 constant SWEEP = 0x04; uint256 constant TRANSFER = 0x05; uint256 constant PAY_PORTION = 0x06; uint256 constant COMMAND_PLACEHOLDER_0x07 = 0x07; // Command Types where 0x08<=value<=0x0f, executed in the second nested-if block uint256 constant SUDOSWAP_Buy = 0x08; uint256 constant SUDOSWAP_Sell = 0x09; uint256 constant EZSWAP_Buy = 0x0a; uint256 constant EZSWAP_Sell = 0x0b; uint256 constant SWEEP_ERC721 = 0x0c; uint256 constant SWEEP_ERC1155 = 0x0d; uint256 constant COMMAND_PLACEHOLDER_0x0e = 0x0e; uint256 constant COMMAND_PLACEHOLDER_0x0f = 0x0f; // Command Types where 0x10<=value<0x18, executed in the third nested-if block uint256 constant COMMAND_PLACEHOLDER_0x10 = 0x10; uint256 constant COMMAND_PLACEHOLDER_0x11 = 0x11; uint256 constant COMMAND_PLACEHOLDER_0x12 = 0x12; uint256 constant COMMAND_PLACEHOLDER_0x13 = 0x13; uint256 constant COMMAND_PLACEHOLDER_0x14 = 0x14; uint256 constant COMMAND_PLACEHOLDER_0x15 = 0x15; uint256 constant COMMAND_PLACEHOLDER_0x16 = 0x16; uint256 constant COMMAND_PLACEHOLDER_0x17 = 0x17; // Command Types where 0x18<=value<=0x1f, executed in the final nested-if block uint256 constant COMMAND_PLACEHOLDER_0x18 = 0x18; uint256 constant COMMAND_PLACEHOLDER_0x19 = 0x19; uint256 constant COMMAND_PLACEHOLDER_0x1a = 0x1a; uint256 constant COMMAND_PLACEHOLDER_0x1b = 0x1b; uint256 constant COMMAND_PLACEHOLDER_0x1c = 0x1c; uint256 constant COMMAND_PLACEHOLDER_0x1d = 0x1d; uint256 constant COMMAND_PLACEHOLDER_0x1e = 0x1e; uint256 constant COMMAND_PLACEHOLDER_0x1f = 0x1f; }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.17; import {IWETH9} from '../interfaces/IWETH9.sol'; /// @title Constant state /// @notice Constant state used by the Universal Router library Constants { /// @dev Used for identifying cases when this contract's balance of a token is to be used as an input /// This value is equivalent to 1<<255, i.e. a singular 1 in the most significant bit. uint256 internal constant CONTRACT_BALANCE = 0x8000000000000000000000000000000000000000000000000000000000000000; /// @dev Used for identifying cases when a v2 pair has already received input tokens uint256 internal constant ALREADY_PAID = 0; /// @dev Used as a flag for identifying the transfer of ETH instead of a token address internal constant ETH = address(0); /// @dev Used as a flag for identifying that msg.sender should be used, saves gas by sending more 0 bytes address internal constant MSG_SENDER = address(1); /// @dev Used as a flag for identifying address(this) should be used, saves gas by sending more 0 bytes address internal constant ADDRESS_THIS = address(2); }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.17; import {Constants} from '../libraries/Constants.sol'; /// @title Recipient Library /// @notice Calculates the recipient address for a command library Recipient { /// @notice Calculates the recipient address for a command /// @param recipient The recipient or recipient-flag for the command /// @return output The resultant recipient for the command function map(address recipient) internal view returns (address) { if (recipient == Constants.MSG_SENDER) { return msg.sender; } else if (recipient == Constants.ADDRESS_THIS) { return address(this); } else { return recipient; } } }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.17; import {ERC721} from "solmate/src/tokens/ERC721.sol"; import {ERC1155} from "solmate/src/tokens/ERC1155.sol"; /// @title HandleLSSVM contract /// @notice Handle sell NFT through LSSVM abstract contract HandleLSSVM { struct LSSVMSellNftStruct { address collection; uint256[] tokenIds; uint256 tokenStandards; } /// @notice sell NFT /// @param protocol EZSWAP or SUDOSWAP /// @param data encode data /// @param nftOwner if fail, transfer NFT back /// @param sellNfts data about NFT /// @return success /// @return output function handleLSSVMSell( address protocol, bytes memory data, address nftOwner, LSSVMSellNftStruct[] memory sellNfts ) internal returns (bool success, bytes memory output) { // transfer NFT to this address for (uint256 j = 0; j < sellNfts.length; ) { LSSVMSellNftStruct memory sellNft = sellNfts[j]; uint256[] memory tokenIds = sellNft.tokenIds; address token = sellNft.collection; uint256 tokenStandards = sellNft.tokenStandards; if (tokenStandards == 721) { for (uint256 i = 0; i < tokenIds.length; i++) { uint256 tokenId = tokenIds[i]; ERC721(token).safeTransferFrom( nftOwner, address(this), tokenId ); } ERC721(token).setApprovalForAll(protocol, true); } else { revert("HandleLSSVM:TokenStandard Error"); } unchecked { ++j; } } // call LSSVM router (success, output) = protocol.call(data); // if trade fail, transfer NFT back to user for (uint256 k = 0; k < sellNfts.length; ) { LSSVMSellNftStruct memory sellNft = sellNfts[k]; uint256[] memory tokenIds = sellNft.tokenIds; address token = sellNft.collection; uint256 tokenStandards = sellNft.tokenStandards; if (tokenStandards == 721) { for (uint256 i = 0; i < tokenIds.length; i++) { uint256 tokenId = tokenIds[i]; if (ERC721(token).ownerOf(tokenId) == address(this)) { ERC721(token).safeTransferFrom( address(this), nftOwner, tokenId ); } } } else { revert("HandleLSSVM:TokenStandard Error"); } unchecked { ++k; } } } }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.17; import {RouterImmutables} from "../base/RouterImmutables.sol"; import {ERC721} from "solmate/src/tokens/ERC721.sol"; import {ERC1155} from "solmate/src/tokens/ERC1155.sol"; abstract contract HandleReservoir is RouterImmutables { enum ReservoirOfferMarket { OPENSEA, LOOKSRARE, X2Y2 } struct ReservoirOfferStruct { ReservoirOfferMarket offerMarket; uint256 tokenStandard; address collection; uint256 tokenId; uint256 tokenAmount; bytes inputDate; uint offerAmount; } /// @notice look for the market /// @param offerMarket enum for market /// @return address of market function getOfferMarketAddress( ReservoirOfferMarket offerMarket ) internal view returns (address) { if (offerMarket == ReservoirOfferMarket.OPENSEA) { return SEAPORTMODULE; // SeaportModule } else if (offerMarket == ReservoirOfferMarket.LOOKSRARE) { return LOOKSRAREMODULE; // LooksRareModule } else if (offerMarket == ReservoirOfferMarket.X2Y2) { return X2Y2MODULE; // X2Y2Module } else { revert("HandleReservoir:OfferMarket Error"); } } /// @notice sell NFT /// @param reservoirOffers data about offer function handleReservoirSell( ReservoirOfferStruct[] memory reservoirOffers ) internal { for (uint256 i; i < reservoirOffers.length; ) { ReservoirOfferStruct memory reservoirOffer = reservoirOffers[i]; if (reservoirOffer.tokenStandard == 721) { uint256 beforeTransferBalance = WETH9.balanceOf(address(this)); ERC721(reservoirOffer.collection).safeTransferFrom( msg.sender, getOfferMarketAddress(reservoirOffer.offerMarket), reservoirOffer.tokenId, reservoirOffer.inputDate ); uint256 afterTransferBalance = WETH9.balanceOf(address(this)); require( afterTransferBalance - beforeTransferBalance >= reservoirOffer.offerAmount, "HandleReservoir:OfferAmount Error" ); } else if (reservoirOffer.tokenStandard == 1155) { uint256 beforeTransferBalance = WETH9.balanceOf(address(this)); ERC1155(reservoirOffer.collection).safeTransferFrom( msg.sender, getOfferMarketAddress(reservoirOffer.offerMarket), reservoirOffer.tokenId, reservoirOffer.tokenAmount, reservoirOffer.inputDate ); uint256 afterTransferBalance = WETH9.balanceOf(address(this)); require( afterTransferBalance - beforeTransferBalance >= reservoirOffer.offerAmount, "HandleReservoir:OfferAmount Error" ); } else { revert("HandleReservoir:TokenStandard Error"); } unchecked { ++i; } } } }
// SPDX-License-Identifier: GPL-3.0-or-later pragma solidity ^0.8.17; import {Constants} from '../libraries/Constants.sol'; import {RouterImmutables} from '../base/RouterImmutables.sol'; import {SafeTransferLib} from 'solmate/src/utils/SafeTransferLib.sol'; import {ERC20} from 'solmate/src/tokens/ERC20.sol'; import {ERC721} from 'solmate/src/tokens/ERC721.sol'; import {ERC1155} from 'solmate/src/tokens/ERC1155.sol'; /// @title Payments contract /// @notice Performs various operations around the payment of ETH and tokens abstract contract Payments is RouterImmutables { using SafeTransferLib for ERC20; using SafeTransferLib for address; error InsufficientToken(); error InsufficientETH(); error InvalidBips(); uint256 internal constant FEE_BIPS_BASE = 10_000; /// @notice Pays an amount of ETH or ERC20 to a recipient /// @param token The token to pay (can be ETH using Constants.ETH) /// @param recipient The address that will receive the payment /// @param value The amount to pay function pay(address token, address recipient, uint256 value) internal { if (token == Constants.ETH) { recipient.safeTransferETH(value); } else { if (value == Constants.CONTRACT_BALANCE) { value = ERC20(token).balanceOf(address(this)); } ERC20(token).safeTransfer(recipient, value); } } /// @notice Pays a proportion of the contract's ETH or ERC20 to a recipient /// @param token The token to pay (can be ETH using Constants.ETH) /// @param recipient The address that will receive payment /// @param bips Portion in bips of whole balance of the contract function payPortion(address token, address recipient, uint256 bips) internal { if (bips == 0 || bips > 10_000) revert InvalidBips(); if (token == Constants.ETH) { uint256 balance = address(this).balance; uint256 amount = (balance * bips) / FEE_BIPS_BASE; recipient.safeTransferETH(amount); } else { uint256 balance = ERC20(token).balanceOf(address(this)); uint256 amount = (balance * bips) / FEE_BIPS_BASE; // pay with tokens already in the contract (for the exact input multihop case) ERC20(token).safeTransfer(recipient, amount); } } /// @notice Sweeps all of the contract's ERC20 or ETH to an address /// @param token The token to sweep (can be ETH using Constants.ETH) /// @param recipient The address that will receive payment /// @param amountMinimum The minimum desired amount function sweep(address token, address recipient, uint256 amountMinimum) internal { uint256 balance; if (token == Constants.ETH) { balance = address(this).balance; if (balance < amountMinimum) revert InsufficientETH(); if (balance > 0) recipient.safeTransferETH(balance); } else { balance = ERC20(token).balanceOf(address(this)); if (balance < amountMinimum) revert InsufficientToken(); if (balance > 0) ERC20(token).safeTransfer(recipient, balance); } } /// @notice Sweeps an ERC721 to a recipient from the contract /// @param token The ERC721 token to sweep /// @param recipient The address that will receive payment /// @param id The ID of the ERC721 to sweep function sweepERC721(address token, address recipient, uint256 id) internal { ERC721(token).safeTransferFrom(address(this), recipient, id); } /// @notice Sweeps all of the contract's ERC1155 to an address /// @param token The ERC1155 token to sweep /// @param recipient The address that will receive payment /// @param id The ID of the ERC1155 to sweep /// @param amountMinimum The minimum desired amount function sweepERC1155(address token, address recipient, uint256 id, uint256 amountMinimum) internal { uint256 balance = ERC1155(token).balanceOf(address(this), id); if (balance < amountMinimum) revert InsufficientToken(); ERC1155(token).safeTransferFrom(address(this), recipient, id, balance, bytes('')); } /// @notice Wraps an amount of ETH into WETH /// @param recipient The recipient of the WETH /// @param amount The amount to wrap (can be CONTRACT_BALANCE) function wrapETH(address recipient, uint256 amount) internal { if (amount == Constants.CONTRACT_BALANCE) { amount = address(this).balance; } else if (amount > address(this).balance) { revert InsufficientETH(); } if (amount > 0) { WETH9.deposit{value: amount}(); WETH9.transfer(recipient, amount); } } /// @notice Unwraps all of the contract's WETH into ETH /// @param recipient The recipient of the ETH /// @param amountMinimum The minimum amount of ETH desired function unwrapWETH9(address recipient, uint256 amountMinimum) internal { uint256 value = WETH9.balanceOf(address(this)); if (value < amountMinimum) { revert InsufficientETH(); } if (value > 0) { WETH9.withdraw(value); recipient.safeTransferETH(value); } } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; /// @notice Minimalist and gas efficient standard ERC1155 implementation. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC1155.sol) abstract contract ERC1155 { /*////////////////////////////////////////////////////////////// EVENTS //////////////////////////////////////////////////////////////*/ event TransferSingle( address indexed operator, address indexed from, address indexed to, uint256 id, uint256 amount ); event TransferBatch( address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] amounts ); event ApprovalForAll(address indexed owner, address indexed operator, bool approved); event URI(string value, uint256 indexed id); /*////////////////////////////////////////////////////////////// ERC1155 STORAGE //////////////////////////////////////////////////////////////*/ mapping(address => mapping(uint256 => uint256)) public balanceOf; mapping(address => mapping(address => bool)) public isApprovedForAll; /*////////////////////////////////////////////////////////////// METADATA LOGIC //////////////////////////////////////////////////////////////*/ function uri(uint256 id) public view virtual returns (string memory); /*////////////////////////////////////////////////////////////// ERC1155 LOGIC //////////////////////////////////////////////////////////////*/ function setApprovalForAll(address operator, bool approved) public virtual { isApprovedForAll[msg.sender][operator] = approved; emit ApprovalForAll(msg.sender, operator, approved); } function safeTransferFrom( address from, address to, uint256 id, uint256 amount, bytes calldata data ) public virtual { require(msg.sender == from || isApprovedForAll[from][msg.sender], "NOT_AUTHORIZED"); balanceOf[from][id] -= amount; balanceOf[to][id] += amount; emit TransferSingle(msg.sender, from, to, id, amount); require( to.code.length == 0 ? to != address(0) : ERC1155TokenReceiver(to).onERC1155Received(msg.sender, from, id, amount, data) == ERC1155TokenReceiver.onERC1155Received.selector, "UNSAFE_RECIPIENT" ); } function safeBatchTransferFrom( address from, address to, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata data ) public virtual { require(ids.length == amounts.length, "LENGTH_MISMATCH"); require(msg.sender == from || isApprovedForAll[from][msg.sender], "NOT_AUTHORIZED"); // Storing these outside the loop saves ~15 gas per iteration. uint256 id; uint256 amount; for (uint256 i = 0; i < ids.length; ) { id = ids[i]; amount = amounts[i]; balanceOf[from][id] -= amount; balanceOf[to][id] += amount; // An array can't have a total length // larger than the max uint256 value. unchecked { ++i; } } emit TransferBatch(msg.sender, from, to, ids, amounts); require( to.code.length == 0 ? to != address(0) : ERC1155TokenReceiver(to).onERC1155BatchReceived(msg.sender, from, ids, amounts, data) == ERC1155TokenReceiver.onERC1155BatchReceived.selector, "UNSAFE_RECIPIENT" ); } function balanceOfBatch(address[] calldata owners, uint256[] calldata ids) public view virtual returns (uint256[] memory balances) { require(owners.length == ids.length, "LENGTH_MISMATCH"); balances = new uint256[](owners.length); // Unchecked because the only math done is incrementing // the array index counter which cannot possibly overflow. unchecked { for (uint256 i = 0; i < owners.length; ++i) { balances[i] = balanceOf[owners[i]][ids[i]]; } } } /*////////////////////////////////////////////////////////////// ERC165 LOGIC //////////////////////////////////////////////////////////////*/ function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) { return interfaceId == 0x01ffc9a7 || // ERC165 Interface ID for ERC165 interfaceId == 0xd9b67a26 || // ERC165 Interface ID for ERC1155 interfaceId == 0x0e89341c; // ERC165 Interface ID for ERC1155MetadataURI } /*////////////////////////////////////////////////////////////// INTERNAL MINT/BURN LOGIC //////////////////////////////////////////////////////////////*/ function _mint( address to, uint256 id, uint256 amount, bytes memory data ) internal virtual { balanceOf[to][id] += amount; emit TransferSingle(msg.sender, address(0), to, id, amount); require( to.code.length == 0 ? to != address(0) : ERC1155TokenReceiver(to).onERC1155Received(msg.sender, address(0), id, amount, data) == ERC1155TokenReceiver.onERC1155Received.selector, "UNSAFE_RECIPIENT" ); } function _batchMint( address to, uint256[] memory ids, uint256[] memory amounts, bytes memory data ) internal virtual { uint256 idsLength = ids.length; // Saves MLOADs. require(idsLength == amounts.length, "LENGTH_MISMATCH"); for (uint256 i = 0; i < idsLength; ) { balanceOf[to][ids[i]] += amounts[i]; // An array can't have a total length // larger than the max uint256 value. unchecked { ++i; } } emit TransferBatch(msg.sender, address(0), to, ids, amounts); require( to.code.length == 0 ? to != address(0) : ERC1155TokenReceiver(to).onERC1155BatchReceived(msg.sender, address(0), ids, amounts, data) == ERC1155TokenReceiver.onERC1155BatchReceived.selector, "UNSAFE_RECIPIENT" ); } function _batchBurn( address from, uint256[] memory ids, uint256[] memory amounts ) internal virtual { uint256 idsLength = ids.length; // Saves MLOADs. require(idsLength == amounts.length, "LENGTH_MISMATCH"); for (uint256 i = 0; i < idsLength; ) { balanceOf[from][ids[i]] -= amounts[i]; // An array can't have a total length // larger than the max uint256 value. unchecked { ++i; } } emit TransferBatch(msg.sender, from, address(0), ids, amounts); } function _burn( address from, uint256 id, uint256 amount ) internal virtual { balanceOf[from][id] -= amount; emit TransferSingle(msg.sender, from, address(0), id, amount); } } /// @notice A generic interface for a contract which properly accepts ERC1155 tokens. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC1155.sol) abstract contract ERC1155TokenReceiver { function onERC1155Received( address, address, uint256, uint256, bytes calldata ) external virtual returns (bytes4) { return ERC1155TokenReceiver.onERC1155Received.selector; } function onERC1155BatchReceived( address, address, uint256[] calldata, uint256[] calldata, bytes calldata ) external virtual returns (bytes4) { return ERC1155TokenReceiver.onERC1155BatchReceived.selector; } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; /// @notice Modern and gas efficient ERC20 + EIP-2612 implementation. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol) /// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol) /// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it. abstract contract ERC20 { /*////////////////////////////////////////////////////////////// EVENTS //////////////////////////////////////////////////////////////*/ event Transfer(address indexed from, address indexed to, uint256 amount); event Approval(address indexed owner, address indexed spender, uint256 amount); /*////////////////////////////////////////////////////////////// METADATA STORAGE //////////////////////////////////////////////////////////////*/ string public name; string public symbol; uint8 public immutable decimals; /*////////////////////////////////////////////////////////////// ERC20 STORAGE //////////////////////////////////////////////////////////////*/ uint256 public totalSupply; mapping(address => uint256) public balanceOf; mapping(address => mapping(address => uint256)) public allowance; /*////////////////////////////////////////////////////////////// EIP-2612 STORAGE //////////////////////////////////////////////////////////////*/ uint256 internal immutable INITIAL_CHAIN_ID; bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR; mapping(address => uint256) public nonces; /*////////////////////////////////////////////////////////////// CONSTRUCTOR //////////////////////////////////////////////////////////////*/ constructor( string memory _name, string memory _symbol, uint8 _decimals ) { name = _name; symbol = _symbol; decimals = _decimals; INITIAL_CHAIN_ID = block.chainid; INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator(); } /*////////////////////////////////////////////////////////////// ERC20 LOGIC //////////////////////////////////////////////////////////////*/ function approve(address spender, uint256 amount) public virtual returns (bool) { allowance[msg.sender][spender] = amount; emit Approval(msg.sender, spender, amount); return true; } function transfer(address to, uint256 amount) public virtual returns (bool) { balanceOf[msg.sender] -= amount; // Cannot overflow because the sum of all user // balances can't exceed the max uint256 value. unchecked { balanceOf[to] += amount; } emit Transfer(msg.sender, to, amount); return true; } function transferFrom( address from, address to, uint256 amount ) public virtual returns (bool) { uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals. if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount; balanceOf[from] -= amount; // Cannot overflow because the sum of all user // balances can't exceed the max uint256 value. unchecked { balanceOf[to] += amount; } emit Transfer(from, to, amount); return true; } /*////////////////////////////////////////////////////////////// EIP-2612 LOGIC //////////////////////////////////////////////////////////////*/ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) public virtual { require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED"); // Unchecked because the only math done is incrementing // the owner's nonce which cannot realistically overflow. unchecked { address recoveredAddress = ecrecover( keccak256( abi.encodePacked( "\x19\x01", DOMAIN_SEPARATOR(), keccak256( abi.encode( keccak256( "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)" ), owner, spender, value, nonces[owner]++, deadline ) ) ) ), v, r, s ); require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER"); allowance[recoveredAddress][spender] = value; } emit Approval(owner, spender, value); } function DOMAIN_SEPARATOR() public view virtual returns (bytes32) { return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator(); } function computeDomainSeparator() internal view virtual returns (bytes32) { return keccak256( abi.encode( keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"), keccak256(bytes(name)), keccak256("1"), block.chainid, address(this) ) ); } /*////////////////////////////////////////////////////////////// INTERNAL MINT/BURN LOGIC //////////////////////////////////////////////////////////////*/ function _mint(address to, uint256 amount) internal virtual { totalSupply += amount; // Cannot overflow because the sum of all user // balances can't exceed the max uint256 value. unchecked { balanceOf[to] += amount; } emit Transfer(address(0), to, amount); } function _burn(address from, uint256 amount) internal virtual { balanceOf[from] -= amount; // Cannot underflow because a user's balance // will never be larger than the total supply. unchecked { totalSupply -= amount; } emit Transfer(from, address(0), amount); } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; /// @notice Modern, minimalist, and gas efficient ERC-721 implementation. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC721.sol) abstract contract ERC721 { /*////////////////////////////////////////////////////////////// EVENTS //////////////////////////////////////////////////////////////*/ event Transfer(address indexed from, address indexed to, uint256 indexed id); event Approval(address indexed owner, address indexed spender, uint256 indexed id); event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /*////////////////////////////////////////////////////////////// METADATA STORAGE/LOGIC //////////////////////////////////////////////////////////////*/ string public name; string public symbol; function tokenURI(uint256 id) public view virtual returns (string memory); /*////////////////////////////////////////////////////////////// ERC721 BALANCE/OWNER STORAGE //////////////////////////////////////////////////////////////*/ mapping(uint256 => address) internal _ownerOf; mapping(address => uint256) internal _balanceOf; function ownerOf(uint256 id) public view virtual returns (address owner) { require((owner = _ownerOf[id]) != address(0), "NOT_MINTED"); } function balanceOf(address owner) public view virtual returns (uint256) { require(owner != address(0), "ZERO_ADDRESS"); return _balanceOf[owner]; } /*////////////////////////////////////////////////////////////// ERC721 APPROVAL STORAGE //////////////////////////////////////////////////////////////*/ mapping(uint256 => address) public getApproved; mapping(address => mapping(address => bool)) public isApprovedForAll; /*////////////////////////////////////////////////////////////// CONSTRUCTOR //////////////////////////////////////////////////////////////*/ constructor(string memory _name, string memory _symbol) { name = _name; symbol = _symbol; } /*////////////////////////////////////////////////////////////// ERC721 LOGIC //////////////////////////////////////////////////////////////*/ function approve(address spender, uint256 id) public virtual { address owner = _ownerOf[id]; require(msg.sender == owner || isApprovedForAll[owner][msg.sender], "NOT_AUTHORIZED"); getApproved[id] = spender; emit Approval(owner, spender, id); } function setApprovalForAll(address operator, bool approved) public virtual { isApprovedForAll[msg.sender][operator] = approved; emit ApprovalForAll(msg.sender, operator, approved); } function transferFrom( address from, address to, uint256 id ) public virtual { require(from == _ownerOf[id], "WRONG_FROM"); require(to != address(0), "INVALID_RECIPIENT"); require( msg.sender == from || isApprovedForAll[from][msg.sender] || msg.sender == getApproved[id], "NOT_AUTHORIZED" ); // Underflow of the sender's balance is impossible because we check for // ownership above and the recipient's balance can't realistically overflow. unchecked { _balanceOf[from]--; _balanceOf[to]++; } _ownerOf[id] = to; delete getApproved[id]; emit Transfer(from, to, id); } function safeTransferFrom( address from, address to, uint256 id ) public virtual { transferFrom(from, to, id); require( to.code.length == 0 || ERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, "") == ERC721TokenReceiver.onERC721Received.selector, "UNSAFE_RECIPIENT" ); } function safeTransferFrom( address from, address to, uint256 id, bytes calldata data ) public virtual { transferFrom(from, to, id); require( to.code.length == 0 || ERC721TokenReceiver(to).onERC721Received(msg.sender, from, id, data) == ERC721TokenReceiver.onERC721Received.selector, "UNSAFE_RECIPIENT" ); } /*////////////////////////////////////////////////////////////// ERC165 LOGIC //////////////////////////////////////////////////////////////*/ function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) { return interfaceId == 0x01ffc9a7 || // ERC165 Interface ID for ERC165 interfaceId == 0x80ac58cd || // ERC165 Interface ID for ERC721 interfaceId == 0x5b5e139f; // ERC165 Interface ID for ERC721Metadata } /*////////////////////////////////////////////////////////////// INTERNAL MINT/BURN LOGIC //////////////////////////////////////////////////////////////*/ function _mint(address to, uint256 id) internal virtual { require(to != address(0), "INVALID_RECIPIENT"); require(_ownerOf[id] == address(0), "ALREADY_MINTED"); // Counter overflow is incredibly unrealistic. unchecked { _balanceOf[to]++; } _ownerOf[id] = to; emit Transfer(address(0), to, id); } function _burn(uint256 id) internal virtual { address owner = _ownerOf[id]; require(owner != address(0), "NOT_MINTED"); // Ownership check above ensures no underflow. unchecked { _balanceOf[owner]--; } delete _ownerOf[id]; delete getApproved[id]; emit Transfer(owner, address(0), id); } /*////////////////////////////////////////////////////////////// INTERNAL SAFE MINT LOGIC //////////////////////////////////////////////////////////////*/ function _safeMint(address to, uint256 id) internal virtual { _mint(to, id); require( to.code.length == 0 || ERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, "") == ERC721TokenReceiver.onERC721Received.selector, "UNSAFE_RECIPIENT" ); } function _safeMint( address to, uint256 id, bytes memory data ) internal virtual { _mint(to, id); require( to.code.length == 0 || ERC721TokenReceiver(to).onERC721Received(msg.sender, address(0), id, data) == ERC721TokenReceiver.onERC721Received.selector, "UNSAFE_RECIPIENT" ); } } /// @notice A generic interface for a contract which properly accepts ERC721 tokens. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC721.sol) abstract contract ERC721TokenReceiver { function onERC721Received( address, address, uint256, bytes calldata ) external virtual returns (bytes4) { return ERC721TokenReceiver.onERC721Received.selector; } }
// SPDX-License-Identifier: AGPL-3.0-only pragma solidity >=0.8.0; import {ERC20} from "../tokens/ERC20.sol"; /// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values. /// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeTransferLib.sol) /// @dev Use with caution! Some functions in this library knowingly create dirty bits at the destination of the free memory pointer. /// @dev Note that none of the functions in this library check that a token has code at all! That responsibility is delegated to the caller. library SafeTransferLib { /*////////////////////////////////////////////////////////////// ETH OPERATIONS //////////////////////////////////////////////////////////////*/ function safeTransferETH(address to, uint256 amount) internal { bool success; assembly { // Transfer the ETH and store if it succeeded or not. success := call(gas(), to, amount, 0, 0, 0, 0) } require(success, "ETH_TRANSFER_FAILED"); } /*////////////////////////////////////////////////////////////// ERC20 OPERATIONS //////////////////////////////////////////////////////////////*/ function safeTransferFrom( ERC20 token, address from, address to, uint256 amount ) internal { bool success; assembly { // Get a pointer to some free memory. let freeMemoryPointer := mload(0x40) // Write the abi-encoded calldata into memory, beginning with the function selector. mstore(freeMemoryPointer, 0x23b872dd00000000000000000000000000000000000000000000000000000000) mstore(add(freeMemoryPointer, 4), from) // Append the "from" argument. mstore(add(freeMemoryPointer, 36), to) // Append the "to" argument. mstore(add(freeMemoryPointer, 68), amount) // Append the "amount" argument. success := and( // Set success to whether the call reverted, if not we check it either // returned exactly 1 (can't just be non-zero data), or had no return data. or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())), // We use 100 because the length of our calldata totals up like so: 4 + 32 * 3. // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space. // Counterintuitively, this call must be positioned second to the or() call in the // surrounding and() call or else returndatasize() will be zero during the computation. call(gas(), token, 0, freeMemoryPointer, 100, 0, 32) ) } require(success, "TRANSFER_FROM_FAILED"); } function safeTransfer( ERC20 token, address to, uint256 amount ) internal { bool success; assembly { // Get a pointer to some free memory. let freeMemoryPointer := mload(0x40) // Write the abi-encoded calldata into memory, beginning with the function selector. mstore(freeMemoryPointer, 0xa9059cbb00000000000000000000000000000000000000000000000000000000) mstore(add(freeMemoryPointer, 4), to) // Append the "to" argument. mstore(add(freeMemoryPointer, 36), amount) // Append the "amount" argument. success := and( // Set success to whether the call reverted, if not we check it either // returned exactly 1 (can't just be non-zero data), or had no return data. or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())), // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2. // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space. // Counterintuitively, this call must be positioned second to the or() call in the // surrounding and() call or else returndatasize() will be zero during the computation. call(gas(), token, 0, freeMemoryPointer, 68, 0, 32) ) } require(success, "TRANSFER_FAILED"); } function safeApprove( ERC20 token, address to, uint256 amount ) internal { bool success; assembly { // Get a pointer to some free memory. let freeMemoryPointer := mload(0x40) // Write the abi-encoded calldata into memory, beginning with the function selector. mstore(freeMemoryPointer, 0x095ea7b300000000000000000000000000000000000000000000000000000000) mstore(add(freeMemoryPointer, 4), to) // Append the "to" argument. mstore(add(freeMemoryPointer, 36), amount) // Append the "amount" argument. success := and( // Set success to whether the call reverted, if not we check it either // returned exactly 1 (can't just be non-zero data), or had no return data. or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())), // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2. // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space. // Counterintuitively, this call must be positioned second to the or() call in the // surrounding and() call or else returndatasize() will be zero during the computation. call(gas(), token, 0, freeMemoryPointer, 68, 0, 32) ) } require(success, "APPROVE_FAILED"); } }
{ "optimizer": { "enabled": false, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"components":[{"internalType":"address","name":"weth9","type":"address"},{"internalType":"address","name":"reservoir","type":"address"},{"internalType":"address","name":"seaportModule","type":"address"},{"internalType":"address","name":"looksRareModule","type":"address"},{"internalType":"address","name":"x2y2Module","type":"address"},{"internalType":"address","name":"sudoswap","type":"address"},{"internalType":"address","name":"ezswap","type":"address"}],"internalType":"struct RouterParameters","name":"params","type":"tuple"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ETHNotAccepted","type":"error"},{"inputs":[{"internalType":"uint256","name":"commandIndex","type":"uint256"},{"internalType":"bytes","name":"message","type":"bytes"}],"name":"ExecutionFailed","type":"error"},{"inputs":[],"name":"InsufficientETH","type":"error"},{"inputs":[],"name":"InsufficientToken","type":"error"},{"inputs":[],"name":"InvalidBips","type":"error"},{"inputs":[{"internalType":"uint256","name":"commandType","type":"uint256"}],"name":"InvalidCommandType","type":"error"},{"inputs":[],"name":"InvalidOwnerERC1155","type":"error"},{"inputs":[],"name":"InvalidOwnerERC721","type":"error"},{"inputs":[],"name":"LengthMismatch","type":"error"},{"inputs":[],"name":"TransactionDeadlinePassed","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"inputs":[{"internalType":"bytes","name":"commands","type":"bytes"},{"internalType":"bytes[]","name":"inputs","type":"bytes[]"}],"name":"execute","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes","name":"commands","type":"bytes"},{"internalType":"bytes[]","name":"inputs","type":"bytes[]"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"execute","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC1155BatchReceived","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC1155Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"pure","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":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
6101606040523480156200001257600080fd5b5060405162003ede38038062003ede83398181016040528101906200003891906200050f565b80806000015173ffffffffffffffffffffffffffffffffffffffff1660808173ffffffffffffffffffffffffffffffffffffffff1681525050806020015173ffffffffffffffffffffffffffffffffffffffff1660a08173ffffffffffffffffffffffffffffffffffffffff1681525050806040015173ffffffffffffffffffffffffffffffffffffffff1660c08173ffffffffffffffffffffffffffffffffffffffff1681525050806060015173ffffffffffffffffffffffffffffffffffffffff1660e08173ffffffffffffffffffffffffffffffffffffffff1681525050806080015173ffffffffffffffffffffffffffffffffffffffff166101008173ffffffffffffffffffffffffffffffffffffffff16815250508060a0015173ffffffffffffffffffffffffffffffffffffffff166101208173ffffffffffffffffffffffffffffffffffffffff16815250508060c0015173ffffffffffffffffffffffffffffffffffffffff166101408173ffffffffffffffffffffffffffffffffffffffff16815250505060008060019054906101000a900460ff16159050808015620001f75750600160008054906101000a900460ff1660ff16105b8062000233575062000214306200031760201b620004cf1760201c565b158015620002325750600160008054906101000a900460ff1660ff16145b5b62000275576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200026c90620005c8565b60405180910390fd5b60016000806101000a81548160ff021916908360ff1602179055508015620002b3576001600060016101000a81548160ff0219169083151502179055505b80156200030f5760008060016101000a81548160ff0219169083151502179055507f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb3847402498600160405162000306919062000644565b60405180910390a15b505062000661565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b6000604051905090565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b62000399826200034e565b810181811067ffffffffffffffff82111715620003bb57620003ba6200035f565b5b80604052505050565b6000620003d06200033a565b9050620003de82826200038e565b919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006200041082620003e3565b9050919050565b620004228162000403565b81146200042e57600080fd5b50565b600081519050620004428162000417565b92915050565b600060e0828403121562000461576200046062000349565b5b6200046d60e0620003c4565b905060006200047f8482850162000431565b6000830152506020620004958482850162000431565b6020830152506040620004ab8482850162000431565b6040830152506060620004c18482850162000431565b6060830152506080620004d78482850162000431565b60808301525060a0620004ed8482850162000431565b60a08301525060c0620005038482850162000431565b60c08301525092915050565b600060e0828403121562000528576200052762000344565b5b6000620005388482850162000448565b91505092915050565b600082825260208201905092915050565b7f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160008201527f647920696e697469616c697a6564000000000000000000000000000000000000602082015250565b6000620005b0602e8362000541565b9150620005bd8262000552565b604082019050919050565b60006020820190508181036000830152620005e381620005a1565b9050919050565b6000819050919050565b600060ff82169050919050565b6000819050919050565b60006200062c620006266200062084620005ea565b62000601565b620005f4565b9050919050565b6200063e816200060b565b82525050565b60006020820190506200065b600083018462000633565b92915050565b60805160a05160c05160e0516101005161012051610140516137e3620006fb600039600081816109960152610a58015260008181610878015261093a0152600061201601526000611fc301526000611f6f01526000610591015260008181610c9b01528181610dc201528181610ec601528181610ff30152818161122a015281816112ab01528181611351015261143001526137e36000f3fe6080604052600436106100595760003560e01c806301ffc9a714610065578063150b7a02146100a257806324856bc3146100df5780633593564c146100fb578063bc197c8114610117578063f23a6e611461015457610060565b3661006057005b600080fd5b34801561007157600080fd5b5061008c600480360381019061008791906121d3565b610191565b604051610099919061221b565b60405180910390f35b3480156100ae57600080fd5b506100c960048036038101906100c4919061232f565b6102cb565b6040516100d691906123c6565b60405180910390f35b6100f960048036038101906100f49190612437565b6102e0565b005b610115600480360381019061011091906124b8565b610452565b005b34801561012357600080fd5b5061013e600480360381019061013991906125a3565b6104a1565b60405161014b91906123c6565b60405180910390f35b34801561016057600080fd5b5061017b6004803603810190610176919061267f565b6104b9565b60405161018891906123c6565b60405180910390f35b60007f4e2312e0000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916148061025c57507f150b7a02000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b806102c457507f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b9050919050565b600063150b7a0260e01b905095945050505050565b6102e86104f2565b600060606000868690509050808585905014610330576040517fff633a3800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b818110156104405760008888838181106103505761034f612719565b5b9050013560f81c60f81b9050600087878481811061037157610370612719565b5b90506020028101906103839190612757565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505090506103d28282610541565b8096508197505050851580156103ed57506103ec82610c1f565b5b156104315782856040517f2c4029e9000000000000000000000000000000000000000000000000000000008152600401610428929190612859565b60405180910390fd5b82806001019350505050610333565b5050505061044c610c56565b50505050565b808042111561048d576040517f5bf6f91600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610499868686866102e0565b505050505050565b600063bc197c8160e01b905098975050505050505050565b600063f23a6e6160e01b90509695505050505050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b600260015403610537576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161052e906128e6565b60405180910390fd5b6002600181905550565b600060606000601f60f81b851660f81c60ff169050600192506010811015610bda5760088110156108535760008103610627576000808580602001905181019061058b9190612a3c565b915091507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1682826040516105d59190612ad4565b60006040518083038185875af1925050503d8060008114610612576040519150601f19603f3d011682016040523d82523d6000602084013e610617565b606091505b508095508196505050505061084e565b60018103610656576000848060200190518101906106459190612ce0565b905061065081610c5f565b5061084d565b600281036106a857600080858060200190518101906106759190612d67565b915091506106a161069b8373ffffffffffffffffffffffffffffffffffffffff16611132565b826111b5565b505061084c565b600381036106fa57600080858060200190518101906106c79190612d67565b915091506106f36106ed8373ffffffffffffffffffffffffffffffffffffffff16611132565b8261134d565b505061084b565b600481036107525760008060008680602001905181019061071b9190612da7565b92509250925061074a836107448473ffffffffffffffffffffffffffffffffffffffff16611132565b836114e8565b50505061084a565b600581036107aa576000806000868060200190518101906107739190612da7565b9250925092506107a28361079c8473ffffffffffffffffffffffffffffffffffffffff16611132565b83611684565b505050610849565b60068103610802576000806000868060200190518101906107cb9190612da7565b9250925092506107fa836107f48473ffffffffffffffffffffffffffffffffffffffff16611132565b836117bb565b505050610848565b6007810361084757806040517fd76a1e9e00000000000000000000000000000000000000000000000000000000815260040161083e9190612dfa565b60405180910390fd5b5b5b5b5b5b5b5b610bd5565b6008810361090e57600080858060200190518101906108729190612a3c565b915091507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1682826040516108bc9190612ad4565b60006040518083038185875af1925050503d80600081146108f9576040519150601f19603f3d011682016040523d82523d6000602084013e6108fe565b606091505b5080955081965050505050610bd4565b600981036109715760008060008680602001905181019061092f9190613039565b9250925092506109617f0000000000000000000000000000000000000000000000000000000000000000848484611956565b8096508197505050505050610bd3565b600a8103610a2c57600080858060200190518101906109909190612a3c565b915091507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1682826040516109da9190612ad4565b60006040518083038185875af1925050503d8060008114610a17576040519150601f19603f3d011682016040523d82523d6000602084013e610a1c565b606091505b5080955081965050505050610bd2565b600b8103610a8f57600080600086806020019051810190610a4d9190613039565b925092509250610a7f7f0000000000000000000000000000000000000000000000000000000000000000848484611956565b8096508197505050505050610bd1565b600c8103610ae757600080600086806020019051810190610ab09190612da7565b925092509250610adf83610ad98473ffffffffffffffffffffffffffffffffffffffff16611132565b83611d8a565b505050610bd0565b600d8103610b445760008060008087806020019051810190610b0991906130c4565b9350935093509350610b3b84610b348573ffffffffffffffffffffffffffffffffffffffff16611132565b8484611dfe565b50505050610bcf565b600e8103610b8957806040517fd76a1e9e000000000000000000000000000000000000000000000000000000008152600401610b809190612dfa565b60405180910390fd5b600f8103610bce57806040517fd76a1e9e000000000000000000000000000000000000000000000000000000008152600401610bc59190612dfa565b60405180910390fd5b5b5b5b5b5b5b5b610c17565b806040517fd76a1e9e000000000000000000000000000000000000000000000000000000008152600401610c0e9190612dfa565b60405180910390fd5b509250929050565b60008060f81b608060f81b83167effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b60018081905550565b60005b815181101561112e576000828281518110610c8057610c7f612719565b5b602002602001015190506102d1816020015103610eb55760007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401610cf2919061313a565b602060405180830381865afa158015610d0f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d339190613155565b9050816040015173ffffffffffffffffffffffffffffffffffffffff1663b88d4fde33610d638560000151611f40565b85606001518660a001516040518563ffffffff1660e01b8152600401610d8c9493929190613182565b600060405180830381600087803b158015610da657600080fd5b505af1158015610dba573d6000803e3d6000fd5b5050505060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401610e19919061313a565b602060405180830381865afa158015610e36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e5a9190613155565b90508260c001518282610e6d91906131fd565b1015610eae576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ea5906132a3565b60405180910390fd5b5050611122565b6104838160200151036110e65760007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401610f1d919061313a565b602060405180830381865afa158015610f3a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f5e9190613155565b9050816040015173ffffffffffffffffffffffffffffffffffffffff1663f242432a33610f8e8560000151611f40565b856060015186608001518760a001516040518663ffffffff1660e01b8152600401610fbd9594939291906132c3565b600060405180830381600087803b158015610fd757600080fd5b505af1158015610feb573d6000803e3d6000fd5b5050505060007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b815260040161104a919061313a565b602060405180830381865afa158015611067573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061108b9190613155565b90508260c00151828261109e91906131fd565b10156110df576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110d6906132a3565b60405180910390fd5b5050611121565b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111189061338f565b60405180910390fd5b5b81600101915050610c62565b5050565b6000600173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611170573390506111b0565b600273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036111ac573090506111b0565b8190505b919050565b7f800000000000000000000000000000000000000000000000000000000000000081036111e45747905061121f565b4781111561121e576040517f6a12f10400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5b6000811115611349577f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b15801561129057600080fd5b505af11580156112a4573d6000803e3d6000fd5b50505050507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff1663a9059cbb83836040518363ffffffff1660e01b81526004016113049291906133af565b6020604051808303816000875af1158015611323573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113479190613404565b505b5050565b60007f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016113a8919061313a565b602060405180830381865afa1580156113c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113e99190613155565b905081811015611425576040517f6a12f10400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008111156114e3577f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16632e1a7d4d826040518263ffffffff1660e01b81526004016114879190612dfa565b600060405180830381600087803b1580156114a157600080fd5b505af11580156114b5573d6000803e3d6000fd5b505050506114e2818473ffffffffffffffffffffffffffffffffffffffff1661207c90919063ffffffff16565b5b505050565b60008073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603611592574790508181101561155a576040517f6a12f10400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600081111561158d5761158c818473ffffffffffffffffffffffffffffffffffffffff1661207c90919063ffffffff16565b5b61167e565b8373ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016115cb919061313a565b602060405180830381865afa1580156115e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061160c9190613155565b905081811015611648576040517f675cae3800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600081111561167d5761167c83828673ffffffffffffffffffffffffffffffffffffffff166120cf9092919063ffffffff16565b5b5b50505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036116e6576116e1818373ffffffffffffffffffffffffffffffffffffffff1661207c90919063ffffffff16565b6117b6565b7f8000000000000000000000000000000000000000000000000000000000000000810361178a578273ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401611746919061313a565b602060405180830381865afa158015611763573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117879190613155565b90505b6117b582828573ffffffffffffffffffffffffffffffffffffffff166120cf9092919063ffffffff16565b5b505050565b60008114806117cb575061271081115b15611802576040517fdeaa01e600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036118885760004790506000612710838361184c9190613431565b61185691906134a2565b9050611881818573ffffffffffffffffffffffffffffffffffffffff1661207c90919063ffffffff16565b5050611951565b60008373ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016118c3919061313a565b602060405180830381865afa1580156118e0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119049190613155565b9050600061271083836119179190613431565b61192191906134a2565b905061194e84828773ffffffffffffffffffffffffffffffffffffffff166120cf9092919063ffffffff16565b50505b505050565b6000606060005b8351811015611b1557600084828151811061197b5761197a612719565b5b602002602001015190506000816020015190506000826000015190506000836040015190506102d18103611acb5760005b8351811015611a575760008482815181106119ca576119c9612719565b5b602002602001015190508373ffffffffffffffffffffffffffffffffffffffff166342842e0e8c30846040518463ffffffff1660e01b8152600401611a11939291906134d3565b600060405180830381600087803b158015611a2b57600080fd5b505af1158015611a3f573d6000803e3d6000fd5b50505050508080611a4f9061350a565b9150506119ac565b508173ffffffffffffffffffffffffffffffffffffffff1663a22cb4658c60016040518363ffffffff1660e01b8152600401611a94929190613552565b600060405180830381600087803b158015611aae57600080fd5b505af1158015611ac2573d6000803e3d6000fd5b50505050611b06565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611afd906135c7565b60405180910390fd5b8460010194505050505061195d565b508573ffffffffffffffffffffffffffffffffffffffff1685604051611b3b9190612ad4565b6000604051808303816000865af19150503d8060008114611b78576040519150601f19603f3d011682016040523d82523d6000602084013e611b7d565b606091505b50809250819350505060005b8351811015611d80576000848281518110611ba757611ba6612719565b5b602002602001015190506000816020015190506000826000015190506000836040015190506102d18103611d365760005b8351811015611d30576000848281518110611bf657611bf5612719565b5b602002602001015190503073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16636352211e836040518263ffffffff1660e01b8152600401611c509190612dfa565b602060405180830381865afa158015611c6d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c9191906135e7565b73ffffffffffffffffffffffffffffffffffffffff1603611d1c578373ffffffffffffffffffffffffffffffffffffffff166342842e0e308d846040518463ffffffff1660e01b8152600401611ce9939291906134d3565b600060405180830381600087803b158015611d0357600080fd5b505af1158015611d17573d6000803e3d6000fd5b505050505b508080611d289061350a565b915050611bd8565b50611d71565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611d68906135c7565b60405180910390fd5b84600101945050505050611b89565b5094509492505050565b8273ffffffffffffffffffffffffffffffffffffffff166342842e0e3084846040518463ffffffff1660e01b8152600401611dc7939291906134d3565b600060405180830381600087803b158015611de157600080fd5b505af1158015611df5573d6000803e3d6000fd5b50505050505050565b60008473ffffffffffffffffffffffffffffffffffffffff1662fdd58e30856040518363ffffffff1660e01b8152600401611e3a9291906133af565b602060405180830381865afa158015611e57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e7b9190613155565b905081811015611eb7576040517f675cae3800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8473ffffffffffffffffffffffffffffffffffffffff1663f242432a30868685604051806020016040528060008152506040518663ffffffff1660e01b8152600401611f079594939291906132c3565b600060405180830381600087803b158015611f2157600080fd5b505af1158015611f35573d6000803e3d6000fd5b505050505050505050565b6000806002811115611f5557611f54613614565b5b826002811115611f6857611f67613614565b5b03611f95577f00000000000000000000000000000000000000000000000000000000000000009050612077565b60016002811115611fa957611fa8613614565b5b826002811115611fbc57611fbb613614565b5b03611fe9577f00000000000000000000000000000000000000000000000000000000000000009050612077565b600280811115611ffc57611ffb613614565b5b82600281111561200f5761200e613614565b5b0361203c577f00000000000000000000000000000000000000000000000000000000000000009050612077565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161206e906136b5565b60405180910390fd5b919050565b600080600080600085875af19050806120ca576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120c190613721565b60405180910390fd5b505050565b60006040517fa9059cbb000000000000000000000000000000000000000000000000000000008152836004820152826024820152602060006044836000895af13d15601f3d1160016000511416171691505080612161576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121589061378d565b60405180910390fd5b50505050565b6000604051905090565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b6121b08161217b565b81146121bb57600080fd5b50565b6000813590506121cd816121a7565b92915050565b6000602082840312156121e9576121e8612171565b5b60006121f7848285016121be565b91505092915050565b60008115159050919050565b61221581612200565b82525050565b6000602082019050612230600083018461220c565b92915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061226182612236565b9050919050565b61227181612256565b811461227c57600080fd5b50565b60008135905061228e81612268565b92915050565b6000819050919050565b6122a781612294565b81146122b257600080fd5b50565b6000813590506122c48161229e565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f8401126122ef576122ee6122ca565b5b8235905067ffffffffffffffff81111561230c5761230b6122cf565b5b602083019150836001820283011115612328576123276122d4565b5b9250929050565b60008060008060006080868803121561234b5761234a612171565b5b60006123598882890161227f565b955050602061236a8882890161227f565b945050604061237b888289016122b5565b935050606086013567ffffffffffffffff81111561239c5761239b612176565b5b6123a8888289016122d9565b92509250509295509295909350565b6123c08161217b565b82525050565b60006020820190506123db60008301846123b7565b92915050565b60008083601f8401126123f7576123f66122ca565b5b8235905067ffffffffffffffff811115612414576124136122cf565b5b6020830191508360208202830111156124305761242f6122d4565b5b9250929050565b6000806000806040858703121561245157612450612171565b5b600085013567ffffffffffffffff81111561246f5761246e612176565b5b61247b878288016122d9565b9450945050602085013567ffffffffffffffff81111561249e5761249d612176565b5b6124aa878288016123e1565b925092505092959194509250565b6000806000806000606086880312156124d4576124d3612171565b5b600086013567ffffffffffffffff8111156124f2576124f1612176565b5b6124fe888289016122d9565b9550955050602086013567ffffffffffffffff81111561252157612520612176565b5b61252d888289016123e1565b93509350506040612540888289016122b5565b9150509295509295909350565b60008083601f840112612563576125626122ca565b5b8235905067ffffffffffffffff8111156125805761257f6122cf565b5b60208301915083602082028301111561259c5761259b6122d4565b5b9250929050565b60008060008060008060008060a0898b0312156125c3576125c2612171565b5b60006125d18b828c0161227f565b98505060206125e28b828c0161227f565b975050604089013567ffffffffffffffff81111561260357612602612176565b5b61260f8b828c0161254d565b9650965050606089013567ffffffffffffffff81111561263257612631612176565b5b61263e8b828c0161254d565b9450945050608089013567ffffffffffffffff81111561266157612660612176565b5b61266d8b828c016122d9565b92509250509295985092959890939650565b60008060008060008060a0878903121561269c5761269b612171565b5b60006126aa89828a0161227f565b96505060206126bb89828a0161227f565b95505060406126cc89828a016122b5565b94505060606126dd89828a016122b5565b935050608087013567ffffffffffffffff8111156126fe576126fd612176565b5b61270a89828a016122d9565b92509250509295509295509295565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600080fd5b600080fd5b600080fd5b6000808335600160200384360303811261277457612773612748565b5b80840192508235915067ffffffffffffffff8211156127965761279561274d565b5b6020830192506001820236038313156127b2576127b1612752565b5b509250929050565b6127c381612294565b82525050565b600081519050919050565b600082825260208201905092915050565b60005b838110156128035780820151818401526020810190506127e8565b60008484015250505050565b6000601f19601f8301169050919050565b600061282b826127c9565b61283581856127d4565b93506128458185602086016127e5565b61284e8161280f565b840191505092915050565b600060408201905061286e60008301856127ba565b81810360208301526128808184612820565b90509392505050565b600082825260208201905092915050565b7f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00600082015250565b60006128d0601f83612889565b91506128db8261289a565b602082019050919050565b600060208201905081810360008301526128ff816128c3565b9050919050565b6000815190506129158161229e565b92915050565b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6129588261280f565b810181811067ffffffffffffffff8211171561297757612976612920565b5b80604052505050565b600061298a612167565b9050612996828261294f565b919050565b600067ffffffffffffffff8211156129b6576129b5612920565b5b6129bf8261280f565b9050602081019050919050565b60006129df6129da8461299b565b612980565b9050828152602081018484840111156129fb576129fa61291b565b5b612a068482856127e5565b509392505050565b600082601f830112612a2357612a226122ca565b5b8151612a338482602086016129cc565b91505092915050565b60008060408385031215612a5357612a52612171565b5b6000612a6185828601612906565b925050602083015167ffffffffffffffff811115612a8257612a81612176565b5b612a8e85828601612a0e565b9150509250929050565b600081905092915050565b6000612aae826127c9565b612ab88185612a98565b9350612ac88185602086016127e5565b80840191505092915050565b6000612ae08284612aa3565b915081905092915050565b600067ffffffffffffffff821115612b0657612b05612920565b5b602082029050602081019050919050565b600080fd5b600080fd5b60038110612b2e57600080fd5b50565b600081519050612b4081612b21565b92915050565b600081519050612b5581612268565b92915050565b600060e08284031215612b7157612b70612b17565b5b612b7b60e0612980565b90506000612b8b84828501612b31565b6000830152506020612b9f84828501612906565b6020830152506040612bb384828501612b46565b6040830152506060612bc784828501612906565b6060830152506080612bdb84828501612906565b60808301525060a082015167ffffffffffffffff811115612bff57612bfe612b1c565b5b612c0b84828501612a0e565b60a08301525060c0612c1f84828501612906565b60c08301525092915050565b6000612c3e612c3984612aeb565b612980565b90508083825260208201905060208402830185811115612c6157612c606122d4565b5b835b81811015612ca857805167ffffffffffffffff811115612c8657612c856122ca565b5b808601612c938982612b5b565b85526020850194505050602081019050612c63565b5050509392505050565b600082601f830112612cc757612cc66122ca565b5b8151612cd7848260208601612c2b565b91505092915050565b600060208284031215612cf657612cf5612171565b5b600082015167ffffffffffffffff811115612d1457612d13612176565b5b612d2084828501612cb2565b91505092915050565b6000612d3482612236565b9050919050565b612d4481612d29565b8114612d4f57600080fd5b50565b600081519050612d6181612d3b565b92915050565b60008060408385031215612d7e57612d7d612171565b5b6000612d8c85828601612d52565b9250506020612d9d85828601612906565b9150509250929050565b600080600060608486031215612dc057612dbf612171565b5b6000612dce86828701612d52565b9350506020612ddf86828701612d52565b9250506040612df086828701612906565b9150509250925092565b6000602082019050612e0f60008301846127ba565b92915050565b600067ffffffffffffffff821115612e3057612e2f612920565b5b602082029050602081019050919050565b600067ffffffffffffffff821115612e5c57612e5b612920565b5b602082029050602081019050919050565b6000612e80612e7b84612e41565b612980565b90508083825260208201905060208402830185811115612ea357612ea26122d4565b5b835b81811015612ecc5780612eb88882612906565b845260208401935050602081019050612ea5565b5050509392505050565b600082601f830112612eeb57612eea6122ca565b5b8151612efb848260208601612e6d565b91505092915050565b600060608284031215612f1a57612f19612b17565b5b612f246060612980565b90506000612f3484828501612b46565b600083015250602082015167ffffffffffffffff811115612f5857612f57612b1c565b5b612f6484828501612ed6565b6020830152506040612f7884828501612906565b60408301525092915050565b6000612f97612f9284612e15565b612980565b90508083825260208201905060208402830185811115612fba57612fb96122d4565b5b835b8181101561300157805167ffffffffffffffff811115612fdf57612fde6122ca565b5b808601612fec8982612f04565b85526020850194505050602081019050612fbc565b5050509392505050565b600082601f8301126130205761301f6122ca565b5b8151613030848260208601612f84565b91505092915050565b60008060006060848603121561305257613051612171565b5b600084015167ffffffffffffffff8111156130705761306f612176565b5b61307c86828701612a0e565b935050602061308d86828701612d52565b925050604084015167ffffffffffffffff8111156130ae576130ad612176565b5b6130ba8682870161300b565b9150509250925092565b600080600080608085870312156130de576130dd612171565b5b60006130ec87828801612d52565b94505060206130fd87828801612d52565b935050604061310e87828801612906565b925050606061311f87828801612906565b91505092959194509250565b61313481612256565b82525050565b600060208201905061314f600083018461312b565b92915050565b60006020828403121561316b5761316a612171565b5b600061317984828501612906565b91505092915050565b6000608082019050613197600083018761312b565b6131a4602083018661312b565b6131b160408301856127ba565b81810360608301526131c38184612820565b905095945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061320882612294565b915061321383612294565b925082820390508181111561322b5761322a6131ce565b5b92915050565b7f48616e646c655265736572766f69723a4f66666572416d6f756e74204572726f60008201527f7200000000000000000000000000000000000000000000000000000000000000602082015250565b600061328d602183612889565b915061329882613231565b604082019050919050565b600060208201905081810360008301526132bc81613280565b9050919050565b600060a0820190506132d8600083018861312b565b6132e5602083018761312b565b6132f260408301866127ba565b6132ff60608301856127ba565b81810360808301526133118184612820565b90509695505050505050565b7f48616e646c655265736572766f69723a546f6b656e5374616e6461726420457260008201527f726f720000000000000000000000000000000000000000000000000000000000602082015250565b6000613379602383612889565b91506133848261331d565b604082019050919050565b600060208201905081810360008301526133a88161336c565b9050919050565b60006040820190506133c4600083018561312b565b6133d160208301846127ba565b9392505050565b6133e181612200565b81146133ec57600080fd5b50565b6000815190506133fe816133d8565b92915050565b60006020828403121561341a57613419612171565b5b6000613428848285016133ef565b91505092915050565b600061343c82612294565b915061344783612294565b925082820261345581612294565b9150828204841483151761346c5761346b6131ce565b5b5092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60006134ad82612294565b91506134b883612294565b9250826134c8576134c7613473565b5b828204905092915050565b60006060820190506134e8600083018661312b565b6134f5602083018561312b565b61350260408301846127ba565b949350505050565b600061351582612294565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203613547576135466131ce565b5b600182019050919050565b6000604082019050613567600083018561312b565b613574602083018461220c565b9392505050565b7f48616e646c654c5353564d3a546f6b656e5374616e64617264204572726f7200600082015250565b60006135b1601f83612889565b91506135bc8261357b565b602082019050919050565b600060208201905081810360008301526135e0816135a4565b9050919050565b6000602082840312156135fd576135fc612171565b5b600061360b84828501612b46565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b7f48616e646c655265736572766f69723a4f666665724d61726b6574204572726f60008201527f7200000000000000000000000000000000000000000000000000000000000000602082015250565b600061369f602183612889565b91506136aa82613643565b604082019050919050565b600060208201905081810360008301526136ce81613692565b9050919050565b7f4554485f5452414e534645525f4641494c454400000000000000000000000000600082015250565b600061370b601383612889565b9150613716826136d5565b602082019050919050565b6000602082019050818103600083015261373a816136fe565b9050919050565b7f5452414e534645525f4641494c45440000000000000000000000000000000000600082015250565b6000613777600f83612889565b915061378282613741565b602082019050919050565b600060208201905081810360008301526137a68161376a565b905091905056fea26469706673582212209cca99d0e0d64a4675dcad5b003c1dbd84e313e50da7da0da744ee246748d6ff64736f6c63430008110033000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000178a86d36d89c7fdebea90b739605da7b131ff6a0000000000000000000000003729014ef28f01b3ddcf7f980d925e0b71b1f847000000000000000000000000385df8cbc196f5f780367f3cdc96af072a916f7e000000000000000000000000613d3c588f6b8f89302b463f8f19f7241b2857e20000000000000000000000002b2e8cda09bba9660dca5cb6233787738ad68329000000000000000000000000a63ec144d070a1bf19a7577c88c580e7de92e0fc
Deployed Bytecode
0x6080604052600436106100595760003560e01c806301ffc9a714610065578063150b7a02146100a257806324856bc3146100df5780633593564c146100fb578063bc197c8114610117578063f23a6e611461015457610060565b3661006057005b600080fd5b34801561007157600080fd5b5061008c600480360381019061008791906121d3565b610191565b604051610099919061221b565b60405180910390f35b3480156100ae57600080fd5b506100c960048036038101906100c4919061232f565b6102cb565b6040516100d691906123c6565b60405180910390f35b6100f960048036038101906100f49190612437565b6102e0565b005b610115600480360381019061011091906124b8565b610452565b005b34801561012357600080fd5b5061013e600480360381019061013991906125a3565b6104a1565b60405161014b91906123c6565b60405180910390f35b34801561016057600080fd5b5061017b6004803603810190610176919061267f565b6104b9565b60405161018891906123c6565b60405180910390f35b60007f4e2312e0000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916148061025c57507f150b7a02000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b806102c457507f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b9050919050565b600063150b7a0260e01b905095945050505050565b6102e86104f2565b600060606000868690509050808585905014610330576040517fff633a3800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b818110156104405760008888838181106103505761034f612719565b5b9050013560f81c60f81b9050600087878481811061037157610370612719565b5b90506020028101906103839190612757565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505090506103d28282610541565b8096508197505050851580156103ed57506103ec82610c1f565b5b156104315782856040517f2c4029e9000000000000000000000000000000000000000000000000000000008152600401610428929190612859565b60405180910390fd5b82806001019350505050610333565b5050505061044c610c56565b50505050565b808042111561048d576040517f5bf6f91600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610499868686866102e0565b505050505050565b600063bc197c8160e01b905098975050505050505050565b600063f23a6e6160e01b90509695505050505050565b6000808273ffffffffffffffffffffffffffffffffffffffff163b119050919050565b600260015403610537576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161052e906128e6565b60405180910390fd5b6002600181905550565b600060606000601f60f81b851660f81c60ff169050600192506010811015610bda5760088110156108535760008103610627576000808580602001905181019061058b9190612a3c565b915091507f000000000000000000000000178a86d36d89c7fdebea90b739605da7b131ff6a73ffffffffffffffffffffffffffffffffffffffff1682826040516105d59190612ad4565b60006040518083038185875af1925050503d8060008114610612576040519150601f19603f3d011682016040523d82523d6000602084013e610617565b606091505b508095508196505050505061084e565b60018103610656576000848060200190518101906106459190612ce0565b905061065081610c5f565b5061084d565b600281036106a857600080858060200190518101906106759190612d67565b915091506106a161069b8373ffffffffffffffffffffffffffffffffffffffff16611132565b826111b5565b505061084c565b600381036106fa57600080858060200190518101906106c79190612d67565b915091506106f36106ed8373ffffffffffffffffffffffffffffffffffffffff16611132565b8261134d565b505061084b565b600481036107525760008060008680602001905181019061071b9190612da7565b92509250925061074a836107448473ffffffffffffffffffffffffffffffffffffffff16611132565b836114e8565b50505061084a565b600581036107aa576000806000868060200190518101906107739190612da7565b9250925092506107a28361079c8473ffffffffffffffffffffffffffffffffffffffff16611132565b83611684565b505050610849565b60068103610802576000806000868060200190518101906107cb9190612da7565b9250925092506107fa836107f48473ffffffffffffffffffffffffffffffffffffffff16611132565b836117bb565b505050610848565b6007810361084757806040517fd76a1e9e00000000000000000000000000000000000000000000000000000000815260040161083e9190612dfa565b60405180910390fd5b5b5b5b5b5b5b5b610bd5565b6008810361090e57600080858060200190518101906108729190612a3c565b915091507f0000000000000000000000002b2e8cda09bba9660dca5cb6233787738ad6832973ffffffffffffffffffffffffffffffffffffffff1682826040516108bc9190612ad4565b60006040518083038185875af1925050503d80600081146108f9576040519150601f19603f3d011682016040523d82523d6000602084013e6108fe565b606091505b5080955081965050505050610bd4565b600981036109715760008060008680602001905181019061092f9190613039565b9250925092506109617f0000000000000000000000002b2e8cda09bba9660dca5cb6233787738ad68329848484611956565b8096508197505050505050610bd3565b600a8103610a2c57600080858060200190518101906109909190612a3c565b915091507f000000000000000000000000a63ec144d070a1bf19a7577c88c580e7de92e0fc73ffffffffffffffffffffffffffffffffffffffff1682826040516109da9190612ad4565b60006040518083038185875af1925050503d8060008114610a17576040519150601f19603f3d011682016040523d82523d6000602084013e610a1c565b606091505b5080955081965050505050610bd2565b600b8103610a8f57600080600086806020019051810190610a4d9190613039565b925092509250610a7f7f000000000000000000000000a63ec144d070a1bf19a7577c88c580e7de92e0fc848484611956565b8096508197505050505050610bd1565b600c8103610ae757600080600086806020019051810190610ab09190612da7565b925092509250610adf83610ad98473ffffffffffffffffffffffffffffffffffffffff16611132565b83611d8a565b505050610bd0565b600d8103610b445760008060008087806020019051810190610b0991906130c4565b9350935093509350610b3b84610b348573ffffffffffffffffffffffffffffffffffffffff16611132565b8484611dfe565b50505050610bcf565b600e8103610b8957806040517fd76a1e9e000000000000000000000000000000000000000000000000000000008152600401610b809190612dfa565b60405180910390fd5b600f8103610bce57806040517fd76a1e9e000000000000000000000000000000000000000000000000000000008152600401610bc59190612dfa565b60405180910390fd5b5b5b5b5b5b5b5b610c17565b806040517fd76a1e9e000000000000000000000000000000000000000000000000000000008152600401610c0e9190612dfa565b60405180910390fd5b509250929050565b60008060f81b608060f81b83167effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916149050919050565b60018081905550565b60005b815181101561112e576000828281518110610c8057610c7f612719565b5b602002602001015190506102d1816020015103610eb55760007f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc273ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401610cf2919061313a565b602060405180830381865afa158015610d0f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d339190613155565b9050816040015173ffffffffffffffffffffffffffffffffffffffff1663b88d4fde33610d638560000151611f40565b85606001518660a001516040518563ffffffff1660e01b8152600401610d8c9493929190613182565b600060405180830381600087803b158015610da657600080fd5b505af1158015610dba573d6000803e3d6000fd5b5050505060007f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc273ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401610e19919061313a565b602060405180830381865afa158015610e36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e5a9190613155565b90508260c001518282610e6d91906131fd565b1015610eae576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610ea5906132a3565b60405180910390fd5b5050611122565b6104838160200151036110e65760007f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc273ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401610f1d919061313a565b602060405180830381865afa158015610f3a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f5e9190613155565b9050816040015173ffffffffffffffffffffffffffffffffffffffff1663f242432a33610f8e8560000151611f40565b856060015186608001518760a001516040518663ffffffff1660e01b8152600401610fbd9594939291906132c3565b600060405180830381600087803b158015610fd757600080fd5b505af1158015610feb573d6000803e3d6000fd5b5050505060007f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc273ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b815260040161104a919061313a565b602060405180830381865afa158015611067573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061108b9190613155565b90508260c00151828261109e91906131fd565b10156110df576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016110d6906132a3565b60405180910390fd5b5050611121565b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111189061338f565b60405180910390fd5b5b81600101915050610c62565b5050565b6000600173ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603611170573390506111b0565b600273ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036111ac573090506111b0565b8190505b919050565b7f800000000000000000000000000000000000000000000000000000000000000081036111e45747905061121f565b4781111561121e576040517f6a12f10400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5b6000811115611349577f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc273ffffffffffffffffffffffffffffffffffffffff1663d0e30db0826040518263ffffffff1660e01b81526004016000604051808303818588803b15801561129057600080fd5b505af11580156112a4573d6000803e3d6000fd5b50505050507f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc273ffffffffffffffffffffffffffffffffffffffff1663a9059cbb83836040518363ffffffff1660e01b81526004016113049291906133af565b6020604051808303816000875af1158015611323573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113479190613404565b505b5050565b60007f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc273ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016113a8919061313a565b602060405180830381865afa1580156113c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113e99190613155565b905081811015611425576040517f6a12f10400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008111156114e3577f000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc273ffffffffffffffffffffffffffffffffffffffff16632e1a7d4d826040518263ffffffff1660e01b81526004016114879190612dfa565b600060405180830381600087803b1580156114a157600080fd5b505af11580156114b5573d6000803e3d6000fd5b505050506114e2818473ffffffffffffffffffffffffffffffffffffffff1661207c90919063ffffffff16565b5b505050565b60008073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603611592574790508181101561155a576040517f6a12f10400000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600081111561158d5761158c818473ffffffffffffffffffffffffffffffffffffffff1661207c90919063ffffffff16565b5b61167e565b8373ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016115cb919061313a565b602060405180830381865afa1580156115e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061160c9190613155565b905081811015611648576040517f675cae3800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600081111561167d5761167c83828673ffffffffffffffffffffffffffffffffffffffff166120cf9092919063ffffffff16565b5b5b50505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036116e6576116e1818373ffffffffffffffffffffffffffffffffffffffff1661207c90919063ffffffff16565b6117b6565b7f8000000000000000000000000000000000000000000000000000000000000000810361178a578273ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401611746919061313a565b602060405180830381865afa158015611763573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117879190613155565b90505b6117b582828573ffffffffffffffffffffffffffffffffffffffff166120cf9092919063ffffffff16565b5b505050565b60008114806117cb575061271081115b15611802576040517fdeaa01e600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036118885760004790506000612710838361184c9190613431565b61185691906134a2565b9050611881818573ffffffffffffffffffffffffffffffffffffffff1661207c90919063ffffffff16565b5050611951565b60008373ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016118c3919061313a565b602060405180830381865afa1580156118e0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119049190613155565b9050600061271083836119179190613431565b61192191906134a2565b905061194e84828773ffffffffffffffffffffffffffffffffffffffff166120cf9092919063ffffffff16565b50505b505050565b6000606060005b8351811015611b1557600084828151811061197b5761197a612719565b5b602002602001015190506000816020015190506000826000015190506000836040015190506102d18103611acb5760005b8351811015611a575760008482815181106119ca576119c9612719565b5b602002602001015190508373ffffffffffffffffffffffffffffffffffffffff166342842e0e8c30846040518463ffffffff1660e01b8152600401611a11939291906134d3565b600060405180830381600087803b158015611a2b57600080fd5b505af1158015611a3f573d6000803e3d6000fd5b50505050508080611a4f9061350a565b9150506119ac565b508173ffffffffffffffffffffffffffffffffffffffff1663a22cb4658c60016040518363ffffffff1660e01b8152600401611a94929190613552565b600060405180830381600087803b158015611aae57600080fd5b505af1158015611ac2573d6000803e3d6000fd5b50505050611b06565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611afd906135c7565b60405180910390fd5b8460010194505050505061195d565b508573ffffffffffffffffffffffffffffffffffffffff1685604051611b3b9190612ad4565b6000604051808303816000865af19150503d8060008114611b78576040519150601f19603f3d011682016040523d82523d6000602084013e611b7d565b606091505b50809250819350505060005b8351811015611d80576000848281518110611ba757611ba6612719565b5b602002602001015190506000816020015190506000826000015190506000836040015190506102d18103611d365760005b8351811015611d30576000848281518110611bf657611bf5612719565b5b602002602001015190503073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16636352211e836040518263ffffffff1660e01b8152600401611c509190612dfa565b602060405180830381865afa158015611c6d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c9191906135e7565b73ffffffffffffffffffffffffffffffffffffffff1603611d1c578373ffffffffffffffffffffffffffffffffffffffff166342842e0e308d846040518463ffffffff1660e01b8152600401611ce9939291906134d3565b600060405180830381600087803b158015611d0357600080fd5b505af1158015611d17573d6000803e3d6000fd5b505050505b508080611d289061350a565b915050611bd8565b50611d71565b6040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611d68906135c7565b60405180910390fd5b84600101945050505050611b89565b5094509492505050565b8273ffffffffffffffffffffffffffffffffffffffff166342842e0e3084846040518463ffffffff1660e01b8152600401611dc7939291906134d3565b600060405180830381600087803b158015611de157600080fd5b505af1158015611df5573d6000803e3d6000fd5b50505050505050565b60008473ffffffffffffffffffffffffffffffffffffffff1662fdd58e30856040518363ffffffff1660e01b8152600401611e3a9291906133af565b602060405180830381865afa158015611e57573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e7b9190613155565b905081811015611eb7576040517f675cae3800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8473ffffffffffffffffffffffffffffffffffffffff1663f242432a30868685604051806020016040528060008152506040518663ffffffff1660e01b8152600401611f079594939291906132c3565b600060405180830381600087803b158015611f2157600080fd5b505af1158015611f35573d6000803e3d6000fd5b505050505050505050565b6000806002811115611f5557611f54613614565b5b826002811115611f6857611f67613614565b5b03611f95577f0000000000000000000000003729014ef28f01b3ddcf7f980d925e0b71b1f8479050612077565b60016002811115611fa957611fa8613614565b5b826002811115611fbc57611fbb613614565b5b03611fe9577f000000000000000000000000385df8cbc196f5f780367f3cdc96af072a916f7e9050612077565b600280811115611ffc57611ffb613614565b5b82600281111561200f5761200e613614565b5b0361203c577f000000000000000000000000613d3c588f6b8f89302b463f8f19f7241b2857e29050612077565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161206e906136b5565b60405180910390fd5b919050565b600080600080600085875af19050806120ca576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120c190613721565b60405180910390fd5b505050565b60006040517fa9059cbb000000000000000000000000000000000000000000000000000000008152836004820152826024820152602060006044836000895af13d15601f3d1160016000511416171691505080612161576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121589061378d565b60405180910390fd5b50505050565b6000604051905090565b600080fd5b600080fd5b60007fffffffff0000000000000000000000000000000000000000000000000000000082169050919050565b6121b08161217b565b81146121bb57600080fd5b50565b6000813590506121cd816121a7565b92915050565b6000602082840312156121e9576121e8612171565b5b60006121f7848285016121be565b91505092915050565b60008115159050919050565b61221581612200565b82525050565b6000602082019050612230600083018461220c565b92915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061226182612236565b9050919050565b61227181612256565b811461227c57600080fd5b50565b60008135905061228e81612268565b92915050565b6000819050919050565b6122a781612294565b81146122b257600080fd5b50565b6000813590506122c48161229e565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f8401126122ef576122ee6122ca565b5b8235905067ffffffffffffffff81111561230c5761230b6122cf565b5b602083019150836001820283011115612328576123276122d4565b5b9250929050565b60008060008060006080868803121561234b5761234a612171565b5b60006123598882890161227f565b955050602061236a8882890161227f565b945050604061237b888289016122b5565b935050606086013567ffffffffffffffff81111561239c5761239b612176565b5b6123a8888289016122d9565b92509250509295509295909350565b6123c08161217b565b82525050565b60006020820190506123db60008301846123b7565b92915050565b60008083601f8401126123f7576123f66122ca565b5b8235905067ffffffffffffffff811115612414576124136122cf565b5b6020830191508360208202830111156124305761242f6122d4565b5b9250929050565b6000806000806040858703121561245157612450612171565b5b600085013567ffffffffffffffff81111561246f5761246e612176565b5b61247b878288016122d9565b9450945050602085013567ffffffffffffffff81111561249e5761249d612176565b5b6124aa878288016123e1565b925092505092959194509250565b6000806000806000606086880312156124d4576124d3612171565b5b600086013567ffffffffffffffff8111156124f2576124f1612176565b5b6124fe888289016122d9565b9550955050602086013567ffffffffffffffff81111561252157612520612176565b5b61252d888289016123e1565b93509350506040612540888289016122b5565b9150509295509295909350565b60008083601f840112612563576125626122ca565b5b8235905067ffffffffffffffff8111156125805761257f6122cf565b5b60208301915083602082028301111561259c5761259b6122d4565b5b9250929050565b60008060008060008060008060a0898b0312156125c3576125c2612171565b5b60006125d18b828c0161227f565b98505060206125e28b828c0161227f565b975050604089013567ffffffffffffffff81111561260357612602612176565b5b61260f8b828c0161254d565b9650965050606089013567ffffffffffffffff81111561263257612631612176565b5b61263e8b828c0161254d565b9450945050608089013567ffffffffffffffff81111561266157612660612176565b5b61266d8b828c016122d9565b92509250509295985092959890939650565b60008060008060008060a0878903121561269c5761269b612171565b5b60006126aa89828a0161227f565b96505060206126bb89828a0161227f565b95505060406126cc89828a016122b5565b94505060606126dd89828a016122b5565b935050608087013567ffffffffffffffff8111156126fe576126fd612176565b5b61270a89828a016122d9565b92509250509295509295509295565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600080fd5b600080fd5b600080fd5b6000808335600160200384360303811261277457612773612748565b5b80840192508235915067ffffffffffffffff8211156127965761279561274d565b5b6020830192506001820236038313156127b2576127b1612752565b5b509250929050565b6127c381612294565b82525050565b600081519050919050565b600082825260208201905092915050565b60005b838110156128035780820151818401526020810190506127e8565b60008484015250505050565b6000601f19601f8301169050919050565b600061282b826127c9565b61283581856127d4565b93506128458185602086016127e5565b61284e8161280f565b840191505092915050565b600060408201905061286e60008301856127ba565b81810360208301526128808184612820565b90509392505050565b600082825260208201905092915050565b7f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00600082015250565b60006128d0601f83612889565b91506128db8261289a565b602082019050919050565b600060208201905081810360008301526128ff816128c3565b9050919050565b6000815190506129158161229e565b92915050565b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6129588261280f565b810181811067ffffffffffffffff8211171561297757612976612920565b5b80604052505050565b600061298a612167565b9050612996828261294f565b919050565b600067ffffffffffffffff8211156129b6576129b5612920565b5b6129bf8261280f565b9050602081019050919050565b60006129df6129da8461299b565b612980565b9050828152602081018484840111156129fb576129fa61291b565b5b612a068482856127e5565b509392505050565b600082601f830112612a2357612a226122ca565b5b8151612a338482602086016129cc565b91505092915050565b60008060408385031215612a5357612a52612171565b5b6000612a6185828601612906565b925050602083015167ffffffffffffffff811115612a8257612a81612176565b5b612a8e85828601612a0e565b9150509250929050565b600081905092915050565b6000612aae826127c9565b612ab88185612a98565b9350612ac88185602086016127e5565b80840191505092915050565b6000612ae08284612aa3565b915081905092915050565b600067ffffffffffffffff821115612b0657612b05612920565b5b602082029050602081019050919050565b600080fd5b600080fd5b60038110612b2e57600080fd5b50565b600081519050612b4081612b21565b92915050565b600081519050612b5581612268565b92915050565b600060e08284031215612b7157612b70612b17565b5b612b7b60e0612980565b90506000612b8b84828501612b31565b6000830152506020612b9f84828501612906565b6020830152506040612bb384828501612b46565b6040830152506060612bc784828501612906565b6060830152506080612bdb84828501612906565b60808301525060a082015167ffffffffffffffff811115612bff57612bfe612b1c565b5b612c0b84828501612a0e565b60a08301525060c0612c1f84828501612906565b60c08301525092915050565b6000612c3e612c3984612aeb565b612980565b90508083825260208201905060208402830185811115612c6157612c606122d4565b5b835b81811015612ca857805167ffffffffffffffff811115612c8657612c856122ca565b5b808601612c938982612b5b565b85526020850194505050602081019050612c63565b5050509392505050565b600082601f830112612cc757612cc66122ca565b5b8151612cd7848260208601612c2b565b91505092915050565b600060208284031215612cf657612cf5612171565b5b600082015167ffffffffffffffff811115612d1457612d13612176565b5b612d2084828501612cb2565b91505092915050565b6000612d3482612236565b9050919050565b612d4481612d29565b8114612d4f57600080fd5b50565b600081519050612d6181612d3b565b92915050565b60008060408385031215612d7e57612d7d612171565b5b6000612d8c85828601612d52565b9250506020612d9d85828601612906565b9150509250929050565b600080600060608486031215612dc057612dbf612171565b5b6000612dce86828701612d52565b9350506020612ddf86828701612d52565b9250506040612df086828701612906565b9150509250925092565b6000602082019050612e0f60008301846127ba565b92915050565b600067ffffffffffffffff821115612e3057612e2f612920565b5b602082029050602081019050919050565b600067ffffffffffffffff821115612e5c57612e5b612920565b5b602082029050602081019050919050565b6000612e80612e7b84612e41565b612980565b90508083825260208201905060208402830185811115612ea357612ea26122d4565b5b835b81811015612ecc5780612eb88882612906565b845260208401935050602081019050612ea5565b5050509392505050565b600082601f830112612eeb57612eea6122ca565b5b8151612efb848260208601612e6d565b91505092915050565b600060608284031215612f1a57612f19612b17565b5b612f246060612980565b90506000612f3484828501612b46565b600083015250602082015167ffffffffffffffff811115612f5857612f57612b1c565b5b612f6484828501612ed6565b6020830152506040612f7884828501612906565b60408301525092915050565b6000612f97612f9284612e15565b612980565b90508083825260208201905060208402830185811115612fba57612fb96122d4565b5b835b8181101561300157805167ffffffffffffffff811115612fdf57612fde6122ca565b5b808601612fec8982612f04565b85526020850194505050602081019050612fbc565b5050509392505050565b600082601f8301126130205761301f6122ca565b5b8151613030848260208601612f84565b91505092915050565b60008060006060848603121561305257613051612171565b5b600084015167ffffffffffffffff8111156130705761306f612176565b5b61307c86828701612a0e565b935050602061308d86828701612d52565b925050604084015167ffffffffffffffff8111156130ae576130ad612176565b5b6130ba8682870161300b565b9150509250925092565b600080600080608085870312156130de576130dd612171565b5b60006130ec87828801612d52565b94505060206130fd87828801612d52565b935050604061310e87828801612906565b925050606061311f87828801612906565b91505092959194509250565b61313481612256565b82525050565b600060208201905061314f600083018461312b565b92915050565b60006020828403121561316b5761316a612171565b5b600061317984828501612906565b91505092915050565b6000608082019050613197600083018761312b565b6131a4602083018661312b565b6131b160408301856127ba565b81810360608301526131c38184612820565b905095945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061320882612294565b915061321383612294565b925082820390508181111561322b5761322a6131ce565b5b92915050565b7f48616e646c655265736572766f69723a4f66666572416d6f756e74204572726f60008201527f7200000000000000000000000000000000000000000000000000000000000000602082015250565b600061328d602183612889565b915061329882613231565b604082019050919050565b600060208201905081810360008301526132bc81613280565b9050919050565b600060a0820190506132d8600083018861312b565b6132e5602083018761312b565b6132f260408301866127ba565b6132ff60608301856127ba565b81810360808301526133118184612820565b90509695505050505050565b7f48616e646c655265736572766f69723a546f6b656e5374616e6461726420457260008201527f726f720000000000000000000000000000000000000000000000000000000000602082015250565b6000613379602383612889565b91506133848261331d565b604082019050919050565b600060208201905081810360008301526133a88161336c565b9050919050565b60006040820190506133c4600083018561312b565b6133d160208301846127ba565b9392505050565b6133e181612200565b81146133ec57600080fd5b50565b6000815190506133fe816133d8565b92915050565b60006020828403121561341a57613419612171565b5b6000613428848285016133ef565b91505092915050565b600061343c82612294565b915061344783612294565b925082820261345581612294565b9150828204841483151761346c5761346b6131ce565b5b5092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b60006134ad82612294565b91506134b883612294565b9250826134c8576134c7613473565b5b828204905092915050565b60006060820190506134e8600083018661312b565b6134f5602083018561312b565b61350260408301846127ba565b949350505050565b600061351582612294565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203613547576135466131ce565b5b600182019050919050565b6000604082019050613567600083018561312b565b613574602083018461220c565b9392505050565b7f48616e646c654c5353564d3a546f6b656e5374616e64617264204572726f7200600082015250565b60006135b1601f83612889565b91506135bc8261357b565b602082019050919050565b600060208201905081810360008301526135e0816135a4565b9050919050565b6000602082840312156135fd576135fc612171565b5b600061360b84828501612b46565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b7f48616e646c655265736572766f69723a4f666665724d61726b6574204572726f60008201527f7200000000000000000000000000000000000000000000000000000000000000602082015250565b600061369f602183612889565b91506136aa82613643565b604082019050919050565b600060208201905081810360008301526136ce81613692565b9050919050565b7f4554485f5452414e534645525f4641494c454400000000000000000000000000600082015250565b600061370b601383612889565b9150613716826136d5565b602082019050919050565b6000602082019050818103600083015261373a816136fe565b9050919050565b7f5452414e534645525f4641494c45440000000000000000000000000000000000600082015250565b6000613777600f83612889565b915061378282613741565b602082019050919050565b600060208201905081810360008301526137a68161376a565b905091905056fea26469706673582212209cca99d0e0d64a4675dcad5b003c1dbd84e313e50da7da0da744ee246748d6ff64736f6c63430008110033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2000000000000000000000000178a86d36d89c7fdebea90b739605da7b131ff6a0000000000000000000000003729014ef28f01b3ddcf7f980d925e0b71b1f847000000000000000000000000385df8cbc196f5f780367f3cdc96af072a916f7e000000000000000000000000613d3c588f6b8f89302b463f8f19f7241b2857e20000000000000000000000002b2e8cda09bba9660dca5cb6233787738ad68329000000000000000000000000a63ec144d070a1bf19a7577c88c580e7de92e0fc
-----Decoded View---------------
Arg [0] : params (tuple): System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput]
-----Encoded View---------------
7 Constructor Arguments found :
Arg [0] : 000000000000000000000000c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2
Arg [1] : 000000000000000000000000178a86d36d89c7fdebea90b739605da7b131ff6a
Arg [2] : 0000000000000000000000003729014ef28f01b3ddcf7f980d925e0b71b1f847
Arg [3] : 000000000000000000000000385df8cbc196f5f780367f3cdc96af072a916f7e
Arg [4] : 000000000000000000000000613d3c588f6b8f89302b463f8f19f7241b2857e2
Arg [5] : 0000000000000000000000002b2e8cda09bba9660dca5cb6233787738ad68329
Arg [6] : 000000000000000000000000a63ec144d070a1bf19a7577c88c580e7de92e0fc
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 35 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
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.