Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Latest 1 internal transaction
Advanced mode:
Parent Transaction Hash | Block |
From
|
To
|
|||
---|---|---|---|---|---|---|
21325477 | 33 days ago | Contract Creation | 0 ETH |
Loading...
Loading
Contract Name:
TransferModule
Compiler Version
v0.8.21+commit.d9974bed
Optimization Enabled:
Yes with 200 runs
Other Settings:
shanghai EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// c=< // | // | ////\ 1@2 // @@ | /___\** @@@2 @@@@@@@@@@@@@@@@@@@@@@ // @@@ | |~L~ |* @@@@@@ @@@ @@@@@ @@@@ @@@ @@@@ @@@ @@@@@@@@ @@@@ @@@@ @@@ @@@@@@@@@ @@@@ @@@@ // @@@@@ | \=_/8 @@@@1@@ @@@ @@@@@ @@@@ @@@@ @@@ @@@@@ @@@ @@@@@@@@@ @@@@ @@@@@ @@@@ @@@@@@@@@ @@@@ @@@@ // @@@@@@| _ /| |\__ @@@@@@@@2 @@@ @@@@@ @@@@ @@@@ @@@ @@@@@@@ @@@ @@@@ @@@@ @@@@@@ @@@@ @@@ @@@@@@@ // 1@@@@@@|\ \___/) @@1@@@@@2 ~~~ ~~~~~ @@@@ ~~@@ ~~~ ~~~~~~~~~~~ ~~~~ ~~~~ ~~~~~~~~~~~ ~@@ @@@@@ // 2@@@@@ | \ \ / | @@@@@@2 @@@ @@@@@ @@@@ @@@@ @@@ @@@@@@@@@@@ @@@@@@@@@ @@@@ @@@@@@@@@@@ @@@@@@@@@ @@@@@ // 2@@@@ |_ > <|__ @@1@12 @@@ @@@@@ @@@@ @@@@ @@@ @@@@ @@@@@@ @@@@ @@@@ @@@@ @@@@@@ @@@ @@@@@@@ // @@@@ / _| / \/ \ @@1@ @@@ @@@ @@@@ @@@@ @@@ @@@@ @@@@@ @@@@ @@@@ @@@@ @@@@@ @@@@@@@@@ @@@@ @@@@ // @@ / |^\/ | | @@1 @@@ @@@@ @@@@ @@@ @@@@ @@@ @@@@ @@@@ @@@ @@@@ @@@@@@@@@ @@@@ @@@@ // / / ---- \ \\\= @@ @@@@@@@@@@@@@@@@@@@@@@ // \___/ -------- ~~ @@@ // @@ | | | | -- @@ // ———————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————— // SPDX-License-Identifier: MIT pragma solidity ^0.8.21; import { ReentrancyGuardUpgradeable } from "@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol"; import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import { ITransferModule } from "src/interfaces/accounts/ITransferModule.sol"; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import { IERC721 } from "@openzeppelin/contracts/token/ERC721/IERC721.sol"; import { IERC1155 } from "@openzeppelin/contracts/token/ERC1155/IERC1155.sol"; import { IERC721ABatchTransferable } from "ERC721A/extensions/IERC721ABatchTransferable.sol"; import { Cosigning } from "src/accounts/storage/Cosigning.sol"; import { EIP712 } from "src/accounts/storage/EIP712.sol"; import { SecurityUtils } from "src/accounts/utils/SecurityUtils.sol"; import { NonStandardToken } from "src/libraries/NonStandardToken.sol"; contract TransferModule is ITransferModule, ReentrancyGuardUpgradeable { using SafeERC20 for IERC20; /*/////////////////////////////////////////////////////////////// MODIFIERS ///////////////////////////////////////////////////////////////*/ /** * @notice Modifier to ensure that the transfer request is valid and has been co-signed by the sudo key and platform. * @param _request The transfer request. * @param _sudoKeySignature The signature of the sudo key. * @param _platformKeySignature The signature of the platform key. */ modifier requiresCoSigning( TransferRequest calldata _request, bytes calldata _sudoKeySignature, bytes calldata _platformKeySignature ) { if (_request.selector != msg.sig) revert InvalidRequest(); if (!Cosigning._isValidNonce(_request.nonce)) revert InvalidNonce(); bytes32 requestHash = EIP712._hashTypedDataV4(_hashTransferRequest(_request)); SecurityUtils._validateCoSignature(requestHash, _sudoKeySignature, _platformKeySignature); // Finally consume the nonce Cosigning._consumeNonce(_request.nonce); _; } /*/////////////////////////////////////////////////////////////// MUTATIVE FUNCTIONS ///////////////////////////////////////////////////////////////*/ /** * @notice Transfers ether to a destination address. * @param _request The transfer request. * @param _sudoKeySignature The signature of the sudo key. * @param _platformKeySignature The signature of the platform key. * @dev Should be called without using the forwarder. * @dev Request must be co-signed by the sudo key and platform key. */ function transferEther(TransferRequest calldata _request, bytes calldata _sudoKeySignature, bytes calldata _platformKeySignature) external requiresCoSigning(_request, _sudoKeySignature, _platformKeySignature) nonReentrant { _transferEther(_request); } /** * @notice Transfers an ERC20 token to a destination address. * @param _request The transfer request. * @param _sudoKeySignature The signature of the sudo key. * @param _platformKeySignature The signature of the platform key. * @dev Should be called without using the forwarder. * @dev Request must be co-signed by the sudo key and platform key. */ function transferERC20(TransferRequest calldata _request, bytes calldata _sudoKeySignature, bytes calldata _platformKeySignature) external requiresCoSigning(_request, _sudoKeySignature, _platformKeySignature) nonReentrant { _transferERC20(_request); } /** * @notice Transfers an ERC721 token to a destination address. * @param _request The transfer request. * @param _sudoKeySignature The signature of the sudo key. * @param _platformKeySignature The signature of the platform key. * @dev Should be called without using the forwarder. * @dev Request must be co-signed by the sudo key and platform key. */ function transferERC721(TransferRequest calldata _request, bytes calldata _sudoKeySignature, bytes calldata _platformKeySignature) external requiresCoSigning(_request, _sudoKeySignature, _platformKeySignature) nonReentrant { _transferERC721(_request); } /** * @notice Transfers a batch of ERC721A tokens to a destination address. * @param _request The transfer request. * @param _sudoKeySignature The signature of the sudo key. * @param _platformKeySignature The signature of the platform key. * @dev Should be called without using the forwarder. * @dev Request must be co-signed by the sudo key and platform key. * @dev Token ids must be strictly ascending. */ function transferERC721ABatch( TransferRequest calldata _request, bytes calldata _sudoKeySignature, bytes calldata _platformKeySignature ) external requiresCoSigning(_request, _sudoKeySignature, _platformKeySignature) nonReentrant { _transferERC721ABatch(_request); } /** * @notice Transfers an ERC1155 token to a destination address. * @param _request The transfer request. * @param _sudoKeySignature The signature of the sudo key. * @param _platformKeySignature The signature of the platform key. * @dev Should be called without using the forwarder. * @dev Request must be co-signed by the sudo key and platform key. */ function transferERC1155(TransferRequest calldata _request, bytes calldata _sudoKeySignature, bytes calldata _platformKeySignature) external requiresCoSigning(_request, _sudoKeySignature, _platformKeySignature) nonReentrant { _transferERC1155(_request); } /** * @notice Transfers a batch of ERC1155 tokens to a destination address. * @param _request The transfer request. * @param _sudoKeySignature The signature of the sudo key. * @param _platformKeySignature The signature of the platform key. * @dev Should be called without using the forwarder. * @dev Request must be co-signed by the sudo key and platform key. */ function transferERC1155Batch( TransferRequest calldata _request, bytes calldata _sudoKeySignature, bytes calldata _platformKeySignature ) external requiresCoSigning(_request, _sudoKeySignature, _platformKeySignature) nonReentrant { _transferERC1155Batch(_request); } /** * @notice Transfers a non-standard token to a destination address. * @param _request The transfer request. * @param _sudoKeySignature The signature of the sudo key. * @param _platformKeySignature The signature of the platform key. * @dev Should be called without using the forwarder. * @dev Request must be co-signed by the sudo key and platform key. */ function transferNonStandardToken( TransferRequest calldata _request, bytes calldata _sudoKeySignature, bytes calldata _platformKeySignature ) external requiresCoSigning(_request, _sudoKeySignature, _platformKeySignature) nonReentrant { _transferNonStandardToken(_request); } /*/////////////////////////////////////////////////////////////// INTERNAL FUNCTIONS ///////////////////////////////////////////////////////////////*/ /** * @notice Creates an EIP712 compliant hash for a transfer request * @param _request The transfer request to hash * @return The EIP712 compliant hash of the transfer request */ function _hashTransferRequest(TransferRequest calldata _request) internal pure returns (bytes32) { return keccak256( abi.encode( Cosigning._TRANSFER_REQUEST_TYPEHASH, _request.selector, _request.destination, _request.token, _request.nonStandardIndex, _request.tokenId, _request.amount, keccak256(abi.encodePacked(_request.amounts)), keccak256(abi.encodePacked(_request.tokenIds)), keccak256(_request.data), _request.nonce ) ); } /** * @notice Transfers ether to a destination address. * @param _request The transfer request. */ function _transferEther(TransferRequest calldata _request) internal { if (_request.destination == address(0)) revert NullAddress(); if (_request.amount == 0) revert ZeroValue(); emit EtherTransferred(_request.destination, _request.amount); // slither-disable-next-line arbitrary-send-eth (bool success,) = _request.destination.call{ value: _request.amount }(""); if (!success) revert EtherTransferFailed(); } /** * @notice Transfers an ERC20 token to a destination address. * @param _request The transfer request. */ function _transferERC20(TransferRequest calldata _request) internal { if (_request.amount == 0) revert ZeroValue(); emit ERC20Transferred(_request.token, _request.destination, _request.amount); IERC20(_request.token).safeTransfer(_request.destination, _request.amount); } /** * @notice Transfers an ERC721 token to a destination address. * @param _request The transfer request. */ function _transferERC721(TransferRequest calldata _request) internal { if (_request.destination == address(0)) revert NullAddress(); if (_request.token == address(0)) revert NullAddress(); emit ERC721Transferred(_request.token, _request.destination, _request.tokenId); IERC721(_request.token).safeTransferFrom(address(this), _request.destination, _request.tokenId, _request.data); } /** * @notice Transfers a batch of ERC721A tokens to a destination address. * @param _request The transfer request. */ function _transferERC721ABatch(TransferRequest calldata _request) internal { if (_request.destination == address(0)) revert NullAddress(); if (_request.token == address(0)) revert NullAddress(); if (_request.tokenIds.length == 0) revert InvalidLength(); emit ERC721ABatchTransferred(_request.token, _request.destination, _request.tokenIds.length); IERC721ABatchTransferable(_request.token).safeBatchTransferFrom( address(this), _request.destination, _request.tokenIds, _request.data ); } /** * @notice Transfers an ERC1155 token to a destination address. * @param _request The transfer request. */ function _transferERC1155(TransferRequest calldata _request) internal { emit ERC1155Transferred(_request.token, _request.destination, _request.tokenId, _request.amount, _request.data); IERC1155(_request.token).safeTransferFrom( address(this), _request.destination, _request.tokenId, _request.amount, _request.data ); } /** * @notice Transfers a batch of ERC1155 tokens to a destination address. * @param _request The transfer request. */ function _transferERC1155Batch(TransferRequest calldata _request) internal { emit ERC1155BatchTransferred(_request.token, _request.destination, _request.tokenIds, _request.amounts, _request.data); IERC1155(_request.token).safeBatchTransferFrom( address(this), _request.destination, _request.tokenIds, _request.amounts, _request.data ); } /** * @notice Transfers a non-standard token to a destination address. * @param _request The transfer request. */ function _transferNonStandardToken(TransferRequest calldata _request) internal { if (_request.destination == address(0)) revert NullAddress(); if (_request.token == address(0)) revert NullAddress(); emit NonStandardNFTTransferred(_request.token, _request.destination, _request.tokenId, _request.nonStandardIndex); NonStandardToken.transfer(_request.token, _request.destination, _request.tokenId, _request.nonStandardIndex); } }
// SPDX-License-Identifier: MIT // ERC721A Contracts v4.3.0 // Creator: Chiru Labs pragma solidity ^0.8.4; /** * @dev Interface of ERC721A. */ interface IERC721A { /** * The caller must own the token or be an approved operator. */ error ApprovalCallerNotOwnerNorApproved(); /** * The token does not exist. */ error ApprovalQueryForNonexistentToken(); /** * Cannot query the balance for the zero address. */ error BalanceQueryForZeroAddress(); /** * Cannot mint to the zero address. */ error MintToZeroAddress(); /** * The quantity of tokens minted must be more than zero. */ error MintZeroQuantity(); /** * The token does not exist. */ error OwnerQueryForNonexistentToken(); /** * The caller must own the token or be an approved operator. */ error TransferCallerNotOwnerNorApproved(); /** * The token must be owned by `from`. */ error TransferFromIncorrectOwner(); /** * Cannot safely transfer to a contract that does not implement the * ERC721Receiver interface. */ error TransferToNonERC721ReceiverImplementer(); /** * Cannot transfer to the zero address. */ error TransferToZeroAddress(); /** * The token does not exist. */ error URIQueryForNonexistentToken(); /** * The `quantity` minted with ERC2309 exceeds the safety limit. */ error MintERC2309QuantityExceedsLimit(); /** * The `extraData` cannot be set on an unintialized ownership slot. */ error OwnershipNotInitializedForExtraData(); /** * The `tokenIds` must be strictly ascending. */ error TokenIdsNotStrictlyAscending(); /** * `_sequentialUpTo()` must be greater than `_startTokenId()`. */ error SequentialUpToTooSmall(); /** * The `tokenId` of a sequential mint exceeds `_sequentialUpTo()`. */ error SequentialMintExceedsLimit(); /** * Spot minting requires a `tokenId` greater than `_sequentialUpTo()`. */ error SpotMintTokenIdTooSmall(); /** * Cannot mint over a token that already exists. */ error TokenAlreadyExists(); /** * The feature is not compatible with spot mints. */ error NotCompatibleWithSpotMints(); // ============================================================= // STRUCTS // ============================================================= struct TokenOwnership { // The address of the owner. address addr; // Stores the start time of ownership with minimal overhead for tokenomics. uint64 startTimestamp; // Whether the token has been burned. bool burned; // Arbitrary data similar to `startTimestamp` that can be set via {_extraData}. uint24 extraData; } // ============================================================= // TOKEN COUNTERS // ============================================================= /** * @dev Returns the total number of tokens in existence. * Burned tokens will reduce the count. * To get the total number of tokens minted, please see {_totalMinted}. */ function totalSupply() external view returns (uint256); // ============================================================= // IERC165 // ============================================================= /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * [EIP section](https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified) * to learn more about how these ids are created. * * This function call must use less than 30000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); // ============================================================= // IERC721 // ============================================================= /** * @dev Emitted when `tokenId` token is transferred from `from` to `to`. */ event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token. */ event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables or disables * (`approved`) `operator` to manage all of its assets. */ event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /** * @dev Returns the number of tokens in `owner`'s account. */ function balanceOf(address owner) external view returns (uint256 balance); /** * @dev Returns the owner of the `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function ownerOf(uint256 tokenId) external view returns (address owner); /** * @dev Safely transfers `tokenId` token from `from` to `to`, * checking first that contract recipients are aware of the ERC721 protocol * to prevent tokens from being forever locked. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be have been allowed to move * this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement * {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom( address from, address to, uint256 tokenId, bytes calldata data ) external payable; /** * @dev Equivalent to `safeTransferFrom(from, to, tokenId, '')`. */ function safeTransferFrom( address from, address to, uint256 tokenId ) external payable; /** * @dev Transfers `tokenId` from `from` to `to`. * * WARNING: Usage of this method is discouraged, use {safeTransferFrom} * whenever possible. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * - If the caller is not `from`, it must be approved to move this token * by either {approve} or {setApprovalForAll}. * * Emits a {Transfer} event. */ function transferFrom( address from, address to, uint256 tokenId ) external payable; /** * @dev Gives permission to `to` to transfer `tokenId` token to another account. * The approval is cleared when the token is transferred. * * Only a single account can be approved at a time, so approving the * zero address clears previous approvals. * * Requirements: * * - The caller must own the token or be an approved operator. * - `tokenId` must exist. * * Emits an {Approval} event. */ function approve(address to, uint256 tokenId) external payable; /** * @dev Approve or remove `operator` as an operator for the caller. * Operators can call {transferFrom} or {safeTransferFrom} * for any token owned by the caller. * * Requirements: * * - The `operator` cannot be the caller. * * Emits an {ApprovalForAll} event. */ function setApprovalForAll(address operator, bool _approved) external; /** * @dev Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) external view returns (address operator); /** * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`. * * See {setApprovalForAll}. */ function isApprovedForAll(address owner, address operator) external view returns (bool); // ============================================================= // IERC721Metadata // ============================================================= /** * @dev Returns the token collection name. */ function name() external view returns (string memory); /** * @dev Returns the token collection symbol. */ function symbol() external view returns (string memory); /** * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token. */ function tokenURI(uint256 tokenId) external view returns (string memory); // ============================================================= // IERC2309 // ============================================================= /** * @dev Emitted when tokens in `fromTokenId` to `toTokenId` * (inclusive) is transferred from `from` to `to`, as defined in the * [ERC2309](https://eips.ethereum.org/EIPS/eip-2309) standard. * * See {_mintERC2309} for more details. */ event ConsecutiveTransfer(uint256 indexed fromTokenId, uint256 toTokenId, address indexed from, address indexed to); }
// SPDX-License-Identifier: MIT // ERC721A Contracts v4.2.3 // Creator: Chiru Labs pragma solidity ^0.8.4; import '../IERC721A.sol'; /** * @dev Interface of ERC721ABatchTransferable. */ interface IERC721ABatchTransferable is IERC721A { /** * @dev Transfers `tokenIds` in batch from `from` to `to`. See {ERC721A-_batchTransferFrom}. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenIds` tokens must be owned by `from`. * - If the caller is not `from`, it must be approved to move these tokens * by either {approve} or {setApprovalForAll}. * * Emits a {Transfer} event for each transfer. */ function batchTransferFrom( address from, address to, uint256[] memory tokenIds ) external payable; /** * @dev Equivalent to `safeBatchTransferFrom(from, to, tokenIds, '')`. */ function safeBatchTransferFrom( address from, address to, uint256[] memory tokenIds ) external payable; /** * @dev Safely transfers `tokenIds` in batch from `from` to `to`. See {ERC721A-_safeBatchTransferFrom}. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenIds` tokens must be owned by `from`. * - If the caller is not `from`, it must be approved to move these tokens * by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement * {IERC721Receiver-onERC721Received}, which is called for each transferred token. * * Emits a {Transfer} event for each transfer. */ function safeBatchTransferFrom( address from, address to, uint256[] memory tokenIds, bytes memory _data ) external payable; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (proxy/utils/Initializable.sol) pragma solidity ^0.8.20; /** * @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] * ```solidity * 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 Storage of the initializable contract. * * It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions * when using with upgradeable contracts. * * @custom:storage-location erc7201:openzeppelin.storage.Initializable */ struct InitializableStorage { /** * @dev Indicates that the contract has been initialized. */ uint64 _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool _initializing; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Initializable")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00; /** * @dev The contract is already initialized. */ error InvalidInitialization(); /** * @dev The contract is not initializing. */ error NotInitializing(); /** * @dev Triggered when the contract has been initialized or reinitialized. */ event Initialized(uint64 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 in the context of a constructor an `initializer` may be invoked any * number of times. This behavior in the constructor can be useful during testing and is not expected to be used in * production. * * Emits an {Initialized} event. */ modifier initializer() { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); // Cache values to avoid duplicated sloads bool isTopLevelCall = !$._initializing; uint64 initialized = $._initialized; // Allowed calls: // - initialSetup: the contract is not in the initializing state and no previous version was // initialized // - construction: the contract is initialized at version 1 (no reininitialization) and the // current contract is just being deployed bool initialSetup = initialized == 0 && isTopLevelCall; bool construction = initialized == 1 && address(this).code.length == 0; if (!initialSetup && !construction) { revert InvalidInitialization(); } $._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 2**64 - 1 will prevent any future reinitialization. * * Emits an {Initialized} event. */ modifier reinitializer(uint64 version) { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); if ($._initializing || $._initialized >= version) { revert InvalidInitialization(); } $._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() { _checkInitializing(); _; } /** * @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}. */ function _checkInitializing() internal view virtual { if (!_isInitializing()) { revert NotInitializing(); } } /** * @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 { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); if ($._initializing) { revert InvalidInitialization(); } if ($._initialized != type(uint64).max) { $._initialized = type(uint64).max; emit Initialized(type(uint64).max); } } /** * @dev Returns the highest version that has been initialized. See {reinitializer}. */ function _getInitializedVersion() internal view returns (uint64) { return _getInitializableStorage()._initialized; } /** * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}. */ function _isInitializing() internal view returns (bool) { return _getInitializableStorage()._initializing; } /** * @dev Returns a pointer to the storage namespace. */ // solhint-disable-next-line var-name-mixedcase function _getInitializableStorage() private pure returns (InitializableStorage storage $) { assembly { $.slot := INITIALIZABLE_STORAGE } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/ReentrancyGuard.sol) pragma solidity ^0.8.20; import {Initializable} from "../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; /// @custom:storage-location erc7201:openzeppelin.storage.ReentrancyGuard struct ReentrancyGuardStorage { uint256 _status; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.ReentrancyGuard")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant ReentrancyGuardStorageLocation = 0x9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00; function _getReentrancyGuardStorage() private pure returns (ReentrancyGuardStorage storage $) { assembly { $.slot := ReentrancyGuardStorageLocation } } /** * @dev Unauthorized reentrant call. */ error ReentrancyGuardReentrantCall(); function __ReentrancyGuard_init() internal onlyInitializing { __ReentrancyGuard_init_unchained(); } function __ReentrancyGuard_init_unchained() internal onlyInitializing { ReentrancyGuardStorage storage $ = _getReentrancyGuardStorage(); $._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 { ReentrancyGuardStorage storage $ = _getReentrancyGuardStorage(); // On the first call to nonReentrant, _status will be NOT_ENTERED if ($._status == ENTERED) { revert ReentrancyGuardReentrantCall(); } // Any calls to nonReentrant after this point will fail $._status = ENTERED; } function _nonReentrantAfter() private { ReentrancyGuardStorage storage $ = _getReentrancyGuardStorage(); // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) $._status = NOT_ENTERED; } /** * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a * `nonReentrant` function in the call stack. */ function _reentrancyGuardEntered() internal view returns (bool) { ReentrancyGuardStorage storage $ = _getReentrancyGuardStorage(); return $._status == ENTERED; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.1) (token/ERC1155/IERC1155.sol) pragma solidity ^0.8.20; import {IERC165} from "../../utils/introspection/IERC165.sol"; /** * @dev Required interface of an ERC1155 compliant contract, as defined in the * https://eips.ethereum.org/EIPS/eip-1155[EIP]. */ interface IERC1155 is IERC165 { /** * @dev Emitted when `value` amount of tokens of type `id` are transferred from `from` to `to` by `operator`. */ event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value); /** * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all * transfers. */ event TransferBatch( address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values ); /** * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to * `approved`. */ event ApprovalForAll(address indexed account, address indexed operator, bool approved); /** * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI. * * If an {URI} event was emitted for `id`, the standard * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value * returned by {IERC1155MetadataURI-uri}. */ event URI(string value, uint256 indexed id); /** * @dev Returns the value of tokens of token type `id` owned by `account`. * * Requirements: * * - `account` cannot be the zero address. */ function balanceOf(address account, uint256 id) external view returns (uint256); /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}. * * Requirements: * * - `accounts` and `ids` must have the same length. */ function balanceOfBatch( address[] calldata accounts, uint256[] calldata ids ) external view returns (uint256[] memory); /** * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`, * * Emits an {ApprovalForAll} event. * * Requirements: * * - `operator` cannot be the caller. */ function setApprovalForAll(address operator, bool approved) external; /** * @dev Returns true if `operator` is approved to transfer ``account``'s tokens. * * See {setApprovalForAll}. */ function isApprovedForAll(address account, address operator) external view returns (bool); /** * @dev Transfers a `value` amount of tokens of type `id` from `from` to `to`. * * WARNING: This function can potentially allow a reentrancy attack when transferring tokens * to an untrusted contract, when invoking {onERC1155Received} on the receiver. * Ensure to follow the checks-effects-interactions pattern and consider employing * reentrancy guards when interacting with untrusted contracts. * * Emits a {TransferSingle} event. * * Requirements: * * - `to` cannot be the zero address. * - If the caller is not `from`, it must have been approved to spend ``from``'s tokens via {setApprovalForAll}. * - `from` must have a balance of tokens of type `id` of at least `value` amount. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the * acceptance magic value. */ function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes calldata data) external; /** * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}. * * WARNING: This function can potentially allow a reentrancy attack when transferring tokens * to an untrusted contract, when invoking {onERC1155BatchReceived} on the receiver. * Ensure to follow the checks-effects-interactions pattern and consider employing * reentrancy guards when interacting with untrusted contracts. * * Emits either a {TransferSingle} or a {TransferBatch} event, depending on the length of the array arguments. * * Requirements: * * - `ids` and `values` must have the same length. * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the * acceptance magic value. */ function safeBatchTransferFrom( address from, address to, uint256[] calldata ids, uint256[] calldata values, bytes calldata data ) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.20; /** * @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 value of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the value of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves a `value` amount of 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 value) 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 a `value` amount of tokens 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 value) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the * allowance mechanism. `value` 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 value) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. * * ==== Security Considerations * * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be * considered as an intention to spend the allowance in any specific way. The second is that because permits have * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be * generally recommended is: * * ```solidity * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public { * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {} * doThing(..., value); * } * * function doThing(..., uint256 value) public { * token.safeTransferFrom(msg.sender, address(this), value); * ... * } * ``` * * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also * {SafeERC20-safeTransferFrom}). * * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so * contracts should have entry points that don't rely on permit. */ interface IERC20Permit { /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, * given ``owner``'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. * * CAUTION: See Security Considerations above. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.20; import {IERC20} from "../IERC20.sol"; import {IERC20Permit} from "../extensions/IERC20Permit.sol"; import {Address} from "../../../utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; /** * @dev An operation with an ERC20 token failed. */ error SafeERC20FailedOperation(address token); /** * @dev Indicates a failed `decreaseAllowance` request. */ error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease); /** * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeTransfer(IERC20 token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value))); } /** * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful. */ function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value))); } /** * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 oldAllowance = token.allowance(address(this), spender); forceApprove(token, spender, oldAllowance + value); } /** * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no * value, non-reverting calls are assumed to be successful. */ function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal { unchecked { uint256 currentAllowance = token.allowance(address(this), spender); if (currentAllowance < requestedDecrease) { revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease); } forceApprove(token, spender, currentAllowance - requestedDecrease); } } /** * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval * to be set to zero before setting it to a non-zero value, such as USDT. */ function forceApprove(IERC20 token, address spender, uint256 value) internal { bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value)); if (!_callOptionalReturnBool(token, approvalCall)) { _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0))); _callOptionalReturn(token, approvalCall); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data); if (returndata.length != 0 && !abi.decode(returndata, (bool))) { revert SafeERC20FailedOperation(address(token)); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). * * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead. */ function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false // and not revert is the subcall reverts. (bool success, bytes memory returndata) = address(token).call(data); return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && address(token).code.length > 0; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/IERC721.sol) pragma solidity ^0.8.20; import {IERC165} from "../../utils/introspection/IERC165.sol"; /** * @dev Required interface of an ERC721 compliant contract. */ interface IERC721 is IERC165 { /** * @dev Emitted when `tokenId` token is transferred from `from` to `to`. */ event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token. */ event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets. */ event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /** * @dev Returns the number of tokens in ``owner``'s account. */ function balanceOf(address owner) external view returns (uint256 balance); /** * @dev Returns the owner of the `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function ownerOf(uint256 tokenId) external view returns (address owner); /** * @dev Safely transfers `tokenId` token from `from` to `to`. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon * a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external; /** * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients * are aware of the ERC721 protocol to prevent tokens from being forever locked. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must exist and be owned by `from`. * - If the caller is not `from`, it must have been allowed to move this token by either {approve} or * {setApprovalForAll}. * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon * a safe transfer. * * Emits a {Transfer} event. */ function safeTransferFrom(address from, address to, uint256 tokenId) external; /** * @dev Transfers `tokenId` token from `from` to `to`. * * WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC721 * or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must * understand this adds an external call which potentially creates a reentrancy vulnerability. * * Requirements: * * - `from` cannot be the zero address. * - `to` cannot be the zero address. * - `tokenId` token must be owned by `from`. * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 tokenId) external; /** * @dev Gives permission to `to` to transfer `tokenId` token to another account. * The approval is cleared when the token is transferred. * * Only a single account can be approved at a time, so approving the zero address clears previous approvals. * * Requirements: * * - The caller must own the token or be an approved operator. * - `tokenId` must exist. * * Emits an {Approval} event. */ function approve(address to, uint256 tokenId) external; /** * @dev Approve or remove `operator` as an operator for the caller. * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller. * * Requirements: * * - The `operator` cannot be the address zero. * * Emits an {ApprovalForAll} event. */ function setApprovalForAll(address operator, bool approved) external; /** * @dev Returns the account approved for `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function getApproved(uint256 tokenId) external view returns (address operator); /** * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`. * * See {setApprovalForAll} */ function isApprovedForAll(address owner, address operator) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol) pragma solidity ^0.8.20; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev The ETH balance of the account is not enough to perform the operation. */ error AddressInsufficientBalance(address account); /** * @dev There's no code at `target` (it is not a contract). */ error AddressEmptyCode(address target); /** * @dev A call to an address target failed. The target may have reverted. */ error FailedInnerCall(); /** * @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://consensys.net/diligence/blog/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.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { if (address(this).balance < amount) { revert AddressInsufficientBalance(address(this)); } (bool success, ) = recipient.call{value: amount}(""); if (!success) { revert FailedInnerCall(); } } /** * @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 or custom error, it is bubbled * up by this function (like regular Solidity function calls). However, if * the call reverted with no returned reason, this function reverts with a * {FailedInnerCall} error. * * 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. */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0); } /** * @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`. */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { if (address(this).balance < value) { revert AddressInsufficientBalance(address(this)); } (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an * unsuccessful call. */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata ) internal view returns (bytes memory) { if (!success) { _revert(returndata); } else { // only check if target is a contract if the call was successful and the return data is empty // otherwise we already know that it was a contract if (returndata.length == 0 && target.code.length == 0) { revert AddressEmptyCode(target); } return returndata; } } /** * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the * revert reason or with a default {FailedInnerCall} error. */ function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) { if (!success) { _revert(returndata); } else { return returndata; } } /** * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}. */ function _revert(bytes memory returndata) 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 FailedInnerCall(); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/Strings.sol) pragma solidity ^0.8.20; import {Math} from "./math/Math.sol"; import {SignedMath} from "./math/SignedMath.sol"; /** * @dev String operations. */ library Strings { bytes16 private constant HEX_DIGITS = "0123456789abcdef"; uint8 private constant ADDRESS_LENGTH = 20; /** * @dev The `value` string doesn't fit in the specified `length`. */ error StringsInsufficientHexLength(uint256 value, uint256 length); /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { unchecked { uint256 length = Math.log10(value) + 1; string memory buffer = new string(length); uint256 ptr; /// @solidity memory-safe-assembly assembly { ptr := add(buffer, add(32, length)) } while (true) { ptr--; /// @solidity memory-safe-assembly assembly { mstore8(ptr, byte(mod(value, 10), HEX_DIGITS)) } value /= 10; if (value == 0) break; } return buffer; } } /** * @dev Converts a `int256` to its ASCII `string` decimal representation. */ function toStringSigned(int256 value) internal pure returns (string memory) { return string.concat(value < 0 ? "-" : "", toString(SignedMath.abs(value))); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { unchecked { return toHexString(value, Math.log256(value) + 1); } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { uint256 localValue = value; bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = HEX_DIGITS[localValue & 0xf]; localValue >>= 4; } if (localValue != 0) { revert StringsInsufficientHexLength(value, length); } return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal * representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), ADDRESS_LENGTH); } /** * @dev Returns true if the two strings are equal. */ function equal(string memory a, string memory b) internal pure returns (bool) { return bytes(a).length == bytes(b).length && keccak256(bytes(a)) == keccak256(bytes(b)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/ECDSA.sol) pragma solidity ^0.8.20; /** * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations. * * These functions can be used to verify that a message was signed by the holder * of the private keys of a given address. */ library ECDSA { enum RecoverError { NoError, InvalidSignature, InvalidSignatureLength, InvalidSignatureS } /** * @dev The signature derives the `address(0)`. */ error ECDSAInvalidSignature(); /** * @dev The signature has an invalid length. */ error ECDSAInvalidSignatureLength(uint256 length); /** * @dev The signature has an S value that is in the upper half order. */ error ECDSAInvalidSignatureS(bytes32 s); /** * @dev Returns the address that signed a hashed message (`hash`) with `signature` or an error. This will not * return address(0) without also returning an error description. Errors are documented using an enum (error type) * and a bytes32 providing additional information about the error. * * If no error is returned, then the address can be used for verification purposes. * * The `ecrecover` EVM precompile allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it. * * Documentation for signature generation: * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js] * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers] */ function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError, bytes32) { if (signature.length == 65) { bytes32 r; bytes32 s; uint8 v; // ecrecover takes the signature parameters, and the only way to get them // currently is to use assembly. /// @solidity memory-safe-assembly assembly { r := mload(add(signature, 0x20)) s := mload(add(signature, 0x40)) v := byte(0, mload(add(signature, 0x60))) } return tryRecover(hash, v, r, s); } else { return (address(0), RecoverError.InvalidSignatureLength, bytes32(signature.length)); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature`. This address can then be used for verification purposes. * * The `ecrecover` EVM precompile allows for malleable (non-unique) signatures: * this function rejects them by requiring the `s` value to be in the lower * half order, and the `v` value to be either 27 or 28. * * IMPORTANT: `hash` _must_ be the result of a hash operation for the * verification to be secure: it is possible to craft signatures that * recover to arbitrary addresses for non-hashed data. A safe way to ensure * this is by receiving a hash of the original message (which may otherwise * be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it. */ function recover(bytes32 hash, bytes memory signature) internal pure returns (address) { (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, signature); _throwError(error, errorArg); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately. * * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures] */ function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError, bytes32) { unchecked { bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff); // We do not check for an overflow here since the shift operation results in 0 or 1. uint8 v = uint8((uint256(vs) >> 255) + 27); return tryRecover(hash, v, r, s); } } /** * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately. */ function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) { (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, r, vs); _throwError(error, errorArg); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `v`, * `r` and `s` signature fields separately. */ function tryRecover( bytes32 hash, uint8 v, bytes32 r, bytes32 s ) internal pure returns (address, RecoverError, bytes32) { // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most // signatures from current libraries generate a unique signature with an s-value in the lower half order. // // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept // these malleable signatures as well. if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) { return (address(0), RecoverError.InvalidSignatureS, s); } // If the signature is valid (and not malleable), return the signer address address signer = ecrecover(hash, v, r, s); if (signer == address(0)) { return (address(0), RecoverError.InvalidSignature, bytes32(0)); } return (signer, RecoverError.NoError, bytes32(0)); } /** * @dev Overload of {ECDSA-recover} that receives the `v`, * `r` and `s` signature fields separately. */ function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) { (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, v, r, s); _throwError(error, errorArg); return recovered; } /** * @dev Optionally reverts with the corresponding custom error according to the `error` argument provided. */ function _throwError(RecoverError error, bytes32 errorArg) private pure { if (error == RecoverError.NoError) { return; // no error: do nothing } else if (error == RecoverError.InvalidSignature) { revert ECDSAInvalidSignature(); } else if (error == RecoverError.InvalidSignatureLength) { revert ECDSAInvalidSignatureLength(uint256(errorArg)); } else if (error == RecoverError.InvalidSignatureS) { revert ECDSAInvalidSignatureS(errorArg); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/MessageHashUtils.sol) pragma solidity ^0.8.20; import {Strings} from "../Strings.sol"; /** * @dev Signature message hash utilities for producing digests to be consumed by {ECDSA} recovery or signing. * * The library provides methods for generating a hash of a message that conforms to the * https://eips.ethereum.org/EIPS/eip-191[EIP 191] and https://eips.ethereum.org/EIPS/eip-712[EIP 712] * specifications. */ library MessageHashUtils { /** * @dev Returns the keccak256 digest of an EIP-191 signed data with version * `0x45` (`personal_sign` messages). * * The digest is calculated by prefixing a bytes32 `messageHash` with * `"\x19Ethereum Signed Message:\n32"` and hashing the result. It corresponds with the * hash signed when using the https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] JSON-RPC method. * * NOTE: The `messageHash` parameter is intended to be the result of hashing a raw message with * keccak256, although any bytes32 value can be safely used because the final digest will * be re-hashed. * * See {ECDSA-recover}. */ function toEthSignedMessageHash(bytes32 messageHash) internal pure returns (bytes32 digest) { /// @solidity memory-safe-assembly assembly { mstore(0x00, "\x19Ethereum Signed Message:\n32") // 32 is the bytes-length of messageHash mstore(0x1c, messageHash) // 0x1c (28) is the length of the prefix digest := keccak256(0x00, 0x3c) // 0x3c is the length of the prefix (0x1c) + messageHash (0x20) } } /** * @dev Returns the keccak256 digest of an EIP-191 signed data with version * `0x45` (`personal_sign` messages). * * The digest is calculated by prefixing an arbitrary `message` with * `"\x19Ethereum Signed Message:\n" + len(message)` and hashing the result. It corresponds with the * hash signed when using the https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] JSON-RPC method. * * See {ECDSA-recover}. */ function toEthSignedMessageHash(bytes memory message) internal pure returns (bytes32) { return keccak256(bytes.concat("\x19Ethereum Signed Message:\n", bytes(Strings.toString(message.length)), message)); } /** * @dev Returns the keccak256 digest of an EIP-191 signed data with version * `0x00` (data with intended validator). * * The digest is calculated by prefixing an arbitrary `data` with `"\x19\x00"` and the intended * `validator` address. Then hashing the result. * * See {ECDSA-recover}. */ function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) { return keccak256(abi.encodePacked(hex"19_00", validator, data)); } /** * @dev Returns the keccak256 digest of an EIP-712 typed data (EIP-191 version `0x01`). * * The digest is calculated from a `domainSeparator` and a `structHash`, by prefixing them with * `\x19\x01` and hashing the result. It corresponds to the hash signed by the * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] JSON-RPC method as part of EIP-712. * * See {ECDSA-recover}. */ function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 digest) { /// @solidity memory-safe-assembly assembly { let ptr := mload(0x40) mstore(ptr, hex"19_01") mstore(add(ptr, 0x02), domainSeparator) mstore(add(ptr, 0x22), structHash) digest := keccak256(ptr, 0x42) } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/math/Math.sol) pragma solidity ^0.8.20; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { /** * @dev Muldiv operation overflow. */ error MathOverflowedMulDiv(); enum Rounding { Floor, // Toward negative infinity Ceil, // Toward positive infinity Trunc, // Toward zero Expand // Away from zero } /** * @dev Returns the addition of two unsigned integers, with an overflow flag. */ function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { uint256 c = a + b; if (c < a) return (false, 0); return (true, c); } } /** * @dev Returns the subtraction of two unsigned integers, with an overflow flag. */ function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b > a) return (false, 0); return (true, a - b); } } /** * @dev Returns the multiplication of two unsigned integers, with an overflow flag. */ function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { // Gas optimization: this is cheaper than requiring 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522 if (a == 0) return (true, 0); uint256 c = a * b; if (c / a != b) return (false, 0); return (true, c); } } /** * @dev Returns the division of two unsigned integers, with a division by zero flag. */ function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a / b); } } /** * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag. */ function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) { unchecked { if (b == 0) return (false, 0); return (true, a % b); } } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds towards infinity instead * of rounding towards zero. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { if (b == 0) { // Guarantee the same behavior as in a regular Solidity division. return a / b; } // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or * denominator == 0. * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by * Uniswap Labs also under MIT license. */ function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0 = x * y; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { // Solidity will revert if denominator == 0, unlike the div opcode on its own. // The surrounding unchecked block does not change this fact. // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic. return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. if (denominator <= prod1) { revert MathOverflowedMulDiv(); } /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. // Always >= 1. See https://cs.stackexchange.com/q/138556/92363. uint256 twos = denominator & (0 - denominator); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also // works in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded * towards zero. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. // // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` // // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1 << (log2(a) >> 1); // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + (unsignedRoundsUp(rounding) && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2 of a positive value rounded towards zero. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 128; } if (value >> 64 > 0) { value >>= 64; result += 64; } if (value >> 32 > 0) { value >>= 32; result += 32; } if (value >> 16 > 0) { value >>= 16; result += 16; } if (value >> 8 > 0) { value >>= 8; result += 8; } if (value >> 4 > 0) { value >>= 4; result += 4; } if (value >> 2 > 0) { value >>= 2; result += 2; } if (value >> 1 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + (unsignedRoundsUp(rounding) && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10 of a positive value rounded towards zero. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10 ** 64) { value /= 10 ** 64; result += 64; } if (value >= 10 ** 32) { value /= 10 ** 32; result += 32; } if (value >= 10 ** 16) { value /= 10 ** 16; result += 16; } if (value >= 10 ** 8) { value /= 10 ** 8; result += 8; } if (value >= 10 ** 4) { value /= 10 ** 4; result += 4; } if (value >= 10 ** 2) { value /= 10 ** 2; result += 2; } if (value >= 10 ** 1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + (unsignedRoundsUp(rounding) && 10 ** result < value ? 1 : 0); } } /** * @dev Return the log in base 256 of a positive value rounded towards zero. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 16; } if (value >> 64 > 0) { value >>= 64; result += 8; } if (value >> 32 > 0) { value >>= 32; result += 4; } if (value >> 16 > 0) { value >>= 16; result += 2; } if (value >> 8 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 256, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + (unsignedRoundsUp(rounding) && 1 << (result << 3) < value ? 1 : 0); } } /** * @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers. */ function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) { return uint8(rounding) % 2 == 1; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/math/SignedMath.sol) pragma solidity ^0.8.20; /** * @dev Standard signed math utilities missing in the Solidity language. */ library SignedMath { /** * @dev Returns the largest of two signed numbers. */ function max(int256 a, int256 b) internal pure returns (int256) { return a > b ? a : b; } /** * @dev Returns the smallest of two signed numbers. */ function min(int256 a, int256 b) internal pure returns (int256) { return a < b ? a : b; } /** * @dev Returns the average of two signed numbers without overflow. * The result is rounded towards zero. */ function average(int256 a, int256 b) internal pure returns (int256) { // Formula from the book "Hacker's Delight" int256 x = (a & b) + ((a ^ b) >> 1); return x + (int256(uint256(x) >> 255) & (a ^ b)); } /** * @dev Returns the absolute unsigned value of a signed value. */ function abs(int256 n) internal pure returns (uint256) { unchecked { // must be unchecked in order to support `n = type(int256).min` return uint256(n >= 0 ? n : -n); } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.21; import { IInfinexProtocolConfigBeacon } from "src/interfaces/beacons/IInfinexProtocolConfigBeacon.sol"; /** * @title Account storage struct */ library Account { struct InitializableStorage { uint64 _initialized; bool _initializing; } struct Data { address infinexProtocolConfigBeacon; // Address of the Infinex Protocol Config Beacon uint256 referralTokenId; // ID of the referral token bool upgrading; // Flag to indicate if the account is upgrading } /*/////////////////////////////////////////////////////////////// EVENTS / ERRORS ///////////////////////////////////////////////////////////////*/ event Initialized(uint64 version); error InvalidInitialization(); /*/////////////////////////////////////////////////////////////// VIEW FUNCTIONS ///////////////////////////////////////////////////////////////*/ /** * @dev Returns the account stored at the specified account id. */ function getStorage() internal pure returns (Data storage data) { bytes32 s = keccak256(abi.encode("io.infinex.AccountStorage")); assembly { data.slot := s } } /** * @notice Get the Infinex Protocol Config * @return The Infinex Protocol Config Beacon */ function _infinexProtocolConfig() internal view returns (IInfinexProtocolConfigBeacon) { Data storage data = getStorage(); return IInfinexProtocolConfigBeacon(data.infinexProtocolConfigBeacon); } /** * @notice Get the referral token ID * @return The referral token ID */ function _referralTokenId() internal view returns (uint256) { Data storage data = getStorage(); return data.referralTokenId; } /** * @notice Get the upgrading flag * @return The upgrading flag */ function _upgrading() internal view returns (bool) { Data storage data = getStorage(); return data.upgrading; } /*/////////////////////////////////////////////////////////////// MUTATIVE FUNCTIONS ///////////////////////////////////////////////////////////////*/ /** * @notice Sets the initialized version of the contract. * @param _version The initialized version as a uint64 value. */ function _setInitializedVersion(uint64 _version) internal { InitializableStorage storage initializableStorage; // storage slot comes from OZ proxy/utils/Initializable.sol bytes32 INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00; //#gitleaks:allow assembly { initializableStorage.slot := INITIALIZABLE_STORAGE } initializableStorage._initialized = _version; emit Initialized(_version); } /** * @notice Set the upgrading flag for the account. * @param _isUpgrading The value to set for the upgrading flag. */ function _setUpgrading(bool _isUpgrading) internal { Data storage data = getStorage(); data.upgrading = _isUpgrading; } function _setInfinexProtocolConfigBeacon(address _infinexProtocolConfigBeacon) internal { Data storage data = getStorage(); data.infinexProtocolConfigBeacon = _infinexProtocolConfigBeacon; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.21; /** * @title Cosigning related storage struct and functions */ library Cosigning { struct Data { mapping(uint248 => uint256) nonces; // Mapping of nonces used by the platform cosigner } bytes32 internal constant _TRANSFER_REQUEST_TYPEHASH = keccak256( "TransferRequest(bytes4 selector,address destination,address token,uint256 nonStandardIndex,uint256 tokenId,uint256 amount,uint256[] amounts,uint256[] tokenIds,bytes data,uint256 nonce)" ); bytes32 internal constant _RECOVERY_REQUEST_TYPEHASH = keccak256("RecoveryRequest(bytes4 selector,address newFundsRecoveryAddress,uint256 nonce)"); /*/////////////////////////////////////////////////////////////// EVENTS ///////////////////////////////////////////////////////////////*/ event CosigningNonceConsumed(uint256 nonce); /*/////////////////////////////////////////////////////////////// VIEW FUNCTIONS ///////////////////////////////////////////////////////////////*/ /** * @dev Returns the stored at the specified account id. */ function getStorage() internal pure returns (Data storage data) { bytes32 s = keccak256(abi.encode("io.infinex.Transfer")); assembly { data.slot := s } } /** * @notice Check if the provided nonce is valid * @param _nonce The nonce to check * @return A boolean indicating if the nonce is valid */ function _isValidNonce(uint256 _nonce) internal view returns (bool) { uint256 bitmap = getStorage().nonces[uint248(_nonce >> 8)]; return (bitmap & (1 << (_nonce & 0xFF))) == 0; } /** * @notice Consumes a nonce, marking it as used * @param _nonce The nonce to consume */ function _consumeNonce(uint256 _nonce) internal { emit CosigningNonceConsumed(_nonce); getStorage().nonces[uint248(_nonce >> 8)] |= (1 << (_nonce & 0xFF)); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.21; import { MessageHashUtils } from "@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol"; library EIP712 { bytes32 private constant TYPE_HASH = keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"); /// @custom:storage-location erc7201:openzeppelin.storage.EIP712 struct EIP712Storage { /// @custom:oz-renamed-from _HASHED_NAME bytes32 _hashedName; /// @custom:oz-renamed-from _HASHED_VERSION bytes32 _hashedVersion; string _name; string _version; } function _getEIP712Storage() private pure returns (EIP712Storage storage data) { bytes32 s = keccak256(abi.encode("io.infinex.EIP712")); assembly { data.slot := s } } /** * @dev Initializes the domain separator and parameter caches. * * The meaning of `name` and `version` is specified in * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]: * * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol. * - `version`: the current major version of the signing domain. * * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart * contract upgrade]. */ function __EIP712_init(string memory name, string memory version) internal { __EIP712_init_unchained(name, version); } function __EIP712_init_unchained(string memory name, string memory version) internal { EIP712Storage storage $ = _getEIP712Storage(); $._name = name; $._version = version; // Reset prior values in storage if upgrading $._hashedName = 0; $._hashedVersion = 0; } /** * @dev Returns the domain separator for the current chain. */ function _domainSeparatorV4() internal view returns (bytes32) { return _buildDomainSeparator(); } function _buildDomainSeparator() private view returns (bytes32) { return keccak256(abi.encode(TYPE_HASH, _EIP712NameHash(), _EIP712VersionHash(), block.chainid, address(this))); } /** * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this * function returns the hash of the fully encoded EIP712 message for this domain. * * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example: * * ```solidity * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode( * keccak256("Mail(address to,string contents)"), * mailTo, * keccak256(bytes(mailContents)) * ))); * address signer = ECDSA.recover(digest, signature); * ``` */ function _hashTypedDataV4(bytes32 structHash) internal view returns (bytes32) { return MessageHashUtils.toTypedDataHash(_domainSeparatorV4(), structHash); } /** * @dev See {IERC-5267}. */ function eip712Domain() internal view returns ( bytes1 fields, string memory name, string memory version, uint256 chainId, address verifyingContract, bytes32 salt, uint256[] memory extensions ) { EIP712Storage storage $ = _getEIP712Storage(); // If the hashed name and version in storage are non-zero, the contract hasn't been properly initialized // and the EIP712 domain is not reliable, as it will be missing name and version. // solhint-disable-next-line gas-custom-errors require($._hashedName == 0 && $._hashedVersion == 0, "EIP712: Uninitialized"); return ( hex"0f", // 01111 _EIP712Name(), _EIP712Version(), block.chainid, address(this), bytes32(0), new uint256[](0) ); } /** * @dev The name parameter for the EIP712 domain. * * NOTE: This function reads from storage by default, but can be redefined to return a constant value if gas costs * are a concern. */ function _EIP712Name() internal view returns (string memory) { EIP712Storage storage $ = _getEIP712Storage(); return $._name; } /** * @dev The version parameter for the EIP712 domain. * * NOTE: This function reads from storage by default, but can be redefined to return a constant value if gas costs * are a concern. */ function _EIP712Version() internal view returns (string memory) { EIP712Storage storage $ = _getEIP712Storage(); return $._version; } /** * @dev The hash of the name parameter for the EIP712 domain. * * NOTE: In previous versions this function was virtual. In this version you should override `_EIP712Name` instead. */ function _EIP712NameHash() internal view returns (bytes32) { EIP712Storage storage $ = _getEIP712Storage(); string memory name = _EIP712Name(); if (bytes(name).length > 0) { return keccak256(bytes(name)); } else { // If the name is empty, the contract may have been upgraded without initializing the new storage. // We return the name hash in storage if non-zero, otherwise we assume the name is empty by design. bytes32 hashedName = $._hashedName; if (hashedName != 0) { return hashedName; } else { return keccak256(""); } } } /** * @dev The hash of the version parameter for the EIP712 domain. * * NOTE: In previous versions this function was virtual. In this version you should override `_EIP712Version` instead. */ function _EIP712VersionHash() internal view returns (bytes32) { EIP712Storage storage $ = _getEIP712Storage(); string memory version = _EIP712Version(); if (bytes(version).length > 0) { return keccak256(bytes(version)); } else { // If the version is empty, the contract may have been upgraded without initializing the new storage. // We return the version hash in storage if non-zero, otherwise we assume the version is empty by design. bytes32 hashedVersion = $._hashedVersion; if (hashedVersion != 0) { return hashedVersion; } else { return keccak256(""); } } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.21; import { MessageHashUtils } from "@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol"; import { Error } from "src/libraries/Error.sol"; /** * @title Security keys storage and functions */ library SecurityKeys { using MessageHashUtils for bytes32; // slither-disable-next-line constable-states,unused-state bytes32 internal constant _SIGNATURE_REQUEST_TYPEHASH = keccak256( "Request(address _address,address _address2,uint256 _uint256,bytes32 _nonce,uint32 _uint32,bool _bool,bytes4 _selector)" ); bytes4 internal constant EIP1271_MAGIC_VALUE = 0x1626ba7e; struct Data { mapping(bytes32 => bool) nonces; // Mapping of nonces mapping(address => bool) operationKeys; mapping(address => bool) recoveryKeys; mapping(address => bool) sudoKeys; uint16 sudoKeysCounter; } /*/////////////////////////////////////////////////////////////// EVENTS / ERRORS ///////////////////////////////////////////////////////////////*/ event NonceConsumed(bytes32 nonce); event OperationKeyStatusSet(address operationKey, bool isValid); event RecoveryKeyStatusSet(address recoveryKey, bool isValid); event SudoKeyStatusSet(address sudoKey, bool isValid); /** * @dev Returns the account stored at the specified account id. */ function getStorage() internal pure returns (Data storage data) { bytes32 s = keccak256(abi.encode("io.infinex.SecurityKeys")); assembly { data.slot := s } } /*/////////////////////////////////////////////////////////////// VIEW FUNCTIONS ///////////////////////////////////////////////////////////////*/ /** * @notice Check if the provided operation key is valid * @param _operationKey The operation key to check * @return A boolean indicating if the operation key is valid */ function _isValidOperationKey(address _operationKey) internal view returns (bool) { Data storage data = getStorage(); return data.operationKeys[_operationKey]; } /** * @notice Check if the provided recovery key is valid * @param _recoveryKey The recovery key to check * @return A boolean indicating if the recovery key is valid */ function _isValidRecoveryKey(address _recoveryKey) internal view returns (bool) { Data storage data = getStorage(); return data.recoveryKeys[_recoveryKey]; } /** * @notice Check if the provided sudo key is valid * @param _sudoKey The sudo key to check * @return A boolean indicating if the sudo key is valid */ function _isValidSudoKey(address _sudoKey) internal view returns (bool) { Data storage data = getStorage(); return data.sudoKeys[_sudoKey]; } /** * @notice Check if the provided nonce is valid * @param _nonce The nonce to check * @return A boolean indicating if the nonce is valid */ function _isValidNonce(bytes32 _nonce) internal view returns (bool) { Data storage data = getStorage(); return !data.nonces[_nonce]; } /*/////////////////////////////////////////////////////////////// MUTATIVE FUNCTIONS ///////////////////////////////////////////////////////////////*/ /** * @notice Set an operation key for the account * @param _operationKey The operation key address to be set * @param _isValid Whether the key is to be set as valid or invalid */ function _setOperationKeyStatus(address _operationKey, bool _isValid) internal { Data storage data = getStorage(); if (_operationKey == address(0)) revert Error.NullAddress(); if (data.operationKeys[_operationKey]) { if (_isValid) revert Error.KeyAlreadyValid(); } else { if (!_isValid) revert Error.KeyAlreadyInvalid(); } emit OperationKeyStatusSet(_operationKey, _isValid); data.operationKeys[_operationKey] = _isValid; } /** * @notice Set a new recovery key for the account * @param _recoveryKey The recovery key address to be set * @param _isValid Whether the key is to be set as valid or invalid */ function _setRecoveryKeyStatus(address _recoveryKey, bool _isValid) internal { Data storage data = getStorage(); if (_recoveryKey == address(0)) revert Error.NullAddress(); if (data.recoveryKeys[_recoveryKey]) { if (_isValid) revert Error.KeyAlreadyValid(); } else { if (!_isValid) revert Error.KeyAlreadyInvalid(); } emit RecoveryKeyStatusSet(_recoveryKey, _isValid); data.recoveryKeys[_recoveryKey] = _isValid; } /** * @notice Set a sudo key for the account * @param _sudoKey The sudo key address to be set * @param _isValid Whether the key is to be set as valid or invalid */ function _setSudoKeyStatus(address _sudoKey, bool _isValid) internal { Data storage data = getStorage(); if (_sudoKey == address(0)) revert Error.NullAddress(); if (data.sudoKeys[_sudoKey]) { if (_isValid) revert Error.KeyAlreadyValid(); if (data.sudoKeysCounter == 1) revert Error.CannotRemoveLastKey(); --data.sudoKeysCounter; } else { if (!_isValid) revert Error.KeyAlreadyInvalid(); ++data.sudoKeysCounter; } emit SudoKeyStatusSet(_sudoKey, _isValid); data.sudoKeys[_sudoKey] = _isValid; } /** * @notice Consumes a nonce, marking it as used * @param _nonce The nonce to consume * @dev Reverts if nonce has already been consumed. */ function _consumeNonce(bytes32 _nonce) internal returns (bool) { Data storage data = getStorage(); if (data.nonces[_nonce]) revert Error.InvalidNonce(_nonce); emit NonceConsumed(_nonce); data.nonces[_nonce] = true; return true; } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.21; import { ECDSA } from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; import { IInfinexProtocolConfigBeacon } from "src/interfaces/beacons/IInfinexProtocolConfigBeacon.sol"; import { Account } from "src/accounts/storage/Account.sol"; import { SecurityKeys } from "src/accounts/storage/SecurityKeys.sol"; library SecurityUtils { error InvalidSudoKeySignature(); error InvalidPlatformSignature(); /** * @notice Validates the co-signature of the sudo key and platform key. * @param _requestHash The hash of the request. * @param _sudoKeySignature The signature of the sudo key. * @param _platformSignature The signature of the platform key. */ function _validateCoSignature(bytes32 _requestHash, bytes calldata _sudoKeySignature, bytes calldata _platformSignature) internal view { if (!SecurityKeys._isValidSudoKey(ECDSA.recover(_requestHash, _sudoKeySignature))) { revert InvalidSudoKeySignature(); } IInfinexProtocolConfigBeacon infinexBeacon = IInfinexProtocolConfigBeacon(Account._infinexProtocolConfig()); if (infinexBeacon.platformKey() != ECDSA.recover(_requestHash, _platformSignature)) { revert InvalidPlatformSignature(); } } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.21; interface ITransferModule { /*/////////////////////////////////////////////////////////////// STRUCTS ///////////////////////////////////////////////////////////////*/ /** * @notice A struct that contains the transfer request data. */ struct TransferRequest { bytes4 selector; address destination; address token; uint256 nonStandardIndex; uint256 tokenId; uint256 amount; uint256[] amounts; uint256[] tokenIds; bytes data; uint256 nonce; } /*/////////////////////////////////////////////////////////////// ERRORS ///////////////////////////////////////////////////////////////*/ error InvalidNonce(); error InvalidRequest(); error ZeroValue(); error NullAddress(); error InvalidLength(); error EtherTransferFailed(); /*/////////////////////////////////////////////////////////////// EVENTS ///////////////////////////////////////////////////////////////*/ event EtherTransferred(address indexed destination, uint256 amount); event ERC20Transferred(address indexed token, address indexed destination, uint256 amount); event ERC721Transferred(address indexed token, address indexed destination, uint256 tokenId); event ERC721ABatchTransferred(address indexed token, address indexed destination, uint256 amount); event ERC1155Transferred(address indexed token, address indexed destination, uint256 tokenId, uint256 amount, bytes data); event ERC1155BatchTransferred( address indexed token, address indexed destination, uint256[] tokenIds, uint256[] amounts, bytes data ); event NonStandardNFTTransferred(address indexed token, address indexed destination, uint256 tokenId, uint256 nonStandardIndex); event TransferFeeTaken(address indexed token, uint256 fee); /*/////////////////////////////////////////////////////////////// MUTATIVE FUNCTIONS ///////////////////////////////////////////////////////////////*/ /** * @notice Transfers ether to a destination address. * @param _request The transfer request. * @param _sudoKeySignature The signature of the sudo key. * @param _platformSignature The signature of the platform key. */ function transferEther(TransferRequest calldata _request, bytes calldata _sudoKeySignature, bytes calldata _platformSignature) external; /** * @notice Transfers an ERC20 token to a destination address. * @param _request The transfer request. * @param _sudoKeySignature The signature of the sudo key. * @param _platformSignature The signature of the platform key. */ function transferERC20(TransferRequest calldata _request, bytes calldata _sudoKeySignature, bytes calldata _platformSignature) external; /** * @notice Transfers an ERC721 token to a destination address. * @param _request The transfer request. * @param _sudoKeySignature The signature of the sudo key. * @param _platformSignature The signature of the platform key. */ function transferERC721(TransferRequest calldata _request, bytes calldata _sudoKeySignature, bytes calldata _platformSignature) external; /** * @notice Transfers an ERC721A batch to a destination address. * @param _request The transfer request. * @param _sudoKeySignature The signature of the sudo key. * @param _platformSignature The signature of the platform key. */ function transferERC721ABatch( TransferRequest calldata _request, bytes calldata _sudoKeySignature, bytes calldata _platformSignature ) external; /** * @notice Transfers an ERC1155 token to a destination address. * @param _request The transfer request. * @param _sudoKeySignature The signature of the sudo key. * @param _platformSignature The signature of the platform key. */ function transferERC1155(TransferRequest calldata _request, bytes calldata _sudoKeySignature, bytes calldata _platformSignature) external; /** * @notice Transfers an ERC1155 batch to a destination address. * @param _request The transfer request. * @param _sudoKeySignature The signature of the sudo key. * @param _platformSignature The signature of the platform key. */ function transferERC1155Batch( TransferRequest calldata _request, bytes calldata _sudoKeySignature, bytes calldata _platformSignature ) external; /** * @notice Transfers a non-standard token to a destination address. * @param _request The transfer request. * @param _sudoKeySignature The signature of the sudo key. * @param _platformSignature The signature of the platform key. */ function transferNonStandardToken( TransferRequest calldata _request, bytes calldata _sudoKeySignature, bytes calldata _platformSignature ) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.21; /** * @title IInfinexProtocolConfigBeacon * @notice Interface for the Infinex Protocol Config Beacon contract. */ interface IInfinexProtocolConfigBeacon { /*/////////////////////////////////////////////////////////////// STRUCTS ///////////////////////////////////////////////////////////////*/ /** * @notice Struct containing the constructor arguments for the InfinexProtocolConfigBeacon contract * @param trustedForwarder Address of the trusted forwarder contract * @param appRegistry Address of the app registry contract * @param latestAccountImplementation Address of the latest account implementation contract * @param initialProxyImplementation Address of the initial proxy implementation contract * @param revenuePool Address of the revenue pool contract * @param USDC Address of the USDC token contract * @param circleBridge Address of the Circle bridge contract * @param circleMinter Address of the Circle minter contract, used for checking the maximum bridge amount * @param wormholeCircleBridge Address of the Wormhole Circle bridge contract * @param defaultDestinationCCTPDomain the CCTP domain of the default destination chain. * @param defaultDestinationWormholeChainId the Wormhole chain id of the default destination chain. * @param supportedEVMCCTPDomains the EVM CCTP domains supported for bridging * @param supportedEVMWormholeChainIds the EVM Wormhole chain ids supported for bridging * @param solanaWalletSeed The salt used to generate the Solana account (fixed seed "wallet") * @param solanaFixedPDASeed The salt used to generate the PDA (Program Derived Address) * @param solanaWalletProgramAddress The Solana Wallet Program Address * @param solanaTokenMintAddress The Solana token mint address * @param solanaTokenProgramAddress The Solana token program address * @param solanaAssociatedTokenProgramAddress The Solana ATA program address * @param wormholeCore The Wormhole core contract address */ struct InfinexBeaconConstructorArgs { address trustedForwarder; address appRegistry; address latestAccountImplementation; address initialProxyImplementation; address revenuePool; address USDC; address circleBridge; address circleMinter; address wormholeCircleBridge; uint32 defaultDestinationCCTPDomain; uint16 defaultDestinationWormholeChainId; uint32[] supportedEVMCCTPDomains; uint16[] supportedEVMWormholeChainIds; uint32 solanaCCTPDestinationDomain; bytes solanaWalletSeed; bytes solanaFixedPDASeed; bytes32 solanaWalletProgramAddress; bytes32 solanaTokenMintAddress; bytes32 solanaTokenProgramAddress; bytes32 solanaAssociatedTokenProgramAddress; address wormholeCore; } /** * @notice Struct containing both Circle and Wormhole bridge configuration * @param circleBridge Address of the Circle bridge contract * @param circleMinter Address of the Circle minter contract, used for checking the maximum bridge amount * @param wormholeCircleBridge Address of the Wormhole Circle bridge contract * @param defaultDestinationCCTPDomain the CCTP domain of the default destination chain. * @param defaultDestinationWormholeChainId the Wormhole chain id of the default destination chain. * @dev Chain id is the official chain id for evm chains and documented one for non evm chains. */ struct BridgeConfiguration { address circleBridge; address circleMinter; address wormholeCircleBridge; uint32 defaultDestinationCCTPDomain; uint16 defaultDestinationWormholeChainId; } /** * @notice The addresses for implementations referenced by the beacon * @param initialProxyImplementation The initial proxy implementation address used for account creation to ensure identical cross chain addresses * @param latestAccountImplementation The latest account implementation address, used for account upgrades and new accounts * @param latestInfinexProtocolConfigBeacon The latest Infinex Protocol config beacon address, used for pointing account updates to the latest beacon */ struct ImplementationAddresses { address initialProxyImplementation; address latestAccountImplementation; address latestInfinexProtocolConfigBeacon; } /** * @notice Struct containing the Solana configuration needed to verify addresses * @param walletSeed The salt used to generate the Solana account (fixed seed "wallet") * @param fixedPDASeed The salt used to generate the PDA (Program Derived Address) * @param walletProgramAddress The Solana Wallet Program Address * @param tokenMintAddress The Solana token mint address * @param tokenProgramAddress The Solana token address * @param associatedTokenProgramAddress The Solana ATA program address */ struct SolanaConfiguration { bytes walletSeed; bytes fixedPDASeed; bytes32 walletProgramAddress; bytes32 tokenMintAddress; bytes32 tokenProgramAddress; bytes32 associatedTokenProgramAddress; } /*/////////////////////////////////////////////////////////////// EVENTS ///////////////////////////////////////////////////////////////*/ event LatestAccountImplementationSet(address latestAccountImplementation); event InitialProxyImplementationSet(address initialProxyImplementation); event AppRegistrySet(address appRegistry); event RevenuePoolSet(address revenuePool); event USDCAddressSet(address USDC); event CircleBridgeParamsSet(address circleBridge, address circleMinter, uint32 defaultDestinationCCTPDomain); event WormholeCircleBridgeParamsSet(address wormholeCircleBridge, uint16 defaultDestinationWormholeChainId); event LatestInfinexProtocolConfigBeaconSet(address latestInfinexProtocolConfigBeacon); event WithdrawalFeeUSDCSet(uint256 withdrawalFee); event FundsRecoveryStatusSet(bool status); event MinimumUSDCBridgeAmountSet(uint256 amount); event WormholeDestinationDomainSet(uint256 indexed chainId, uint16 destinationDomain); event CircleDestinationDomainSet(uint256 indexed chainId, uint32 destinationDomain); event TrustedRecoveryKeeperSet(address indexed trustedRecoveryKeeper, bool isTrusted); event PlatformKeySet(address indexed platformKey); event SupportedEVMCCTPDomainsSet(uint32[] supportedEVMCCTPDomains); event SupportedEVMWormholeChainIdsSet(uint16[] supportedWormholeChainIds); event SolanaCCTPDestinationDomainSet(uint32 solanaCCTPDestinationDomain); /*/////////////////////////////////////////////////////////////// VARIABLES ///////////////////////////////////////////////////////////////*/ /** * @notice Gets the timestamp the beacon was deployed * @return The timestamp the beacon was deployed */ function CREATED_AT() external view returns (uint256); /** * @notice Gets the trusted forwarder address * @return The address of the trusted forwarder */ function TRUSTED_FORWARDER() external view returns (address); /** * @notice Gets the app registry address * @return The address of the app registry */ function appRegistry() external view returns (address); /** * @notice Gets the platform key address * @return The address of the platform key */ function platformKey() external view returns (address); /** * @notice A platform wide feature flag to enable or disable funds recovery, false by default * @return True if funds recovery is active */ function fundsRecoveryActive() external view returns (bool); /** * @notice Gets the revenue pool address * @return The address of the revenue pool */ function revenuePool() external view returns (address); /** * @notice Gets the USDC amount to charge as withdrawal fee * @return The withdrawal fee in USDC's decimals */ function withdrawalFeeUSDC() external view returns (uint256); /** * @notice Retrieves the USDC address. * @return The address of the USDC token */ function USDC() external view returns (address); /** * @notice Retrieves the circle CCTP destination domain for solana. * @return The CCTP destination domain for solana. */ function solanaCCTPDestinationDomain() external view returns (uint32); /** * @notice Retrieves the Wormhole core address. * @return The address of the Wormhole core contract. */ function WORMHOLE_CORE() external view returns (address); /*/////////////////////////////////////////////////////////////// VIEW FUNCTIONS ///////////////////////////////////////////////////////////////*/ /** * @notice Checks if an address is a trusted recovery keeper. * @param _address The address to check. * @return True if the address is a trusted recovery keeper, false otherwise. */ function isTrustedRecoveryKeeper(address _address) external view returns (bool); /** * @notice Retrieves the Circle Bridge parameters. * @return circleBridge The address of the Circle Bridge contract. * @return circleMinter The address of the TokenMinter contract. * @return defaultDestinationCCTPDomain The CCTP domain of the default destination chain. */ function getCircleBridgeParams() external view returns (address circleBridge, address circleMinter, uint32 defaultDestinationCCTPDomain); /** * @notice Retrieves the Circle Bridge address. * @return The address of the Circle Bridge contract. */ function getCircleBridge() external view returns (address); /** * @notice Retrieves the Circle TokenMinter address. * @return The address of the Circle TokenMinter contract. */ function getCircleMinter() external view returns (address); /** * @notice Retrieves the CCTP domain of the destination chain. * @return The CCTP domain of the default destination chain. */ function getDefaultDestinationCCTPDomain() external view returns (uint32); /** * @notice Retrieves the parameters required for Wormhole bridging. * @return The address of the Wormhole Circle Bridge contract. * @return The default wormhole destination domain for the circle bridge contract. */ function getWormholeCircleBridgeParams() external view returns (address, uint16); /** * @notice Retrieves the Wormhole Circle Bridge address. * @return The address of the Wormhole Circle Bridge contract. */ function getWormholeCircleBridge() external view returns (address); /** * @notice Retrieves the Wormhole chain id for Base, or Ethereum Mainnet if deployed on Base. * @return The Wormhole chain id of the default destination chain. */ function getDefaultDestinationWormholeChainId() external view returns (uint16); /** * @notice Gets the latest account implementation address. * @return The address of the latest account implementation. */ function getLatestAccountImplementation() external view returns (address); /** * @notice Gets the initial proxy implementation address. * @return The address of the initial proxy implementation. */ function getInitialProxyImplementation() external view returns (address); /** * @notice The latest Infinex Protocol config beacon address, used for pointing account updates to the latest beacon. * @return The address of the latest Infinex Protocol config beacon. */ function getLatestInfinexProtocolConfigBeacon() external view returns (address); /** * @notice Checks if a CCTP domain is supported for EVM bridging. * @param _cctpDomainId the domain id to check * @return bool if the domain is supported or not. */ function isSupportedEVMCCTPDomain(uint32 _cctpDomainId) external view returns (bool); /** * @notice Checks if a Wormhole chain id is supported for EVM bridging. * @param _wormholeChainId the chain id to check * @return bool if the chain is supported or not. */ function isSupportedEVMWormholeChainId(uint16 _wormholeChainId) external view returns (bool); /** * @notice Returns the Solana configuration * @param walletSeed The salt used to generate the Solana account (fixed seed "wallet") * @param fixedPDASeed The salt used to generate the PDA (Program Derived Address) * @param walletProgramAddress The Solana Wallet Program Address * @param tokenMintAddress The Solana token mint address * @param tokenProgramAddress The Solana token program address * @param associatedTokenProgramAddress The Solana ATA program address */ function getSolanaConfiguration() external view returns ( bytes memory walletSeed, bytes memory fixedPDASeed, bytes32 walletProgramAddress, bytes32 tokenMintAddress, bytes32 tokenProgramAddress, bytes32 associatedTokenProgramAddress ); /*/////////////////////////////////////////////////////////////// MUTATIVE FUNCTIONS ///////////////////////////////////////////////////////////////*/ /** * @notice Sets the address of the app registry contract. * @param _appRegistry The address of the app registry contract. */ function setAppRegistry(address _appRegistry) external; /** * @notice Sets or unsets an address as a trusted recovery keeper. * @param _address The address to set or unset. * @param _isTrusted Boolean indicating whether to set or unset the address as a trusted recovery keeper. */ function setTrustedRecoveryKeeper(address _address, bool _isTrusted) external; /** * @notice Sets the platform key. * @param _platformKey The address to set as the platform key. */ function setPlatformKey(address _platformKey) external; /** * @notice Sets the revenue pool address. * @param _revenuePool The revenue pool address. */ function setRevenuePool(address _revenuePool) external; /** * @notice Sets the USDC amount to charge as withdrawal fee. * @param _withdrawalFeeUSDC The withdrawal fee in USDC's decimals. */ function setWithdrawalFeeUSDC(uint256 _withdrawalFeeUSDC) external; /** * @notice Sets the address of the USDC token contract. * @param _USDC The address of the USDC token contract. * @dev Only the contract owner can call this function. * @dev Throws an error if the provided address is the zero address. */ function setUSDCAddress(address _USDC) external; /** * @notice Sets the parameters for Circle bridging. * @param _circleBridge The address of the Circle Bridge contract. * @param _circleMinter The address of the Circle TokenMinter contract. * @param _defaultDestinationCCTPDomain The CCTP domain of the default destination chain. * @dev Circle Destination Domain can be 0 - Ethereum. */ function setCircleBridgeParams(address _circleBridge, address _circleMinter, uint32 _defaultDestinationCCTPDomain) external; /** * @notice Sets the parameters for Wormhole bridging. * @param _wormholeCircleBridge The address of the Wormhole Circle Bridge contract. * @param _defaultDestinationWormholeChainId The wormhole domain of the default destination chain. */ function setWormholeCircleBridgeParams(address _wormholeCircleBridge, uint16 _defaultDestinationWormholeChainId) external; /** * @notice Sets the initial proxy implementation address. * @param _initialProxyImplementation The initial proxy implementation address. * @dev Throws an error if the provided address is the zero address. */ function setInitialProxyImplementation(address _initialProxyImplementation) external; /** * @notice Sets the latest account implementation address. * @param _latestAccountImplementation The latest account implementation address. * @dev Throws an error if the provided address is the zero address. */ function setLatestAccountImplementation(address _latestAccountImplementation) external; /** * @notice Sets the latest Infinex Protocol Config Beacon. * @param _latestInfinexProtocolConfigBeacon The address of the Infinex Protocol Config Beacon. * @dev Throws an error if the provided address is the zero address. */ function setLatestInfinexProtocolConfigBeacon(address _latestInfinexProtocolConfigBeacon) external; /* * @notice Sets the supported EVM CCTP domains. * @param _supportedEVMCCTPDomains The array of EVM CCTP domains to set. */ function setSupportedEVMCCTPDomains(uint32[] calldata _supportedEVMCCTPDomains) external; /* * @notice Sets the supported Wormhole chain ids. * @param _supportedEVMWormholeChainIds The array of Wormhole chain ids to set. */ function setSupportedEVMWormholeChainIds(uint16[] calldata _supportedEVMWormholeChainIds) external; /** * @notice Sets the solana CCTP destination domain * @param _solanaCCTPDestinationDomain the destination domain for circles CCTP USDC bridge. */ function setSolanaCCTPDestinationDomain(uint32 _solanaCCTPDestinationDomain) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.21; /** * @title ICryptoPunks * @notice Minimal Interface for the crypto punks contract. */ interface ICryptoPunks { function standard() external returns (string memory); function name() external returns (string memory); function symbol() external returns (uint8); function decimals() external returns (uint8); function totalSupply() external returns (uint256); function balanceOf(address _address) external returns (uint256); function punkIndexToAddress(uint256 punkIndex) external view returns (address); function transferPunk(address to, uint256 punkIndex) external; }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.21; /** * @title IEtherRocks * @notice Minimal Interface for the Ether Rocks contract */ interface IEtherRocks { function getRockInfo(uint256 rockNumber) external view returns (address, bool, uint256, uint256); function rockOwningHistory(address _address) external returns (uint256[] memory); function sellRock(uint256 rockNumber, uint256 price) external; function dontSellRock(uint256 rockNumber) external; function giftRock(uint256 rockNumber, address receiver) external; }
// c=< // | // | ////\ 1@2 // @@ | /___\** @@@2 @@@@@@@@@@@@@@@@@@@@@@ // @@@ | |~L~ |* @@@@@@ @@@ @@@@@ @@@@ @@@ @@@@ @@@ @@@@@@@@ @@@@ @@@@ @@@ @@@@@@@@@ @@@@ @@@@ // @@@@@ | \=_/8 @@@@1@@ @@@ @@@@@ @@@@ @@@@ @@@ @@@@@ @@@ @@@@@@@@@ @@@@ @@@@@ @@@@ @@@@@@@@@ @@@@ @@@@ // @@@@@@| _ /| |\__ @@@@@@@@2 @@@ @@@@@ @@@@ @@@@ @@@ @@@@@@@ @@@ @@@@ @@@@ @@@@@@ @@@@ @@@ @@@@@@@ // 1@@@@@@|\ \___/) @@1@@@@@2 ~~~ ~~~~~ @@@@ ~~@@ ~~~ ~~~~~~~~~~~ ~~~~ ~~~~ ~~~~~~~~~~~ ~@@ @@@@@ // 2@@@@@ | \ \ / | @@@@@@2 @@@ @@@@@ @@@@ @@@@ @@@ @@@@@@@@@@@ @@@@@@@@@ @@@@ @@@@@@@@@@@ @@@@@@@@@ @@@@@ // 2@@@@ |_ > <|__ @@1@12 @@@ @@@@@ @@@@ @@@@ @@@ @@@@ @@@@@@ @@@@ @@@@ @@@@ @@@@@@ @@@ @@@@@@@ // @@@@ / _| / \/ \ @@1@ @@@ @@@ @@@@ @@@@ @@@ @@@@ @@@@@ @@@@ @@@@ @@@@ @@@@@ @@@@@@@@@ @@@@ @@@@ // @@ / |^\/ | | @@1 @@@ @@@@ @@@@ @@@ @@@@ @@@ @@@@ @@@@ @@@ @@@@ @@@@@@@@@ @@@@ @@@@ // / / ---- \ \\\= @@ @@@@@@@@@@@@@@@@@@@@@@ // \___/ -------- ~~ @@@ // @@ | | | | -- @@ // ———————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————— // SPDX-License-Identifier: MIT pragma solidity ^0.8.21; library Error { /*/////////////////////////////////////////////////////////////// GENERIC ///////////////////////////////////////////////////////////////*/ error AlreadyExists(); error DoesNotExist(); error Unauthorized(); error InvalidLength(); error NotOwner(); error InvalidCallerContext(); error InvalidChainId(); /*/////////////////////////////////////////////////////////////// ADDRESS ///////////////////////////////////////////////////////////////*/ error ImplementationMismatch(address implementation, address latestImplementation); error InvalidWithdrawalAddress(address to); error NullAddress(); error SameAddress(); error InvalidSolanaAddress(); error AddressAlreadySet(); error InsufficientAllowlistDelay(); /*/////////////////////////////////////////////////////////////// AMOUNT / BALANCE ///////////////////////////////////////////////////////////////*/ error InsufficientBalance(); error InsufficientWithdrawalAmount(uint256 amount); error InsufficientBalanceForFee(uint256 balance, uint256 fee); error InvalidNonce(bytes32 nonce); error ZeroValue(); error EmptyString(); error AmountDeltaZeroValue(); error DecimalsMoreThan18(uint256 decimals); error BridgeMaxAmountExceeded(); error ETHTransferFailed(); error OutOfBounds(); error UnsupportedNonStandardIndex(); /*/////////////////////////////////////////////////////////////// ACCOUNT ///////////////////////////////////////////////////////////////*/ error CreateAccountDisabled(); error InvalidKeysForSalt(); error PredictAddressDisabled(); error FundsRecoveryActivationDeadlinePending(); error InvalidAppAccount(); error InvalidAppBeacon(); error RecoveryAddressNotSet(); /*/////////////////////////////////////////////////////////////// KEY MANAGEMENT ///////////////////////////////////////////////////////////////*/ error InvalidRequest(); error InvalidKeySignature(address from); error KeyAlreadyInvalid(); error KeyAlreadyValid(); error KeyNotFound(); error CannotRemoveLastKey(); /*/////////////////////////////////////////////////////////////// BRIDGING ///////////////////////////////////////////////////////////////*/ error InvalidCCTPDomain(); error InvalidWormholeChainId(); /*/////////////////////////////////////////////////////////////// WORMHOLE ///////////////////////////////////////////////////////////////*/ error UnexpectedResultLength(); error InvalidBlockFinality(); /*/////////////////////////////////////////////////////////////// GAS FEE REBATE ///////////////////////////////////////////////////////////////*/ error InvalidDeductGasFunction(bytes4 sig); /*/////////////////////////////////////////////////////////////// FEATURE FLAGS ///////////////////////////////////////////////////////////////*/ error FundsRecoveryNotActive(); }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.21; import { ICryptoPunks } from "src/interfaces/non-standard-erc721s/ICryptoPunks.sol"; import { IEtherRocks } from "src/interfaces/non-standard-erc721s/IEtherRocks.sol"; /** * @notice A library for handling non-standard tokens. */ library NonStandardToken { error UnsupportedNonStandardIndex(); /** * @notice Transfers a non-standard token. * @param _token The address of the token. * @param _to The address to transfer the token to. * @param _tokenId The ID of the token. * @param _nonStandardIndex The index of the non-standard token. * @dev Reverts if the non-standard index is not supported. */ function transfer(address _token, address _to, uint256 _tokenId, uint256 _nonStandardIndex) internal { if (_nonStandardIndex == 0) { ICryptoPunks(_token).transferPunk(_to, _tokenId); } else if (_nonStandardIndex == 1) { IEtherRocks(_token).giftRock(_tokenId, _to); } else { revert UnsupportedNonStandardIndex(); } } }
{ "optimizer": { "enabled": true, "runs": 200 }, "evmVersion": "shanghai", "remappings": [ "@ensdomains/=lib/ERC721A/node_modules/@ensdomains/", "@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/", "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/", "@pythnetwork/entropy-sdk-solidity/=node_modules/@pythnetwork/entropy-sdk-solidity/", "@synthetixio/core-contracts/=node_modules/@synthetixio/core-contracts/", "@synthetixio/core-modules/=node_modules/@synthetixio/core-modules/", "@synthetixio/main/=node_modules/@synthetixio/main/", "@synthetixio/oracle-manager/=node_modules/@synthetixio/oracle-manager/", "@synthetixio/perps-market/=node_modules/@synthetixio/perps-market/", "@synthetixio/spot-market/=node_modules/@synthetixio/spot-market/", "ERC721A/=lib/ERC721A/contracts/", "cannon-std/=lib/cannon-std/src/", "ds-test/=lib/forge-std/lib/ds-test/src/", "erc4626-tests/=lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/", "eth-gas-reporter/=lib/ERC721A/node_modules/eth-gas-reporter/", "forge-std/=lib/forge-std/src/", "hardhat/=lib/ERC721A/node_modules/hardhat/", "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/", "openzeppelin-contracts/=lib/openzeppelin-contracts/", "solady/=lib/solady/src/", "src/=src/", "test/=test/", "wormhole-circle-integration/=lib/wormhole-circle-integration/evm/src/", "wormhole-solidity-sdk/=lib/wormhole-solidity-sdk/src/", "wormhole/=lib/wormhole-circle-integration/evm/src/" ], "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"AddressInsufficientBalance","type":"error"},{"inputs":[],"name":"ECDSAInvalidSignature","type":"error"},{"inputs":[{"internalType":"uint256","name":"length","type":"uint256"}],"name":"ECDSAInvalidSignatureLength","type":"error"},{"inputs":[{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"ECDSAInvalidSignatureS","type":"error"},{"inputs":[],"name":"EtherTransferFailed","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"inputs":[],"name":"InvalidInitialization","type":"error"},{"inputs":[],"name":"InvalidLength","type":"error"},{"inputs":[],"name":"InvalidNonce","type":"error"},{"inputs":[],"name":"InvalidPlatformSignature","type":"error"},{"inputs":[],"name":"InvalidRequest","type":"error"},{"inputs":[],"name":"InvalidSudoKeySignature","type":"error"},{"inputs":[],"name":"NotInitializing","type":"error"},{"inputs":[],"name":"NullAddress","type":"error"},{"inputs":[],"name":"ReentrancyGuardReentrantCall","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"inputs":[],"name":"UnsupportedNonStandardIndex","type":"error"},{"inputs":[],"name":"ZeroValue","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"nonce","type":"uint256"}],"name":"CosigningNonceConsumed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"destination","type":"address"},{"indexed":false,"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"indexed":false,"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"}],"name":"ERC1155BatchTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"destination","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"}],"name":"ERC1155Transferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"destination","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ERC20Transferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"destination","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"ERC721ABatchTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"destination","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ERC721Transferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"destination","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"EtherTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint64","name":"version","type":"uint64"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"destination","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"nonStandardIndex","type":"uint256"}],"name":"NonStandardNFTTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"fee","type":"uint256"}],"name":"TransferFeeTaken","type":"event"},{"inputs":[{"components":[{"internalType":"bytes4","name":"selector","type":"bytes4"},{"internalType":"address","name":"destination","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"nonStandardIndex","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"uint256","name":"nonce","type":"uint256"}],"internalType":"struct ITransferModule.TransferRequest","name":"_request","type":"tuple"},{"internalType":"bytes","name":"_sudoKeySignature","type":"bytes"},{"internalType":"bytes","name":"_platformKeySignature","type":"bytes"}],"name":"transferERC1155","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"bytes4","name":"selector","type":"bytes4"},{"internalType":"address","name":"destination","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"nonStandardIndex","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"uint256","name":"nonce","type":"uint256"}],"internalType":"struct ITransferModule.TransferRequest","name":"_request","type":"tuple"},{"internalType":"bytes","name":"_sudoKeySignature","type":"bytes"},{"internalType":"bytes","name":"_platformKeySignature","type":"bytes"}],"name":"transferERC1155Batch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"bytes4","name":"selector","type":"bytes4"},{"internalType":"address","name":"destination","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"nonStandardIndex","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"uint256","name":"nonce","type":"uint256"}],"internalType":"struct ITransferModule.TransferRequest","name":"_request","type":"tuple"},{"internalType":"bytes","name":"_sudoKeySignature","type":"bytes"},{"internalType":"bytes","name":"_platformKeySignature","type":"bytes"}],"name":"transferERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"bytes4","name":"selector","type":"bytes4"},{"internalType":"address","name":"destination","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"nonStandardIndex","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"uint256","name":"nonce","type":"uint256"}],"internalType":"struct ITransferModule.TransferRequest","name":"_request","type":"tuple"},{"internalType":"bytes","name":"_sudoKeySignature","type":"bytes"},{"internalType":"bytes","name":"_platformKeySignature","type":"bytes"}],"name":"transferERC721","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"bytes4","name":"selector","type":"bytes4"},{"internalType":"address","name":"destination","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"nonStandardIndex","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"uint256","name":"nonce","type":"uint256"}],"internalType":"struct ITransferModule.TransferRequest","name":"_request","type":"tuple"},{"internalType":"bytes","name":"_sudoKeySignature","type":"bytes"},{"internalType":"bytes","name":"_platformKeySignature","type":"bytes"}],"name":"transferERC721ABatch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"bytes4","name":"selector","type":"bytes4"},{"internalType":"address","name":"destination","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"nonStandardIndex","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"uint256","name":"nonce","type":"uint256"}],"internalType":"struct ITransferModule.TransferRequest","name":"_request","type":"tuple"},{"internalType":"bytes","name":"_sudoKeySignature","type":"bytes"},{"internalType":"bytes","name":"_platformKeySignature","type":"bytes"}],"name":"transferEther","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"bytes4","name":"selector","type":"bytes4"},{"internalType":"address","name":"destination","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"nonStandardIndex","type":"uint256"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256[]","name":"amounts","type":"uint256[]"},{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"uint256","name":"nonce","type":"uint256"}],"internalType":"struct ITransferModule.TransferRequest","name":"_request","type":"tuple"},{"internalType":"bytes","name":"_sudoKeySignature","type":"bytes"},{"internalType":"bytes","name":"_platformKeySignature","type":"bytes"}],"name":"transferNonStandardToken","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
608060405234801561000f575f80fd5b50611e6d8061001d5f395ff3fe608060405234801561000f575f80fd5b506004361061007a575f3560e01c80636955292c116100585780636955292c146100b9578063c9a4324f146100cc578063debe1aa5146100df578063faf6157e146100f2575f80fd5b806301ef26c71461007e578063152acabb146100935780632f0a8b8c146100a6575b5f80fd5b61009161008c3660046119f5565b610105565b005b6100916100a13660046119f5565b6101ec565b6100916100b43660046119f5565b610298565b6100916100c73660046119f5565b610344565b6100916100da3660046119f5565b6103f0565b6100916100ed3660046119f5565b61049c565b6100916101003660046119f5565b610548565b84848484846001600160e01b03195f35166101236020870187611a8b565b6001600160e01b0319161461014b576040516341abc80160e01b815260040160405180910390fd5b6101598561012001356105f4565b61017657604051633ab3447f60e11b815260040160405180910390fd5b5f61018861018387610627565b6107a1565b905061019781868686866107d3565b6101a5866101200135610919565b6101ad610979565b6101b68b6109c3565b6101df60017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0055565b5050505050505050505050565b84848484846001600160e01b03195f351661020a6020870187611a8b565b6001600160e01b03191614610232576040516341abc80160e01b815260040160405180910390fd5b6102408561012001356105f4565b61025d57604051633ab3447f60e11b815260040160405180910390fd5b5f61026a61018387610627565b905061027981868686866107d3565b610287866101200135610919565b61028f610979565b6101b68b610b34565b84848484846001600160e01b03195f35166102b66020870187611a8b565b6001600160e01b031916146102de576040516341abc80160e01b815260040160405180910390fd5b6102ec8561012001356105f4565b61030957604051633ab3447f60e11b815260040160405180910390fd5b5f61031661018387610627565b905061032581868686866107d3565b610333866101200135610919565b61033b610979565b6101b68b610cb0565b84848484846001600160e01b03195f35166103626020870187611a8b565b6001600160e01b0319161461038a576040516341abc80160e01b815260040160405180910390fd5b6103988561012001356105f4565b6103b557604051633ab3447f60e11b815260040160405180910390fd5b5f6103c261018387610627565b90506103d181868686866107d3565b6103df866101200135610919565b6103e7610979565b6101b68b610dbf565b84848484846001600160e01b03195f351661040e6020870187611a8b565b6001600160e01b03191614610436576040516341abc80160e01b815260040160405180910390fd5b6104448561012001356105f4565b61046157604051633ab3447f60e11b815260040160405180910390fd5b5f61046e61018387610627565b905061047d81868686866107d3565b61048b866101200135610919565b610493610979565b6101b68b610eaa565b84848484846001600160e01b03195f35166104ba6020870187611a8b565b6001600160e01b031916146104e2576040516341abc80160e01b815260040160405180910390fd5b6104f08561012001356105f4565b61050d57604051633ab3447f60e11b815260040160405180910390fd5b5f61051a61018387610627565b905061052981868686866107d3565b610537866101200135610919565b61053f610979565b6101b68b610f78565b84848484846001600160e01b03195f35166105666020870187611a8b565b6001600160e01b0319161461058e576040516341abc80160e01b815260040160405180910390fd5b61059c8561012001356105f4565b6105b957604051633ab3447f60e11b815260040160405180910390fd5b5f6105c661018387610627565b90506105d581868686866107d3565b6105e3866101200135610919565b6105eb610979565b6101b68b6110b1565b5f806105fe6111cf565b600884901c5f9081526020919091526040902054600160ff9094169390931b9092161592915050565b5f7f588d3cc8b8f6227b7c4a2fb181b58f36adb9f9f7de835d5f82dff67a4edf32106106566020840184611a8b565b6106666040850160208601611ac6565b6106766060860160408701611ac6565b6060860135608087013560a088013561069260c08a018a611ae1565b6040516020016106a3929190611b27565b60408051601f1981840301815291905280516020909101206106c860e08b018b611ae1565b6040516020016106d9929190611b27565b60408051601f1981840301815291905280516020909101206106ff6101008c018c611b4e565b60405161070d929190611b91565b60408051918290038220602083019b909b526001600160e01b0319909916988101989098526001600160a01b03968716606089015295909416608087015260a086019290925260c085015260e0840152610100830152610120808301919091526101408201929092529083013561016082015261018001604051602081830303815290604052805190602001209050919050565b5f6107cd6107ad611226565b8360405161190160f01b8152600281019290925260228201526042902090565b92915050565b61081a6108158686868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061123492505050565b61125c565b6108375760405163ad1240b560e01b815260040160405180910390fd5b5f61084061128a565b90506108818684848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061123492505050565b6001600160a01b0316816001600160a01b031663578033b76040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108c6573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108ea9190611ba0565b6001600160a01b03161461091157604051639616155b60e01b815260040160405180910390fd5b505050505050565b6040518181527fb776255356e0e0558441ff17973defe3a455e5726025055551677e80c11311779060200160405180910390a1600160ff82161b61095b6111cf565b60089290921c5f908152602092909252604090912080549091179055565b7f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f008054600119016109bd57604051633ee5aeb560e01b815260040160405180910390fd5b60029055565b5f6109d46040830160208401611ac6565b6001600160a01b0316036109fb5760405163e99d5ac560e01b815260040160405180910390fd5b5f610a0c6060830160408401611ac6565b6001600160a01b031603610a335760405163e99d5ac560e01b815260040160405180910390fd5b610a436040820160208301611ac6565b6001600160a01b0316610a5c6060830160408401611ac6565b6001600160a01b03167fcd68d836931d28b26c81fd06a68b603542d9b3a2fd1ba1c1bd30c9e2e5f4e6eb8360800135604051610a9a91815260200190565b60405180910390a3610ab26060820160408301611ac6565b6001600160a01b031663b88d4fde30610ad16040850160208601611ac6565b6080850135610ae4610100870187611b4e565b6040518663ffffffff1660e01b8152600401610b04959493929190611be3565b5f604051808303815f87803b158015610b1b575f80fd5b505af1158015610b2d573d5f803e3d5ffd5b5050505050565b5f610b456040830160208401611ac6565b6001600160a01b031603610b6c5760405163e99d5ac560e01b815260040160405180910390fd5b5f610b7d6060830160408401611ac6565b6001600160a01b031603610ba45760405163e99d5ac560e01b815260040160405180910390fd5b610bb160e0820182611ae1565b90505f03610bd25760405163251f56a160e21b815260040160405180910390fd5b610be26040820160208301611ac6565b6001600160a01b0316610bfb6060830160408401611ac6565b6001600160a01b03167f167e272d1ef648e7a4189d38b9f0f78af27d2be4976fe5eec44bec5fc6869aec610c3260e0850185611ae1565b604051908152602001905060405180910390a3610c556060820160408301611ac6565b6001600160a01b03166328cfbd4630610c746040850160208601611ac6565b610c8160e0860186611ae1565b610c8f610100880188611b4e565b6040518763ffffffff1660e01b8152600401610b0496959493929190611c51565b610cc06040820160208301611ac6565b6001600160a01b0316610cd96060830160408401611ac6565b6001600160a01b03167f3534edb8a2ca71f4ddda4f0cfa32df03bcb50c8710c78b2e9a0e6e08bb08bc97610d1060e0850185611ae1565b610d1d60c0870187611ae1565b610d2b610100890189611b4e565b604051610d3d96959493929190611c9d565b60405180910390a3610d556060820160408301611ac6565b6001600160a01b0316632eb2c2d630610d746040850160208601611ac6565b610d8160e0860186611ae1565b610d8e60c0880188611ae1565b610d9c6101008a018a611b4e565b6040518963ffffffff1660e01b8152600401610b04989796959493929190611cd8565b610dcf6040820160208301611ac6565b6001600160a01b0316610de86060830160408401611ac6565b6001600160a01b03167f1c84289b4389ba8251b26974eaec89409eb21a1198ca5eb281c86388da2e778b608084013560a0850135610e2a610100870187611b4e565b604051610e3a9493929190611d3b565b60405180910390a3610e526060820160408301611ac6565b6001600160a01b031663f242432a30610e716040850160208601611ac6565b608085013560a0860135610e89610100880188611b4e565b6040518763ffffffff1660e01b8152600401610b0496959493929190611d5a565b8060a001355f03610ece57604051637c946ed760e01b815260040160405180910390fd5b610ede6040820160208301611ac6565b6001600160a01b0316610ef76060830160408401611ac6565b6001600160a01b03167fe8de91d538b06154a2c48315768c5046f47e127d7fd3f726fd85cc723f29b0528360a00135604051610f3591815260200190565b60405180910390a3610f75610f506040830160208401611ac6565b60a0830135610f656060850160408601611ac6565b6001600160a01b031691906112a4565b50565b5f610f896040830160208401611ac6565b6001600160a01b031603610fb05760405163e99d5ac560e01b815260040160405180910390fd5b8060a001355f03610fd457604051637c946ed760e01b815260040160405180910390fd5b610fe46040820160208301611ac6565b6001600160a01b03167f2bd8874aee0f667380057c67e3a812157e4b7649b244d6fcbc9094a9a1f7ee1d8260a0013560405161102291815260200190565b60405180910390a25f61103b6040830160208401611ac6565b6001600160a01b03168260a001356040515f6040518083038185875af1925050503d805f8114611086576040519150601f19603f3d011682016040523d82523d5f602084013e61108b565b606091505b50509050806110ad57604051630ce8f45160e31b815260040160405180910390fd5b5050565b5f6110c26040830160208401611ac6565b6001600160a01b0316036110e95760405163e99d5ac560e01b815260040160405180910390fd5b5f6110fa6060830160408401611ac6565b6001600160a01b0316036111215760405163e99d5ac560e01b815260040160405180910390fd5b6111316040820160208301611ac6565b6001600160a01b031661114a6060830160408401611ac6565b6001600160a01b03167faf380d55f38d8ea88ce6ebcd45134146ac7e4d2bc01621c2cfb0186bdfd1289f83608001358460600135604051611195929190918252602082015260400190565b60405180910390a3610f756111b06060830160408401611ac6565b6111c06040840160208501611ac6565b836080013584606001356112fb565b5f806040516020016112089060208082526013908201527234b79734b73334b732bc172a3930b739b332b960691b604082015260600190565b60408051601f19818403018152919052805160209091012092915050565b5f61122f6113c1565b905090565b5f805f806112428686611434565b925092509250611252828261147d565b5090949350505050565b5f8061126661153a565b6001600160a01b039093165f90815260039093016020525050604090205460ff1690565b5f8061129461157d565b546001600160a01b031692915050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b1790526112f69084906115c0565b505050565b805f03611365576040516322dca8bb60e21b81526001600160a01b03848116600483015260248201849052851690638b72a2ec906044015b5f604051808303815f87803b15801561134a575f80fd5b505af115801561135c573d5f803e3d5ffd5b505050506113bb565b806001036113a257604051630d9f100160e11b8152600481018390526001600160a01b038481166024830152851690631b3e200290604401611333565b604051635112c21760e01b815260040160405180910390fd5b50505050565b5f7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6113eb611621565b6113f3611686565b60408051602081019490945283019190915260608201524660808201523060a082015260c00160405160208183030381529060405280519060200120905090565b5f805f835160410361146b576020840151604085015160608601515f1a61145d888285856116c5565b955095509550505050611476565b505081515f91506002905b9250925092565b5f82600381111561149057611490611da0565b03611499575050565b60018260038111156114ad576114ad611da0565b036114cb5760405163f645eedf60e01b815260040160405180910390fd5b60028260038111156114df576114df611da0565b036115055760405163fce698f760e01b8152600481018290526024015b60405180910390fd5b600382600381111561151957611519611da0565b036110ad576040516335e2f38360e21b8152600481018290526024016114fc565b5f806040516020016112089060208082526017908201527f696f2e696e66696e65782e53656375726974794b657973000000000000000000604082015260600190565b5f806040516020016112089060208082526019908201527f696f2e696e66696e65782e4163636f756e7453746f7261676500000000000000604082015260600190565b5f6115d46001600160a01b0384168361178d565b905080515f141580156115f85750808060200190518101906115f69190611db4565b155b156112f657604051635274afe760e01b81526001600160a01b03841660048201526024016114fc565b5f8061162b6117a1565b90505f6116366117d8565b80519091501561164e57805160209091012092915050565b8154801561165d579392505050565b7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470935050505090565b5f806116906117a1565b90505f61169b611876565b8051909150156116b357805160209091012092915050565b6001820154801561165d579392505050565b5f80807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08411156116fe57505f91506003905082611783565b604080515f808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa15801561174f573d5f803e3d5ffd5b5050604051601f1901519150506001600160a01b03811661177a57505f925060019150829050611783565b92505f91508190505b9450945094915050565b606061179a83835f611892565b9392505050565b5f806040516020016112089060208082526011908201527034b79734b73334b732bc1722a4a81b989960791b604082015260600190565b60605f6117e36117a1565b90508060020180546117f490611dd3565b80601f016020809104026020016040519081016040528092919081815260200182805461182090611dd3565b801561186b5780601f106118425761010080835404028352916020019161186b565b820191905f5260205f20905b81548152906001019060200180831161184e57829003601f168201915b505050505091505090565b60605f6118816117a1565b90508060030180546117f490611dd3565b6060814710156118b75760405163cd78605960e01b81523060048201526024016114fc565b5f80856001600160a01b031684866040516118d29190611e0b565b5f6040518083038185875af1925050503d805f811461190c576040519150601f19603f3d011682016040523d82523d5f602084013e611911565b606091505b509150915061192186838361192b565b9695505050505050565b6060826119405761193b82611987565b61179a565b815115801561195757506001600160a01b0384163b155b1561198057604051639996b31560e01b81526001600160a01b03851660048201526024016114fc565b508061179a565b8051156119975780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b5f8083601f8401126119c0575f80fd5b50813567ffffffffffffffff8111156119d7575f80fd5b6020830191508360208285010111156119ee575f80fd5b9250929050565b5f805f805f60608688031215611a09575f80fd5b853567ffffffffffffffff80821115611a20575f80fd5b90870190610140828a031215611a34575f80fd5b90955060208701359080821115611a49575f80fd5b611a5589838a016119b0565b90965094506040880135915080821115611a6d575f80fd5b50611a7a888289016119b0565b969995985093965092949392505050565b5f60208284031215611a9b575f80fd5b81356001600160e01b03198116811461179a575f80fd5b6001600160a01b0381168114610f75575f80fd5b5f60208284031215611ad6575f80fd5b813561179a81611ab2565b5f808335601e19843603018112611af6575f80fd5b83018035915067ffffffffffffffff821115611b10575f80fd5b6020019150600581901b36038213156119ee575f80fd5b5f6001600160fb1b03831115611b3b575f80fd5b8260051b80858437919091019392505050565b5f808335601e19843603018112611b63575f80fd5b83018035915067ffffffffffffffff821115611b7d575f80fd5b6020019150368190038213156119ee575f80fd5b818382375f9101908152919050565b5f60208284031215611bb0575f80fd5b815161179a81611ab2565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b6001600160a01b03868116825285166020820152604081018490526080606082018190525f90611c169083018486611bbb565b979650505050505050565b8183525f6001600160fb1b03831115611c38575f80fd5b8260051b80836020870137939093016020019392505050565b6001600160a01b038781168252861660208201526080604082018190525f90611c7d9083018688611c21565b8281036060840152611c90818587611bbb565b9998505050505050505050565b606081525f611cb060608301888a611c21565b8281036020840152611cc3818789611c21565b90508281036040840152611c90818587611bbb565b6001600160a01b0389811682528816602082015260a0604082018190525f90611d04908301888a611c21565b8281036060840152611d17818789611c21565b90508281036080840152611d2c818587611bbb565b9b9a5050505050505050505050565b848152836020820152606060408201525f611921606083018486611bbb565b6001600160a01b03878116825286166020820152604081018590526060810184905260a0608082018190525f90611d949083018486611bbb565b98975050505050505050565b634e487b7160e01b5f52602160045260245ffd5b5f60208284031215611dc4575f80fd5b8151801515811461179a575f80fd5b600181811c90821680611de757607f821691505b602082108103611e0557634e487b7160e01b5f52602260045260245ffd5b50919050565b5f82515f5b81811015611e2a5760208186018101518583015201611e10565b505f92019182525091905056fea264697066735822122027348f5c57f61b77edba2353f7315b0ef9d5ab206a22bdb9662726903ce40c9164736f6c63430008150033
Deployed Bytecode
0x608060405234801561000f575f80fd5b506004361061007a575f3560e01c80636955292c116100585780636955292c146100b9578063c9a4324f146100cc578063debe1aa5146100df578063faf6157e146100f2575f80fd5b806301ef26c71461007e578063152acabb146100935780632f0a8b8c146100a6575b5f80fd5b61009161008c3660046119f5565b610105565b005b6100916100a13660046119f5565b6101ec565b6100916100b43660046119f5565b610298565b6100916100c73660046119f5565b610344565b6100916100da3660046119f5565b6103f0565b6100916100ed3660046119f5565b61049c565b6100916101003660046119f5565b610548565b84848484846001600160e01b03195f35166101236020870187611a8b565b6001600160e01b0319161461014b576040516341abc80160e01b815260040160405180910390fd5b6101598561012001356105f4565b61017657604051633ab3447f60e11b815260040160405180910390fd5b5f61018861018387610627565b6107a1565b905061019781868686866107d3565b6101a5866101200135610919565b6101ad610979565b6101b68b6109c3565b6101df60017f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f0055565b5050505050505050505050565b84848484846001600160e01b03195f351661020a6020870187611a8b565b6001600160e01b03191614610232576040516341abc80160e01b815260040160405180910390fd5b6102408561012001356105f4565b61025d57604051633ab3447f60e11b815260040160405180910390fd5b5f61026a61018387610627565b905061027981868686866107d3565b610287866101200135610919565b61028f610979565b6101b68b610b34565b84848484846001600160e01b03195f35166102b66020870187611a8b565b6001600160e01b031916146102de576040516341abc80160e01b815260040160405180910390fd5b6102ec8561012001356105f4565b61030957604051633ab3447f60e11b815260040160405180910390fd5b5f61031661018387610627565b905061032581868686866107d3565b610333866101200135610919565b61033b610979565b6101b68b610cb0565b84848484846001600160e01b03195f35166103626020870187611a8b565b6001600160e01b0319161461038a576040516341abc80160e01b815260040160405180910390fd5b6103988561012001356105f4565b6103b557604051633ab3447f60e11b815260040160405180910390fd5b5f6103c261018387610627565b90506103d181868686866107d3565b6103df866101200135610919565b6103e7610979565b6101b68b610dbf565b84848484846001600160e01b03195f351661040e6020870187611a8b565b6001600160e01b03191614610436576040516341abc80160e01b815260040160405180910390fd5b6104448561012001356105f4565b61046157604051633ab3447f60e11b815260040160405180910390fd5b5f61046e61018387610627565b905061047d81868686866107d3565b61048b866101200135610919565b610493610979565b6101b68b610eaa565b84848484846001600160e01b03195f35166104ba6020870187611a8b565b6001600160e01b031916146104e2576040516341abc80160e01b815260040160405180910390fd5b6104f08561012001356105f4565b61050d57604051633ab3447f60e11b815260040160405180910390fd5b5f61051a61018387610627565b905061052981868686866107d3565b610537866101200135610919565b61053f610979565b6101b68b610f78565b84848484846001600160e01b03195f35166105666020870187611a8b565b6001600160e01b0319161461058e576040516341abc80160e01b815260040160405180910390fd5b61059c8561012001356105f4565b6105b957604051633ab3447f60e11b815260040160405180910390fd5b5f6105c661018387610627565b90506105d581868686866107d3565b6105e3866101200135610919565b6105eb610979565b6101b68b6110b1565b5f806105fe6111cf565b600884901c5f9081526020919091526040902054600160ff9094169390931b9092161592915050565b5f7f588d3cc8b8f6227b7c4a2fb181b58f36adb9f9f7de835d5f82dff67a4edf32106106566020840184611a8b565b6106666040850160208601611ac6565b6106766060860160408701611ac6565b6060860135608087013560a088013561069260c08a018a611ae1565b6040516020016106a3929190611b27565b60408051601f1981840301815291905280516020909101206106c860e08b018b611ae1565b6040516020016106d9929190611b27565b60408051601f1981840301815291905280516020909101206106ff6101008c018c611b4e565b60405161070d929190611b91565b60408051918290038220602083019b909b526001600160e01b0319909916988101989098526001600160a01b03968716606089015295909416608087015260a086019290925260c085015260e0840152610100830152610120808301919091526101408201929092529083013561016082015261018001604051602081830303815290604052805190602001209050919050565b5f6107cd6107ad611226565b8360405161190160f01b8152600281019290925260228201526042902090565b92915050565b61081a6108158686868080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061123492505050565b61125c565b6108375760405163ad1240b560e01b815260040160405180910390fd5b5f61084061128a565b90506108818684848080601f0160208091040260200160405190810160405280939291908181526020018383808284375f9201919091525061123492505050565b6001600160a01b0316816001600160a01b031663578033b76040518163ffffffff1660e01b8152600401602060405180830381865afa1580156108c6573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108ea9190611ba0565b6001600160a01b03161461091157604051639616155b60e01b815260040160405180910390fd5b505050505050565b6040518181527fb776255356e0e0558441ff17973defe3a455e5726025055551677e80c11311779060200160405180910390a1600160ff82161b61095b6111cf565b60089290921c5f908152602092909252604090912080549091179055565b7f9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f008054600119016109bd57604051633ee5aeb560e01b815260040160405180910390fd5b60029055565b5f6109d46040830160208401611ac6565b6001600160a01b0316036109fb5760405163e99d5ac560e01b815260040160405180910390fd5b5f610a0c6060830160408401611ac6565b6001600160a01b031603610a335760405163e99d5ac560e01b815260040160405180910390fd5b610a436040820160208301611ac6565b6001600160a01b0316610a5c6060830160408401611ac6565b6001600160a01b03167fcd68d836931d28b26c81fd06a68b603542d9b3a2fd1ba1c1bd30c9e2e5f4e6eb8360800135604051610a9a91815260200190565b60405180910390a3610ab26060820160408301611ac6565b6001600160a01b031663b88d4fde30610ad16040850160208601611ac6565b6080850135610ae4610100870187611b4e565b6040518663ffffffff1660e01b8152600401610b04959493929190611be3565b5f604051808303815f87803b158015610b1b575f80fd5b505af1158015610b2d573d5f803e3d5ffd5b5050505050565b5f610b456040830160208401611ac6565b6001600160a01b031603610b6c5760405163e99d5ac560e01b815260040160405180910390fd5b5f610b7d6060830160408401611ac6565b6001600160a01b031603610ba45760405163e99d5ac560e01b815260040160405180910390fd5b610bb160e0820182611ae1565b90505f03610bd25760405163251f56a160e21b815260040160405180910390fd5b610be26040820160208301611ac6565b6001600160a01b0316610bfb6060830160408401611ac6565b6001600160a01b03167f167e272d1ef648e7a4189d38b9f0f78af27d2be4976fe5eec44bec5fc6869aec610c3260e0850185611ae1565b604051908152602001905060405180910390a3610c556060820160408301611ac6565b6001600160a01b03166328cfbd4630610c746040850160208601611ac6565b610c8160e0860186611ae1565b610c8f610100880188611b4e565b6040518763ffffffff1660e01b8152600401610b0496959493929190611c51565b610cc06040820160208301611ac6565b6001600160a01b0316610cd96060830160408401611ac6565b6001600160a01b03167f3534edb8a2ca71f4ddda4f0cfa32df03bcb50c8710c78b2e9a0e6e08bb08bc97610d1060e0850185611ae1565b610d1d60c0870187611ae1565b610d2b610100890189611b4e565b604051610d3d96959493929190611c9d565b60405180910390a3610d556060820160408301611ac6565b6001600160a01b0316632eb2c2d630610d746040850160208601611ac6565b610d8160e0860186611ae1565b610d8e60c0880188611ae1565b610d9c6101008a018a611b4e565b6040518963ffffffff1660e01b8152600401610b04989796959493929190611cd8565b610dcf6040820160208301611ac6565b6001600160a01b0316610de86060830160408401611ac6565b6001600160a01b03167f1c84289b4389ba8251b26974eaec89409eb21a1198ca5eb281c86388da2e778b608084013560a0850135610e2a610100870187611b4e565b604051610e3a9493929190611d3b565b60405180910390a3610e526060820160408301611ac6565b6001600160a01b031663f242432a30610e716040850160208601611ac6565b608085013560a0860135610e89610100880188611b4e565b6040518763ffffffff1660e01b8152600401610b0496959493929190611d5a565b8060a001355f03610ece57604051637c946ed760e01b815260040160405180910390fd5b610ede6040820160208301611ac6565b6001600160a01b0316610ef76060830160408401611ac6565b6001600160a01b03167fe8de91d538b06154a2c48315768c5046f47e127d7fd3f726fd85cc723f29b0528360a00135604051610f3591815260200190565b60405180910390a3610f75610f506040830160208401611ac6565b60a0830135610f656060850160408601611ac6565b6001600160a01b031691906112a4565b50565b5f610f896040830160208401611ac6565b6001600160a01b031603610fb05760405163e99d5ac560e01b815260040160405180910390fd5b8060a001355f03610fd457604051637c946ed760e01b815260040160405180910390fd5b610fe46040820160208301611ac6565b6001600160a01b03167f2bd8874aee0f667380057c67e3a812157e4b7649b244d6fcbc9094a9a1f7ee1d8260a0013560405161102291815260200190565b60405180910390a25f61103b6040830160208401611ac6565b6001600160a01b03168260a001356040515f6040518083038185875af1925050503d805f8114611086576040519150601f19603f3d011682016040523d82523d5f602084013e61108b565b606091505b50509050806110ad57604051630ce8f45160e31b815260040160405180910390fd5b5050565b5f6110c26040830160208401611ac6565b6001600160a01b0316036110e95760405163e99d5ac560e01b815260040160405180910390fd5b5f6110fa6060830160408401611ac6565b6001600160a01b0316036111215760405163e99d5ac560e01b815260040160405180910390fd5b6111316040820160208301611ac6565b6001600160a01b031661114a6060830160408401611ac6565b6001600160a01b03167faf380d55f38d8ea88ce6ebcd45134146ac7e4d2bc01621c2cfb0186bdfd1289f83608001358460600135604051611195929190918252602082015260400190565b60405180910390a3610f756111b06060830160408401611ac6565b6111c06040840160208501611ac6565b836080013584606001356112fb565b5f806040516020016112089060208082526013908201527234b79734b73334b732bc172a3930b739b332b960691b604082015260600190565b60408051601f19818403018152919052805160209091012092915050565b5f61122f6113c1565b905090565b5f805f806112428686611434565b925092509250611252828261147d565b5090949350505050565b5f8061126661153a565b6001600160a01b039093165f90815260039093016020525050604090205460ff1690565b5f8061129461157d565b546001600160a01b031692915050565b604080516001600160a01b038416602482015260448082018490528251808303909101815260649091019091526020810180516001600160e01b031663a9059cbb60e01b1790526112f69084906115c0565b505050565b805f03611365576040516322dca8bb60e21b81526001600160a01b03848116600483015260248201849052851690638b72a2ec906044015b5f604051808303815f87803b15801561134a575f80fd5b505af115801561135c573d5f803e3d5ffd5b505050506113bb565b806001036113a257604051630d9f100160e11b8152600481018390526001600160a01b038481166024830152851690631b3e200290604401611333565b604051635112c21760e01b815260040160405180910390fd5b50505050565b5f7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6113eb611621565b6113f3611686565b60408051602081019490945283019190915260608201524660808201523060a082015260c00160405160208183030381529060405280519060200120905090565b5f805f835160410361146b576020840151604085015160608601515f1a61145d888285856116c5565b955095509550505050611476565b505081515f91506002905b9250925092565b5f82600381111561149057611490611da0565b03611499575050565b60018260038111156114ad576114ad611da0565b036114cb5760405163f645eedf60e01b815260040160405180910390fd5b60028260038111156114df576114df611da0565b036115055760405163fce698f760e01b8152600481018290526024015b60405180910390fd5b600382600381111561151957611519611da0565b036110ad576040516335e2f38360e21b8152600481018290526024016114fc565b5f806040516020016112089060208082526017908201527f696f2e696e66696e65782e53656375726974794b657973000000000000000000604082015260600190565b5f806040516020016112089060208082526019908201527f696f2e696e66696e65782e4163636f756e7453746f7261676500000000000000604082015260600190565b5f6115d46001600160a01b0384168361178d565b905080515f141580156115f85750808060200190518101906115f69190611db4565b155b156112f657604051635274afe760e01b81526001600160a01b03841660048201526024016114fc565b5f8061162b6117a1565b90505f6116366117d8565b80519091501561164e57805160209091012092915050565b8154801561165d579392505050565b7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470935050505090565b5f806116906117a1565b90505f61169b611876565b8051909150156116b357805160209091012092915050565b6001820154801561165d579392505050565b5f80807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08411156116fe57505f91506003905082611783565b604080515f808252602082018084528a905260ff891692820192909252606081018790526080810186905260019060a0016020604051602081039080840390855afa15801561174f573d5f803e3d5ffd5b5050604051601f1901519150506001600160a01b03811661177a57505f925060019150829050611783565b92505f91508190505b9450945094915050565b606061179a83835f611892565b9392505050565b5f806040516020016112089060208082526011908201527034b79734b73334b732bc1722a4a81b989960791b604082015260600190565b60605f6117e36117a1565b90508060020180546117f490611dd3565b80601f016020809104026020016040519081016040528092919081815260200182805461182090611dd3565b801561186b5780601f106118425761010080835404028352916020019161186b565b820191905f5260205f20905b81548152906001019060200180831161184e57829003601f168201915b505050505091505090565b60605f6118816117a1565b90508060030180546117f490611dd3565b6060814710156118b75760405163cd78605960e01b81523060048201526024016114fc565b5f80856001600160a01b031684866040516118d29190611e0b565b5f6040518083038185875af1925050503d805f811461190c576040519150601f19603f3d011682016040523d82523d5f602084013e611911565b606091505b509150915061192186838361192b565b9695505050505050565b6060826119405761193b82611987565b61179a565b815115801561195757506001600160a01b0384163b155b1561198057604051639996b31560e01b81526001600160a01b03851660048201526024016114fc565b508061179a565b8051156119975780518082602001fd5b604051630a12f52160e11b815260040160405180910390fd5b5f8083601f8401126119c0575f80fd5b50813567ffffffffffffffff8111156119d7575f80fd5b6020830191508360208285010111156119ee575f80fd5b9250929050565b5f805f805f60608688031215611a09575f80fd5b853567ffffffffffffffff80821115611a20575f80fd5b90870190610140828a031215611a34575f80fd5b90955060208701359080821115611a49575f80fd5b611a5589838a016119b0565b90965094506040880135915080821115611a6d575f80fd5b50611a7a888289016119b0565b969995985093965092949392505050565b5f60208284031215611a9b575f80fd5b81356001600160e01b03198116811461179a575f80fd5b6001600160a01b0381168114610f75575f80fd5b5f60208284031215611ad6575f80fd5b813561179a81611ab2565b5f808335601e19843603018112611af6575f80fd5b83018035915067ffffffffffffffff821115611b10575f80fd5b6020019150600581901b36038213156119ee575f80fd5b5f6001600160fb1b03831115611b3b575f80fd5b8260051b80858437919091019392505050565b5f808335601e19843603018112611b63575f80fd5b83018035915067ffffffffffffffff821115611b7d575f80fd5b6020019150368190038213156119ee575f80fd5b818382375f9101908152919050565b5f60208284031215611bb0575f80fd5b815161179a81611ab2565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b6001600160a01b03868116825285166020820152604081018490526080606082018190525f90611c169083018486611bbb565b979650505050505050565b8183525f6001600160fb1b03831115611c38575f80fd5b8260051b80836020870137939093016020019392505050565b6001600160a01b038781168252861660208201526080604082018190525f90611c7d9083018688611c21565b8281036060840152611c90818587611bbb565b9998505050505050505050565b606081525f611cb060608301888a611c21565b8281036020840152611cc3818789611c21565b90508281036040840152611c90818587611bbb565b6001600160a01b0389811682528816602082015260a0604082018190525f90611d04908301888a611c21565b8281036060840152611d17818789611c21565b90508281036080840152611d2c818587611bbb565b9b9a5050505050505050505050565b848152836020820152606060408201525f611921606083018486611bbb565b6001600160a01b03878116825286166020820152604081018590526060810184905260a0608082018190525f90611d949083018486611bbb565b98975050505050505050565b634e487b7160e01b5f52602160045260245ffd5b5f60208284031215611dc4575f80fd5b8151801515811461179a575f80fd5b600181811c90821680611de757607f821691505b602082108103611e0557634e487b7160e01b5f52602260045260245ffd5b50919050565b5f82515f5b81811015611e2a5760208186018101518583015201611e10565b505f92019182525091905056fea264697066735822122027348f5c57f61b77edba2353f7315b0ef9d5ab206a22bdb9662726903ce40c9164736f6c63430008150033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.