More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 11,794 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Transact With Ex... | 329218515 | 1 hr ago | IN | 0 ETH | 0.00003799 | ||||
Transact With Ex... | 329218067 | 1 hr ago | IN | 0 ETH | 0.0000418 | ||||
Transact With Ex... | 329138099 | 6 hrs ago | IN | 0 ETH | 0.00001894 | ||||
Transact With Ex... | 329137504 | 7 hrs ago | IN | 0 ETH | 0.0000189 | ||||
Transact With Ex... | 329136806 | 7 hrs ago | IN | 0 ETH | 0.00001897 | ||||
Transact With Ex... | 329136232 | 7 hrs ago | IN | 0 ETH | 0.00001621 | ||||
Transact With Ex... | 329131270 | 7 hrs ago | IN | 0 ETH | 0.00001754 | ||||
Transact With Ex... | 329131068 | 7 hrs ago | IN | 0 ETH | 0.00001728 | ||||
Transact With Ex... | 329094212 | 10 hrs ago | IN | 0 ETH | 0.00004091 | ||||
Transact With Ex... | 329093165 | 10 hrs ago | IN | 0 ETH | 0.00005946 | ||||
Transact With Ex... | 329064141 | 12 hrs ago | IN | 0 ETH | 0.00033758 | ||||
Transact With Ex... | 328950816 | 19 hrs ago | IN | 0 ETH | 0.00001913 | ||||
Transact With Ex... | 328944549 | 20 hrs ago | IN | 0 ETH | 0.00002928 | ||||
Transact With Ex... | 328936485 | 20 hrs ago | IN | 0 ETH | 0.00002114 | ||||
Transact With Ex... | 328935943 | 21 hrs ago | IN | 0 ETH | 0.00001422 | ||||
Transact With Ex... | 328935735 | 21 hrs ago | IN | 0 ETH | 0.00001549 | ||||
Transact With Ex... | 328934354 | 21 hrs ago | IN | 0 ETH | 0.00001943 | ||||
Transact With Ex... | 328930369 | 21 hrs ago | IN | 0 ETH | 0.00001437 | ||||
Transact With Ex... | 328925459 | 21 hrs ago | IN | 0 ETH | 0.00001388 | ||||
Transact With Ex... | 328922131 | 21 hrs ago | IN | 0 ETH | 0.00001463 | ||||
Transact With Ex... | 328921372 | 22 hrs ago | IN | 0 ETH | 0.00001461 | ||||
Transact With Ex... | 328918928 | 22 hrs ago | IN | 0 ETH | 0.00001441 | ||||
Transact With Ex... | 328918704 | 22 hrs ago | IN | 0 ETH | 0.0000146 | ||||
Transact With Ex... | 328874889 | 25 hrs ago | IN | 0 ETH | 0.00001913 | ||||
Transact With Ex... | 328873743 | 25 hrs ago | IN | 0 ETH | 0.00002966 |
Latest 25 internal transactions (View All)
Advanced mode:
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
329218515 | 1 hr ago | 0.00479151 ETH | ||||
329218067 | 1 hr ago | 0.00487552 ETH | ||||
329138099 | 6 hrs ago | 0.00632824 ETH | ||||
329137504 | 7 hrs ago | 0.00632824 ETH | ||||
329136806 | 7 hrs ago | 0.00639509 ETH | ||||
329136232 | 7 hrs ago | 0.00639509 ETH | ||||
329131270 | 7 hrs ago | 0.0009495 ETH | ||||
329131068 | 7 hrs ago | 0.001 ETH | ||||
329094212 | 10 hrs ago | 0.01152449 ETH | ||||
329093165 | 10 hrs ago | 0.0116 ETH | ||||
329064141 | 12 hrs ago | 0.0018731 ETH | ||||
328874889 | 25 hrs ago | 0.00487552 ETH | ||||
328873743 | 25 hrs ago | 0.00496385 ETH | ||||
328786565 | 31 hrs ago | 0.00690528 ETH | ||||
328785664 | 31 hrs ago | 0.00690528 ETH | ||||
328784988 | 31 hrs ago | 0.00695255 ETH | ||||
328784426 | 31 hrs ago | 0.00695255 ETH | ||||
328772065 | 32 hrs ago | 0.00095946 ETH | ||||
328722926 | 35 hrs ago | 0.01155797 ETH | ||||
328722467 | 35 hrs ago | 0.0116 ETH | ||||
328618207 | 43 hrs ago | 0.0018731 ETH | ||||
328617578 | 43 hrs ago | 0.00192153 ETH | ||||
328602474 | 44 hrs ago | 0.00496385 ETH | ||||
328601592 | 44 hrs ago | 0.00501967 ETH | ||||
328457082 | 2 days ago | 0.001 ETH |
Loading...
Loading
Contract Name:
Hinkal
Compiler Version
v0.8.17+commit.8df45f5f
Optimization Enabled:
Yes with 1000 runs
Other Settings:
default evmVersion, Audited
Contract Source Code (Solidity Standard Json-Input format)Audit Report
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.17; import "./HinkalBase.sol"; import "./VerifierFacade.sol"; import "./types/IHinkal.sol"; import "./types/IExternalAction.sol"; import "./types/ITransactHook.sol"; ///@title Hinkal Contract ///@notice Entrypoint for all Hinkal Transactions. contract Hinkal is IHinkal, VerifierFacade, HinkalBase { mapping(uint256 => address) internal externalActionMap; constructor( IMerkle.MerkleConstructorArgs memory constructorArgs, address _hinkalHelper, address _accessToken, address _hinkalHelperManager ) HinkalBase( constructorArgs, _hinkalHelper, _accessToken, _hinkalHelperManager ) {} function registerExternalAction( uint256 externalActionId, address externalActionAddress ) public onlyRole(DEFAULT_ADMIN_ROLE) { externalActionMap[externalActionId] = externalActionAddress; emit ExternalActionRegistered(externalActionAddress); } ///@notice Stop allowing smart contract to be called by Hinkal. ///@param externalActionId Id of this contract function removeExternalAction( uint256 externalActionId ) public onlyRole(DEFAULT_ADMIN_ROLE) { address externalActionAddress = externalActionMap[externalActionId]; delete externalActionMap[externalActionId]; emit ExternalActionRemoved(externalActionAddress); } function transact( uint256[2] calldata a, uint256[2][2] calldata b, uint256[2] calldata c, Dimensions calldata dimensions, CircomData calldata circomData ) public payable nonReentrant { _transact(a, b, c, dimensions, circomData); } function transactWithExternalAction( uint256[2] calldata a, uint256[2][2] calldata b, uint256[2] calldata c, Dimensions calldata dimensions, CircomData calldata circomData ) public payable nonReentrant { require(circomData.externalActionId != 0, "externalAddress is missing"); _transact(a, b, c, dimensions, circomData); } function transactWithHook( uint256[2] calldata a, uint256[2][2] calldata b, uint256[2] calldata c, Dimensions calldata dimensions, CircomData calldata circomData ) public payable nonReentrant { require( circomData.hookData.hookContract != address(0) || circomData.hookData.preHookContract != address(0), "hookContract is missing" ); _transact(a, b, c, dimensions, circomData); } function transactWithExternalActionAndHook( uint256[2] calldata a, uint256[2][2] calldata b, uint256[2] calldata c, Dimensions calldata dimensions, CircomData calldata circomData ) public payable nonReentrant { require(circomData.externalActionId != 0, "externalAddress is missing"); require( circomData.hookData.hookContract != address(0) || circomData.hookData.preHookContract != address(0), "hookContract is missing" ); _transact(a, b, c, dimensions, circomData); } function _transact( uint256[2] calldata a, uint256[2][2] calldata b, uint256[2] calldata c, Dimensions calldata dimensions, CircomData calldata circomData ) internal { { uint256[] memory inputForCircom = hinkalHelper.performHinkalChecks( circomData, dimensions ); require( verifyProof( a, b, c, inputForCircom, buildVerifierId(dimensions, circomData.externalActionId) ), "Invalid Proof" ); // Root Hash Validation require( rootHashExists(circomData.rootHashHinkal), "Hinkal Root Hash is Incorrect" ); require( accessToken.checkForRootHash( circomData.rootHashAccessToken, msg.sender ), "Access Token Root Hash is Incorrect" ); // if you are forking/develop a netork the next statement should be commented require( circomData.timeStamp > block.timestamp - 7 * 60 && circomData.timeStamp < block.timestamp + 7 * 60, "Timestamp provided does not align with current time" ); } { // function variables to store commitments created on-chain UTXO[] memory utxoSet; if (circomData.hookData.preHookContract != address(0)) { IPreTransactHook transactHook = IPreTransactHook( circomData.hookData.preHookContract ); transactHook.preTransact( circomData, circomData.hookData.preHookMetadata ); } uint256[] memory oldBalances = getBalancesForArray( circomData.erc20TokenAddresses, circomData.tokenIds ); if (circomData.externalActionId == 0) { _internalTransact(circomData); } else { utxoSet = _internalRunExternalAction(circomData); } uint256[] memory newBalances = getBalancesForArray( circomData.erc20TokenAddresses, circomData.tokenIds ); OnChainCommitment[] memory onChainCommitments = new OnChainCommitment[]( utxoSet.length ); uint256 onChainCommitmentCounter = 0; for (uint64 i; i < circomData.erc20TokenAddresses.length; i++) { int256 balanceDif; if (circomData.erc20TokenAddresses[i] == address(0)) { balanceDif = int256(newBalances[i]) + int256(msg.value) - int256(oldBalances[i]); } else { balanceDif = int256(newBalances[i]) - int256(oldBalances[i]); } // balance inequality to check that minimum amount of token is received require( balanceDif >= circomData.amountChanges[i], "Inbalance in token detected" ); uint256 utxoAmount = 0; for (uint j = 0; j < utxoSet.length; j++) { if ( utxoSet[j].erc20Address == circomData.erc20TokenAddresses[i] ) { utxoAmount = utxoSet[j].amount; onChainCommitments[ onChainCommitmentCounter++ ] = createCommitment(utxoSet[j]); break; } } // balance equation to check that we create utxo equal exactly to balance increase require( balanceDif == int256(utxoAmount) + int256(identity(circomData.outCommitments[i][0])) * circomData.amountChanges[i], "Balance Diff Should be equal to sum of onchain and offchain created commitments" ); } if (circomData.hookData.hookContract != address(0)) { ITransactHook transactHook = ITransactHook( circomData.hookData.hookContract ); transactHook.afterTransact( circomData, circomData.hookData.postHookMetadata ); } insertNullifiers(circomData.inputNullifiers); insertCommitments( circomData.outCommitments, circomData.encryptedOutputs, onChainCommitments ); } } ///@notice private internal function for transaction ///@param circomData circom dara function _internalTransact(CircomData calldata circomData) private { for (uint64 i = 0; i < circomData.erc20TokenAddresses.length; i++) { if (circomData.amountChanges[i] > 0) { require( circomData.externalAddress == msg.sender, "Deposit should come from the sender" ); transferTokenFrom( circomData.erc20TokenAddresses[i], circomData.externalAddress, address(this), uint256(circomData.amountChanges[i]), circomData.tokenIds[i] ); } else if (circomData.amountChanges[i] < 0) { uint256 relayFee = 0; if (circomData.relay != address(0)) { relayFee = hinkalHelper.calculateRelayFee( uint256(-circomData.amountChanges[i]), circomData.erc20TokenAddresses[i], circomData.flatFees[i], circomData.externalActionId ); require( relayFee <= uint256(-circomData.amountChanges[i]), "Relay Fee is over withdraw amount" ); if (circomData.tokenIds[i] == 0) transferERC20TokenOrETH( circomData.erc20TokenAddresses[i], circomData.relay, relayFee ); } transferToken( circomData.erc20TokenAddresses[i], circomData.externalAddress, uint256(-circomData.amountChanges[i]) - relayFee, circomData.tokenIds[i] ); } } } ///@notice internal function to use Hinkal with external contracts. ///@param circomData circom data. function _internalRunExternalAction( CircomData calldata circomData ) internal returns (UTXO[] memory) { require( externalActionMap[circomData.externalActionId] == circomData.externalAddress && circomData.externalAddress != address(0), "Unknown externalAddress" ); for (uint64 i = 0; i < circomData.erc20TokenAddresses.length; i++) { if (circomData.amountChanges[i] < 0) { transferToken( circomData.erc20TokenAddresses[i], circomData.externalAddress, uint256(-circomData.amountChanges[i]), circomData.tokenIds[i] ); } } return IExternalAction(circomData.externalAddress).runAction(circomData); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (access/AccessControl.sol) pragma solidity ^0.8.0; import "./IAccessControl.sol"; import "../utils/Context.sol"; import "../utils/Strings.sol"; import "../utils/introspection/ERC165.sol"; /** * @dev Contract module that allows children to implement role-based access * control mechanisms. This is a lightweight version that doesn't allow enumerating role * members except through off-chain means by accessing the contract event logs. Some * applications may benefit from on-chain enumerability, for those cases see * {AccessControlEnumerable}. * * Roles are referred to by their `bytes32` identifier. These should be exposed * in the external API and be unique. The best way to achieve this is by * using `public constant` hash digests: * * ```solidity * bytes32 public constant MY_ROLE = keccak256("MY_ROLE"); * ``` * * Roles can be used to represent a set of permissions. To restrict access to a * function call, use {hasRole}: * * ```solidity * function foo() public { * require(hasRole(MY_ROLE, msg.sender)); * ... * } * ``` * * Roles can be granted and revoked dynamically via the {grantRole} and * {revokeRole} functions. Each role has an associated admin role, and only * accounts that have a role's admin role can call {grantRole} and {revokeRole}. * * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means * that only accounts with this role will be able to grant or revoke other * roles. More complex role relationships can be created by using * {_setRoleAdmin}. * * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to * grant and revoke this role. Extra precautions should be taken to secure * accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules} * to enforce additional security measures for this role. */ abstract contract AccessControl is Context, IAccessControl, ERC165 { struct RoleData { mapping(address => bool) members; bytes32 adminRole; } mapping(bytes32 => RoleData) private _roles; bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00; /** * @dev Modifier that checks that an account has a specific role. Reverts * with a standardized message including the required role. * * The format of the revert reason is given by the following regular expression: * * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ * * _Available since v4.1._ */ modifier onlyRole(bytes32 role) { _checkRole(role); _; } /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId); } /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) public view virtual override returns (bool) { return _roles[role].members[account]; } /** * @dev Revert with a standard message if `_msgSender()` is missing `role`. * Overriding this function changes the behavior of the {onlyRole} modifier. * * Format of the revert message is described in {_checkRole}. * * _Available since v4.6._ */ function _checkRole(bytes32 role) internal view virtual { _checkRole(role, _msgSender()); } /** * @dev Revert with a standard message if `account` is missing `role`. * * The format of the revert reason is given by the following regular expression: * * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/ */ function _checkRole(bytes32 role, address account) internal view virtual { if (!hasRole(role, account)) { revert( string( abi.encodePacked( "AccessControl: account ", Strings.toHexString(account), " is missing role ", Strings.toHexString(uint256(role), 32) ) ) ); } } /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) { return _roles[role].adminRole; } /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. * * May emit a {RoleGranted} event. */ function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { _grantRole(role, account); } /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. * * May emit a {RoleRevoked} event. */ function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) { _revokeRole(role, account); } /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been revoked `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `account`. * * May emit a {RoleRevoked} event. */ function renounceRole(bytes32 role, address account) public virtual override { require(account == _msgSender(), "AccessControl: can only renounce roles for self"); _revokeRole(role, account); } /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. Note that unlike {grantRole}, this function doesn't perform any * checks on the calling account. * * May emit a {RoleGranted} event. * * [WARNING] * ==== * This function should only be called from the constructor when setting * up the initial roles for the system. * * Using this function in any other way is effectively circumventing the admin * system imposed by {AccessControl}. * ==== * * NOTE: This function is deprecated in favor of {_grantRole}. */ function _setupRole(bytes32 role, address account) internal virtual { _grantRole(role, account); } /** * @dev Sets `adminRole` as ``role``'s admin role. * * Emits a {RoleAdminChanged} event. */ function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual { bytes32 previousAdminRole = getRoleAdmin(role); _roles[role].adminRole = adminRole; emit RoleAdminChanged(role, previousAdminRole, adminRole); } /** * @dev Grants `role` to `account`. * * Internal function without access restriction. * * May emit a {RoleGranted} event. */ function _grantRole(bytes32 role, address account) internal virtual { if (!hasRole(role, account)) { _roles[role].members[account] = true; emit RoleGranted(role, account, _msgSender()); } } /** * @dev Revokes `role` from `account`. * * Internal function without access restriction. * * May emit a {RoleRevoked} event. */ function _revokeRole(bytes32 role, address account) internal virtual { if (hasRole(role, account)) { _roles[role].members[account] = false; emit RoleRevoked(role, account, _msgSender()); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol) pragma solidity ^0.8.0; /** * @dev External interface of AccessControl declared to support ERC165 detection. */ interface IAccessControl { /** * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` * * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite * {RoleAdminChanged} not being emitted signaling this. * * _Available since v3.1._ */ event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole); /** * @dev Emitted when `account` is granted `role`. * * `sender` is the account that originated the contract call, an admin role * bearer except when using {AccessControl-_setupRole}. */ event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Emitted when `account` is revoked `role`. * * `sender` is the account that originated the contract call: * - if using `revokeRole`, it is the admin role bearer * - if using `renounceRole`, it is the role bearer (i.e. `account`) */ event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender); /** * @dev Returns `true` if `account` has been granted `role`. */ function hasRole(bytes32 role, address account) external view returns (bool); /** * @dev Returns the admin role that controls `role`. See {grantRole} and * {revokeRole}. * * To change a role's admin, use {AccessControl-_setRoleAdmin}. */ function getRoleAdmin(bytes32 role) external view returns (bytes32); /** * @dev Grants `role` to `account`. * * If `account` had not been already granted `role`, emits a {RoleGranted} * event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function grantRole(bytes32 role, address account) external; /** * @dev Revokes `role` from `account`. * * If `account` had been granted `role`, emits a {RoleRevoked} event. * * Requirements: * * - the caller must have ``role``'s admin role. */ function revokeRole(bytes32 role, address account) external; /** * @dev Revokes `role` from the calling account. * * Roles are often managed via {grantRole} and {revokeRole}: this function's * purpose is to provide a mechanism for accounts to lose their privileges * if they are compromised (such as when a trusted device is misplaced). * * If the calling account had been granted `role`, emits a {RoleRevoked} * event. * * Requirements: * * - the caller must be `account`. */ function renounceRole(bytes32 role, address account) external; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor() { _transferOwnership(_msgSender()); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol) pragma solidity ^0.8.0; import "./Ownable.sol"; /** * @dev Contract module which provides access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership} and {acceptOwnership}. * * This module is used through inheritance. It will make available all functions * from parent (Ownable). */ abstract contract Ownable2Step is Ownable { address private _pendingOwner; event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner); /** * @dev Returns the address of the pending owner. */ function pendingOwner() public view virtual returns (address) { return _pendingOwner; } /** * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one. * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual override onlyOwner { _pendingOwner = newOwner; emit OwnershipTransferStarted(owner(), newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner. * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual override { delete _pendingOwner; super._transferOwnership(newOwner); } /** * @dev The new owner accepts the ownership transfer. */ function acceptOwnership() public virtual { address sender = _msgSender(); require(pendingOwner() == sender, "Ownable2Step: caller is not the new owner"); _transferOwnership(sender); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (interfaces/IERC20.sol) pragma solidity ^0.8.0; import "../token/ERC20/IERC20.sol";
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (interfaces/IERC721.sol) pragma solidity ^0.8.0; import "../token/ERC721/IERC721.sol";
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol) pragma solidity ^0.8.0; /** * @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 ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; constructor() { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { _nonReentrantBefore(); _; _nonReentrantAfter(); } function _nonReentrantBefore() private { // On the first call to nonReentrant, _status will be _NOT_ENTERED require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; } function _nonReentrantAfter() private { // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } /** * @dev 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) { return _status == _ENTERED; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.4) (token/ERC20/extensions/IERC20Permit.sol) pragma solidity ^0.8.0; /** * @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 v4.9.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the amount of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the amount of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves `amount` tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 amount) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets `amount` as the allowance of `spender` over the caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 amount) external returns (bool); /** * @dev Moves `amount` tokens from `from` to `to` using the * allowance mechanism. `amount` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 amount) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.0; import "../IERC20.sol"; import "../extensions/IERC20Permit.sol"; import "../../../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 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.encodeWithSelector(token.transfer.selector, 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.encodeWithSelector(token.transferFrom.selector, from, to, value)); } /** * @dev Deprecated. This function has issues similar to the ones found in * {IERC20-approve}, and its usage is discouraged. * * Whenever possible, use {safeIncreaseAllowance} and * {safeDecreaseAllowance} instead. */ function safeApprove(IERC20 token, address spender, uint256 value) internal { // safeApprove should only be called when setting an initial allowance, // or when resetting it to zero. To increase and decrease it, use // 'safeIncreaseAllowance' and 'safeDecreaseAllowance' require( (value == 0) || (token.allowance(address(this), spender) == 0), "SafeERC20: approve from non-zero to non-zero allowance" ); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 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); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance + value)); } /** * @dev Decrease the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal { unchecked { uint256 oldAllowance = token.allowance(address(this), spender); require(oldAllowance >= value, "SafeERC20: decreased allowance below zero"); _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, oldAllowance - value)); } } /** * @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.encodeWithSelector(token.approve.selector, spender, value); if (!_callOptionalReturnBool(token, approvalCall)) { _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, 0)); _callOptionalReturn(token, approvalCall); } } /** * @dev Use a ERC-2612 signature to set the `owner` approval toward `spender` on `token`. * Revert on invalid signature. */ function safePermit( IERC20Permit token, address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) internal { uint256 nonceBefore = token.nonces(owner); token.permit(owner, spender, value, deadline, v, r, s); uint256 nonceAfter = token.nonces(owner); require(nonceAfter == nonceBefore + 1, "SafeERC20: permit did not succeed"); } /** * @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, "SafeERC20: low-level call failed"); require(returndata.length == 0 || abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed"); } /** * @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.isContract(address(token)); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC721/IERC721.sol) pragma solidity ^0.8.0; import "../../utils/introspection/IERC165.sol"; /** * @dev Required interface of an ERC721 compliant contract. */ interface IERC721 is IERC165 { /** * @dev Emitted when `tokenId` token is transferred from `from` to `to`. */ event Transfer(address indexed from, address indexed to, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token. */ event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId); /** * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets. */ event ApprovalForAll(address indexed owner, address indexed operator, bool approved); /** * @dev Returns the number of tokens in ``owner``'s account. */ function balanceOf(address owner) external view returns (uint256 balance); /** * @dev Returns the owner of the `tokenId` token. * * Requirements: * * - `tokenId` must exist. */ function ownerOf(uint256 tokenId) external view returns (address owner); /** * @dev Safely transfers `tokenId` token from `from` to `to`. * * 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 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); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol) pragma solidity ^0.8.0; /** * @title ERC721 token receiver interface * @dev Interface for any contract that wants to support safeTransfers * from ERC721 asset contracts. */ interface IERC721Receiver { /** * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom} * by `operator` from `from`, this function is called. * * It must return its Solidity selector to confirm the token transfer. * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted. * * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`. */ function onERC721Received( address operator, address from, uint256 tokenId, bytes calldata data ) external returns (bytes4); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol) pragma solidity ^0.8.1; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev Returns true if `account` is a contract. * * [IMPORTANT] * ==== * It is unsafe to assume that an address for which this function returns * false is an externally-owned account (EOA) and not a contract. * * Among others, `isContract` will return false for the following * types of addresses: * * - an externally-owned account * - a contract in construction * - an address where a contract will be created * - an address where a contract lived, but was destroyed * * Furthermore, `isContract` will also return true if the target contract within * the same transaction is already scheduled for destruction by `SELFDESTRUCT`, * which only has an effect at the end of a transaction. * ==== * * [IMPORTANT] * ==== * You shouldn't rely on `isContract` to protect against flash loan attacks! * * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract * constructor. * ==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize/address.code.length, which returns 0 // for contracts in construction, since the code is only stored at the end // of the constructor execution. return account.code.length > 0; } /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://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.0/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance"); (bool success, ) = recipient.call{value: amount}(""); require(success, "Address: unable to send value, recipient may have reverted"); } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason, it is bubbled up by this * function (like regular Solidity function calls). * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. * * _Available since v3.1._ */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, "Address: low-level call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with * `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { return functionCallWithValue(target, data, 0, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. * * _Available since v3.1._ */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { return functionCallWithValue(target, data, value, "Address: low-level call with value failed"); } /** * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but * with `errorMessage` as a fallback revert reason when `target` reverts. * * _Available since v3.1._ */ function functionCallWithValue( address target, bytes memory data, uint256 value, string memory errorMessage ) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { return functionStaticCall(target, data, "Address: low-level static call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a static call. * * _Available since v3.3._ */ function functionStaticCall( address target, bytes memory data, string memory errorMessage ) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { return functionDelegateCall(target, data, "Address: low-level delegate call failed"); } /** * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`], * but performing a delegate call. * * _Available since v3.4._ */ function functionDelegateCall( address target, bytes memory data, string memory errorMessage ) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata, errorMessage); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract. * * _Available since v4.8._ */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata, string memory errorMessage ) internal view returns (bytes memory) { if (success) { if (returndata.length == 0) { // only check isContract if the call was successful and the return data is empty // otherwise we already know that it was a contract require(isContract(target), "Address: call to non-contract"); } return returndata; } else { _revert(returndata, errorMessage); } } /** * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the * revert reason or using the provided one. * * _Available since v4.3._ */ function verifyCallResult( bool success, bytes memory returndata, string memory errorMessage ) internal pure returns (bytes memory) { if (success) { return returndata; } else { _revert(returndata, errorMessage); } } function _revert(bytes memory returndata, string memory errorMessage) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.4) (utils/Context.sol) pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) pragma solidity ^0.8.0; import "./IERC165.sol"; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` * * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. */ abstract contract ERC165 is IERC165 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IERC165).interfaceId; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol) pragma solidity ^0.8.0; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { enum Rounding { Down, // Toward negative infinity Up, // Toward infinity Zero // Toward zero } /** * @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 up instead * of rounding down. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { // (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; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod0 := mul(x, y) 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. require(denominator > prod1, "Math: mulDiv overflow"); /////////////////////////////////////////////// // 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. // Does not overflow because the denominator cannot be zero at this stage in the function. uint256 twos = denominator & (~denominator + 1); 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 (rounding == Rounding.Up && 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 down. * * 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 + (rounding == Rounding.Up && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2, rounded down, of a positive value. * 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 + (rounding == Rounding.Up && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10, rounded down, of a positive value. * 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 + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0); } } /** * @dev Return the log in base 256, rounded down, of a positive value. * 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 + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol) pragma solidity ^0.8.0; /** * @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 // OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol) pragma solidity ^0.8.0; import "./math/Math.sol"; import "./math/SignedMath.sol"; /** * @dev String operations. */ library Strings { bytes16 private constant _SYMBOLS = "0123456789abcdef"; uint8 private constant _ADDRESS_LENGTH = 20; /** * @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), _SYMBOLS)) } value /= 10; if (value == 0) break; } return buffer; } } /** * @dev Converts a `int256` to its ASCII `string` decimal representation. */ function toString(int256 value) internal pure returns (string memory) { return string(abi.encodePacked(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) { 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] = _SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); 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 keccak256(bytes(a)) == keccak256(bytes(b)); } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.17; import "@openzeppelin/contracts/security/ReentrancyGuard.sol"; import "@openzeppelin/contracts/access/AccessControl.sol"; import "./types/IHinkalBase.sol"; import "./types/IHinkalHelper.sol"; import "./types/ICrossChainAccessToken.sol"; import "./types/IMerkle.sol"; import "./Merkle.sol"; import "./OwnerHinkal.sol"; import "./Transferer.sol"; import "./types/CircomData.sol"; ///@title Base class for Hinkal Contract contract HinkalBase is IHinkalBase, Merkle, Transferer, AccessControl, ReentrancyGuard { mapping(uint256 => bool) public nullifiers; IHinkalHelper public hinkalHelper; ICrossChainAccessToken public accessToken; bytes32 public constant HINKAL_HELPER_MANAGER = keccak256("HINKAL_HELPER_MANAGER"); constructor( IMerkle.MerkleConstructorArgs memory constructorArgs, address _hinkalHelper, address _accessToken, address _hinkalHelperManager ) Merkle(constructorArgs) { hinkalHelper = IHinkalHelper(_hinkalHelper); accessToken = ICrossChainAccessToken(_accessToken); _setRoleAdmin(HINKAL_HELPER_MANAGER, HINKAL_HELPER_MANAGER); _grantRole(HINKAL_HELPER_MANAGER, _hinkalHelperManager); _grantRole(DEFAULT_ADMIN_ROLE, msg.sender); } receive() external payable {} ///@notice set the hinkal helper. ///@dev See HinkalHelper contract ///@param _hinkalHelper ethereum address of hinkal helper contract function setHinkalHelper( address _hinkalHelper ) external onlyRole(HINKAL_HELPER_MANAGER) { hinkalHelper = IHinkalHelper(_hinkalHelper); } ///@notice set access token. ///@dev See Cross Chain Access Token contract ///@param _accessToken ethereum address of Cross Chain Access Token contract function setAccessToken( address _accessToken ) external onlyRole(HINKAL_HELPER_MANAGER) { accessToken = ICrossChainAccessToken(_accessToken); } function register(bytes calldata shieldedAddressHash) external { accessToken.registerCheck(msg.sender); emit Register(msg.sender, shieldedAddressHash); } ///@notice insert user commitments to merkle tree. function createCommitment( // TODO --> needs coverage? UTXO memory utxo ) internal view returns (OnChainCommitment memory) { uint256 commitment; if (utxo.tokenId > 0) { commitment = hash5( utxo.amount, uint256(uint160(utxo.erc20Address)), utxo.stealthAddressStructure.stealthAddress, utxo.timeStamp, utxo.tokenId ); } else { commitment = hash4( utxo.amount, uint256(uint160(utxo.erc20Address)), utxo.stealthAddressStructure.stealthAddress, utxo.timeStamp ); } OnChainCommitment memory onChainCommitment = OnChainCommitment({ utxo: utxo, commitment: commitment }); return onChainCommitment; } function insertCommitments( uint256[][] calldata outCommitments, bytes[][] calldata encryptedOutputs, OnChainCommitment[] memory onChainCommitments ) internal { // 1) Total Length of Commitments uint256 length = 0; for (uint16 i = 0; i < outCommitments.length; i++) { for (uint16 j = 0; j < outCommitments[i].length; j++) { length += identity(outCommitments[i][j]); } } length += onChainCommitments.length; if (length > 0) { // 2) Flattening leaves array uint256[] memory leaves = new uint256[](length); uint256 index = 0; for (uint16 i = 0; i < outCommitments.length; i++) { for (uint16 j = 0; j < outCommitments[i].length; j++) { if (outCommitments[i][j] != 0) leaves[index++] = outCommitments[i][j]; } } for (uint16 i = 0; i < onChainCommitments.length; i++) { leaves[index++] = onChainCommitments[i].commitment; } // 3) Inserting Leaves uint256[] memory insertedIndexes = insertMany(leaves); // 4) Emitting Commitments/EncryptedOutputs index = 0; for (uint16 i = 0; i < encryptedOutputs.length; i++) { for (uint16 j = 0; j < encryptedOutputs[i].length; j++) { if (outCommitments[i][j] != 0) { emit NewCommitment( leaves[index], int256(insertedIndexes[index]), encryptedOutputs[i][j] ); index++; } } } for (uint16 i = 0; i < onChainCommitments.length; i++) { emit NewCommitment( leaves[index], -1 * int256(insertedIndexes[index++]), abi.encode(onChainCommitments[i].utxo) ); } } } function insertNullifiers(uint256[][] calldata inputNullifiers) internal { for (uint256 i = 0; i < inputNullifiers.length; i++) { for (uint16 j = 0; j < inputNullifiers[i].length; j++) { if (inputNullifiers[i][j] == 0) continue; require( !nullifiers[inputNullifiers[i][j]], "Nullifier cannot be reused" ); nullifiers[inputNullifiers[i][j]] = true; emit Nullified(inputNullifiers[i][j]); } } } function identity(uint256 value) internal pure returns (uint256) { return value > 0 ? 1 : 0; } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.17; import "./types/IPoseidon2.sol"; import "./MerkleBase.sol"; ///@title Hinkal Merkle Tree contract Merkle is MerkleBase { constructor( MerkleConstructorArgs memory constructorArgs ) MerkleBase(constructorArgs) {} function outputGas(uint256 index, uint256[] memory gasUsed) internal view { gasUsed[index] = gasleft(); } ///@notice insert a single new leaf to Merkle Tree ///@param leaf value to be inserted ///@return index index of node inserted function insert(uint256 leaf) internal override returns (uint256) { uint256 newIndex = ++m_index; uint256 currentNodeIndex = newIndex - 1; require(m_index <= uint256(2) ** LEVELS, "Tree is full."); uint256 fullCount = newIndex - MINIMUM_INDEX; // number of inserted leaves uint256 twoPower = logarithm2(fullCount); // number of tree levels to be updated, (e.g. if 9 => 4 levels should be updated) uint256 prevHash = leaf; insertOne(currentNodeIndex, twoPower, prevHash); roots[rootIndex] = tree[twoPower]; // adding root to roots mapping rootIndex = (rootIndex + 1) % MAX_ROOT_NUMBER; return newIndex - 1; } function insertMany( uint256[] memory leaves ) internal returns (uint256[] memory insertedIndexes) { m_index += uint128(leaves.length); uint256 newIndex = m_index; uint256 currentNodeIndex = newIndex - leaves.length; require(m_index <= uint256(2) ** LEVELS, "Tree is full."); insertedIndexes = new uint256[](leaves.length); for (uint256 i = 0; i < insertedIndexes.length; i++) { insertedIndexes[i] = currentNodeIndex + i; } uint256[][] memory sortedLeaves = sortInPairs(leaves, currentNodeIndex); uint256 fullCount = newIndex - MINIMUM_INDEX; // number of inserted leaves uint256 twoPower = logarithm2(fullCount); // number of tree levels to be updated, (e.g. if 9 => 4 levels should be updated) for (uint256 i = 0; i < sortedLeaves.length; i++) { if (sortedLeaves[i].length == 1) insertOne(currentNodeIndex++, twoPower, sortedLeaves[i][0]); else { insertTwo( sortedLeaves[i][0], sortedLeaves[i][1], currentNodeIndex, twoPower ); currentNodeIndex += 2; } } roots[rootIndex] = tree[twoPower]; // adding root to roots mapping rootIndex = (rootIndex + 1) % MAX_ROOT_NUMBER; } ///@notice insert single value and update Merkle Tree ///@param currentNodeIndex Index of the last node before insertion ///@param twoPower Nodes in Merkle Tree that must be updated ///@param prevHash node to be inserted function insertOne( uint256 currentNodeIndex, uint256 twoPower, uint256 prevHash ) internal { for (uint256 i = 0; i <= twoPower; i++) { if (currentNodeIndex % 2 == 0 || currentNodeIndex == 1) { tree[i] = prevHash; if (i != twoPower) prevHash = hash2(prevHash, 0); } else { prevHash = hash2(tree[i], prevHash); } currentNodeIndex /= 2; } } function insertTwo( uint256 left, uint256 right, uint256 currentNodeIndex, uint256 twoPower ) internal { uint256 prevHash = hash2(left, right); currentNodeIndex /= 2; // we are starting from i = 1, so we need one iteration for (uint256 i = 1; i <= twoPower; i++) { if (currentNodeIndex % 2 == 0 || currentNodeIndex == 1) { tree[i] = prevHash; if (i != twoPower) prevHash = hash2(prevHash, 0); } else { prevHash = hash2(tree[i], prevHash); } currentNodeIndex /= 2; } } ///@notice Sort leaf nodes in pairs of left and right nodes. ///@param leaves leaves to be sorted ///@param currentNodeIndex Index of the last node to be inserted ///@return sortedLeaves leaves sorted in pairs of left and right function sortInPairs( uint256[] memory leaves, uint256 currentNodeIndex ) internal pure returns (uint256[][] memory sortedLeaves) { uint leavesLength = leaves.length; bool firstLeafIfRight = currentNodeIndex % 2 != 0; uint256 firstElement = firstLeafIfRight ? 1 : 0; uint256 netElements = leavesLength - firstElement; uint256 lengthWithoutFirst = (netElements % 2 == 0) ? netElements / 2 : (netElements + 1) / 2; sortedLeaves = new uint256[][](firstElement + lengthWithoutFirst); if (firstLeafIfRight) { uint256[] memory first = new uint256[](1); first[0] = leaves[0]; sortedLeaves[0] = first; } uint arrIndex = firstLeafIfRight ? 1 : 0; uint sortedArrayIndex = arrIndex; while (arrIndex < leavesLength) { uint256[] memory arr; if (arrIndex + 1 < leavesLength) { arr = new uint256[](2); arr[0] = leaves[arrIndex]; arr[1] = leaves[++arrIndex]; } else { arr = new uint256[](1); arr[0] = leaves[arrIndex]; } sortedLeaves[sortedArrayIndex++] = arr; ++arrIndex; } } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.17; import "@openzeppelin/contracts/utils/math/Math.sol"; import "./types/IPoseidon2.sol"; import "./types/IPoseidon4.sol"; import "./types/IPoseidon5.sol"; import "./types/IMerkle.sol"; abstract contract MerkleBase is IMerkle { using Math for uint256; // states mapping(uint256 => uint256) public tree; mapping(uint256 => uint256) roots; uint128 public m_index; // current index of the tree uint128 public rootIndex = 0; // constants uint128 immutable LEVELS; // deepness of tree uint128 constant MAX_ROOT_NUMBER = 25; uint256 immutable MINIMUM_INDEX; IPoseidon2 public immutable poseidon2; // hashing IPoseidon4 public immutable poseidon4; // hashing IPoseidon5 public immutable poseidon5; // please see deployment scripts to understand how to create and instance of Poseidon contract constructor(MerkleConstructorArgs memory constructorArgs) { LEVELS = constructorArgs.levels; m_index = uint128(2 ** (LEVELS - 1)); MINIMUM_INDEX = 2 ** (LEVELS - 1); poseidon2 = IPoseidon2(constructorArgs.poseidon2); poseidon4 = IPoseidon4(constructorArgs.poseidon4); poseidon5 = IPoseidon5(constructorArgs.poseidon5); } function hash2( uint256 a, uint256 b ) public view returns (uint256 poseidonHash) { poseidonHash = poseidon2.poseidon([a, b]); } function hash4( uint256 a0, uint256 a1, uint256 a2, uint256 a3 ) public view returns (uint256 poseidonHash) { poseidonHash = poseidon4.poseidon([a0, a1, a2, a3]); } function hash5( uint256 a0, uint256 a1, uint256 a2, uint256 a3, uint256 a4 ) public view returns (uint256 poseidonHash) { poseidonHash = poseidon5.poseidon([a0, a1, a2, a3, a4]); } function insert(uint256 leaf) internal virtual returns (uint256); function getRootHash() public view returns (uint256) { return roots[rootIndex > 0 ? rootIndex - 1 : MAX_ROOT_NUMBER - 1]; } function rootHashExists(uint256 _root) public view returns (bool) { uint256 i = rootIndex; // latest root hash do { if (i == 0) { i = MAX_ROOT_NUMBER; } i--; if (_root == roots[i]) { return true; } } while (i != rootIndex); return false; } ///@notice logarithm of x with base 2. ///@notice instead of rounding down, this function rounds up. ///@param x operand ///@return y logarithm base 2 of input function logarithm2(uint256 x) public pure returns (uint256 y) { y = Math.log2(x, Math.Rounding.Up); } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity 0.8.17; import "@openzeppelin/contracts/access/Ownable2Step.sol"; contract OwnerHinkal is Ownable2Step { function renounceOwnership() public view override onlyOwner { revert("The Ownership cannot be renounced"); } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.17; import "@openzeppelin/contracts/interfaces/IERC20.sol"; import "@openzeppelin/contracts/interfaces/IERC721.sol"; import "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "./TransfererBase.sol"; contract Transferer is TransfererBase { using SafeERC20 for IERC20; function onERC721Received( address, address, uint256, bytes calldata ) public pure returns (bytes4) { return IERC721Receiver.onERC721Received.selector; } function unsafeApproveERC20Token( address _erc20TokenAddress, address _to, uint256 _value ) internal { IERC20(_erc20TokenAddress).approve(_to, 0); IERC20(_erc20TokenAddress).approve(_to, _value); } function getERC20Allowance( address _erc20TokenAddress, address owner, address spender ) internal view returns (uint256) { IERC20 outToken = IERC20(_erc20TokenAddress); return outToken.allowance(owner, spender); } function approveERC721Token( address _erc20TokenAddress, address _to, uint256 _tokenId ) internal { IERC721(_erc20TokenAddress).approve(_to, _tokenId); } function approveToken( address _erc20TokenAddress, address _to, uint256 _tokenId, uint256 _value ) internal { if (_tokenId == 0) { unsafeApproveERC20Token(_erc20TokenAddress, _to, _value); } else { approveERC721Token(_erc20TokenAddress, _to, _tokenId); } } function transferETH(address _recepient, uint256 _value) internal { (bool success, ) = _recepient.call{value: _value}(""); require(success, "Transfer Failed"); } function transferERC20TokenFrom( address _erc20TokenAddress, address _from, address _to, uint256 _value ) internal { IERC20(_erc20TokenAddress).safeTransferFrom(_from, _to, _value); } function transferNftFrom( address _erc20TokenAddress, address _from, address _to, uint256 _tokenId ) internal { IERC721(_erc20TokenAddress).safeTransferFrom(_from, _to, _tokenId); } function transferERC20TokenOrETH( address _erc20TokenAddress, address _to, uint256 _value ) internal { if (_erc20TokenAddress == address(0)) { transferETH(_to, _value); } else { transferERC20Token(_erc20TokenAddress, _to, _value); } } function transferToken( address _erc20TokenAddress, address _to, uint256 _value, uint256 _tokenId ) internal { if (_tokenId == 0) { transferERC20TokenOrETH(_erc20TokenAddress, _to, _value); } else { transferNftFrom(_erc20TokenAddress, address(this), _to, _tokenId); } } function multiTransfer( address[] memory erc20TokenAddresses, address _to, uint256[] memory amounts ) internal returns (bool) { for (uint64 i = 0; i < erc20TokenAddresses.length; i++) { if (amounts[i] > 0) transferERC20TokenOrETH( erc20TokenAddresses[i], _to, amounts[i] ); } return true; } function transferERC20TokenFromOrCheckETH( address _contractAddress, address _from, address _to, uint256 _value ) internal { if (_contractAddress == address(0)) { require( msg.value == _value, "msg.value doesn't match needed amount" ); if (_to != address(this)) { transferETH(_to, _value); } } else { transferERC20TokenFrom(_contractAddress, _from, _to, _value); } } function transferTokenFrom( address _erc20TokenAddress, address _from, address _to, uint256 _value, uint256 _tokenId ) internal { if (_tokenId == 0) { transferERC20TokenFromOrCheckETH( _erc20TokenAddress, _from, _to, _value ); } else { transferNftFrom(_erc20TokenAddress, _from, _to, _tokenId); } } function multiTransferFrom( address[] memory erc20TokenAddresses, address _from, address _to, uint256[] memory amounts ) internal returns (bool) { for (uint64 i = 0; i < erc20TokenAddresses.length; i++) { if (amounts[i] > 0) { transferERC20TokenFromOrCheckETH( erc20TokenAddresses[i], _from, _to, amounts[i] ); } } return true; } function getERC20OrETHBalance( address _erc20TokenAddress ) internal view returns (uint256) { if (_erc20TokenAddress == address(0)) { return address(this).balance; } else { IERC20 outToken = IERC20(_erc20TokenAddress); return outToken.balanceOf(address(this)); } } function getNftBalance( address _erc20TokenAddress, uint256 tokenId ) internal view returns (uint256) { IERC721 outToken = IERC721(_erc20TokenAddress); try outToken.ownerOf(tokenId) returns (address owner) { if (owner == address(this)) return 1; else return 0; } catch { return 0; } } function getBalancesForArrayMemory( address[] memory erc20TokenAddresses ) internal view returns (uint256[] memory balances) { balances = new uint256[](erc20TokenAddresses.length); for (uint64 i; i < erc20TokenAddresses.length; i++) { balances[i] = getERC20OrETHBalance(erc20TokenAddresses[i]); } } function getBalancesForArrayMemory( address[] memory erc20TokenAddresses, uint256[] memory tokenIds ) internal view returns (uint256[] memory balances) { balances = new uint256[](erc20TokenAddresses.length); for (uint64 i; i < erc20TokenAddresses.length; i++) { if (tokenIds[i] == 0) { balances[i] = getERC20OrETHBalance(erc20TokenAddresses[i]); } else { balances[i] = getNftBalance( erc20TokenAddresses[i], tokenIds[i] ); } } } function getBalancesForArray( address[] calldata erc20TokenAddresses ) internal view returns (uint256[] memory balances) { balances = new uint256[](erc20TokenAddresses.length); for (uint64 i; i < erc20TokenAddresses.length; i++) { balances[i] = getERC20OrETHBalance(erc20TokenAddresses[i]); } } function getBalancesForArray( address[] calldata erc20TokenAddresses, uint256[] calldata tokenIds ) internal view returns (uint256[] memory balances) { balances = new uint256[](erc20TokenAddresses.length); for (uint64 i; i < erc20TokenAddresses.length; i++) { if (tokenIds[i] == 0) { balances[i] = getERC20OrETHBalance(erc20TokenAddresses[i]); } else { balances[i] = getNftBalance( erc20TokenAddresses[i], tokenIds[i] ); } } } function sendToRelay( address relay, uint256 actualAmount, address erc20TokenAddress ) internal { if (relay != address(0) && actualAmount > 0) { transferERC20TokenOrETH( erc20TokenAddress, relay, uint256(actualAmount) ); } } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.17; import "@openzeppelin/contracts/interfaces/IERC20.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; contract TransfererBase { using SafeERC20 for IERC20; function transferERC20Token( address _erc20TokenAddress, address _to, uint256 _value ) internal { IERC20(_erc20TokenAddress).safeTransfer(_to, _value); } function approveERC20Token( address _erc20TokenAddress, address _to, uint256 _value ) internal { IERC20(_erc20TokenAddress).safeApprove(_to, 0); IERC20(_erc20TokenAddress).safeApprove(_to, _value); } function approveUnlimited( address _erc20TokenAddress, address _to ) internal { if (IERC20(_erc20TokenAddress).allowance(address(this), _to) < type(uint256).max / 2) { IERC20(_erc20TokenAddress).safeApprove(_to, 0); IERC20(_erc20TokenAddress).safeApprove(_to, type(uint256).max); } } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.6; struct AxelarChainInfo{ string destinationChain; string destinationAddress; uint256 messageFee; } struct AxelarCapsule{ AxelarChainInfo[] chains; uint256 totalMessageFees; }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.6; import "./StealthAddressStructure.sol"; uint256 constant CIRCOM_P = 21888242871839275222246405745257275088548364400416034343698204186575808495617; // https://docs.circom.io/circom-language/basic-operators/ struct CircomData { uint256 rootHashHinkal; address[] erc20TokenAddresses; uint256[] tokenIds; int256[] amountChanges; uint256[][] inputNullifiers; uint256[][] outCommitments; bytes[][] encryptedOutputs; uint256[] flatFees; uint256 timeStamp; StealthAddressStructure stealthAddressStructure; uint256 rootHashAccessToken; uint256 calldataHash; uint16 publicSignalCount; address relay; address externalAddress; uint256 externalActionId; bytes externalActionMetadata; HookData hookData; } struct HookData { address preHookContract; address hookContract; bytes preHookMetadata; bytes postHookMetadata; }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.6; struct Dimensions { uint16 tokenNumber; uint16 nullifierAmount; uint16 outputAmount; }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity >=0.8.0; import "./CircomData.sol"; interface ICircomDataBuilder { function getHashedCalldata( CircomData memory circomData ) external pure returns (uint256); function formInputForCircom( CircomData memory circomData ) external pure returns (uint256[] memory input); }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity >=0.8.0; import "./IMerkle.sol"; import "./AxelarInfo.sol"; struct SignatureData { uint8 v; bytes32 r; bytes32 s; uint256 accessKey; uint256 nonce; } struct AccessTokenWithAddress { uint256 accessToken; address ethAddress; } interface ICrossChainAccessToken is IMerkle { event NewAccessKeyAdded( uint256 accessKey, uint256 index, address senderAddress ); event MintingFeeChanged(uint256 newMintingFee); event AccessKeyBlacklisted(uint256 blacklistedAccessKey); event AddressBlacklisted(address blacklistedAddress); event AddressRemovedFromBlacklist(address addressToRestore); event FundsWithdrawnFromAccessToken(uint256 amount); event AccessKeyMigrationReceived(uint256 accessKey, string sourceChain); event CrossChainAccessTokenRegistryChange( string sourceChain, address sourceAddress ); struct CrossChainAccessTokenRegistryUpdate { string sourceChain; address sourceAddress; } function usedNonces(uint256) external view returns (bool); function addToken(SignatureData calldata signatureData) external payable; function blacklistAddresses(address) external view returns (bool); function setMintingFee(uint256 _mintingFee) external; function hasToken(uint256 accessKey) external view returns (bool); function blacklistAccessKey(uint256 accessKey, uint256 index) external; function blacklistAddress(address _address) external; function removeAddressFromBlacklist(address addressToRestore) external; function withdraw() external; function setAxelarGasService(address _gasService) external; function addTokenCrossChain( SignatureData calldata signatureData, AxelarCapsule calldata capsule ) external payable; function migrateAccessToken( AxelarCapsule calldata capsule, uint256 accessKey ) external payable; function registerCheck(address sender) external view; function checkForRootHash( uint256 rootHashAccessToken, address sender ) external view returns (bool); }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.17; interface IERC20TokenRegistry { event RegistryStateChanged(bool isEnabled); event TokenAdded(address erc20Token); event TokenRemoved(address erc20Token); event TokenLimit(address erc20Token, uint256 tokenLimit); function tokenRegistry(address) external returns (bool); function tokenLimits(address) external returns (uint256); function enabled() external view returns (bool); function changeState(bool _enabled) external; function addERCToken(address erc20Token) external; function removeToken(address erc20Token) external; function tokenInRegistry(address erc20Token) external view returns (bool); function setTokenLimit(address _token, uint256 _tokenLimit) external; function getTokenLimit(address _token) external view returns (uint256); }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.6; import "./CircomData.sol"; import "./UTXO.sol"; interface IExternalAction { function runAction( CircomData calldata circomData ) external returns (UTXO[] memory); }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.6; import "../types/Dimensions.sol"; import "../types/CircomData.sol"; interface IHinkal { event ExternalActionRegistered(address externalActionAddress); event ExternalActionRemoved(address externalActionAddress); struct ConstructorArgs { uint256 levels; address poseidon; address accessTokenAddress; address circomDataBuilderAddress; address erc20TokenRegistryAddress; address relayStoreAddress; } function transact( uint256[2] calldata a, uint256[2][2] calldata b, uint256[2] calldata c, Dimensions calldata dimensions, CircomData calldata circomData ) external payable; function transactWithExternalAction( uint256[2] calldata a, uint256[2][2] calldata b, uint256[2] calldata c, Dimensions calldata dimensions, CircomData calldata circomData ) external payable; function transactWithHook( uint256[2] calldata a, uint256[2][2] calldata b, uint256[2] calldata c, Dimensions calldata dimensions, CircomData calldata circomData ) external payable; function transactWithExternalActionAndHook( uint256[2] calldata a, uint256[2][2] calldata b, uint256[2] calldata c, Dimensions calldata dimensions, CircomData calldata circomData ) external payable; }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.17; import "./IRelayStore.sol"; import "./UTXO.sol"; interface IHinkalBase { event Register(address ethereumAddress, bytes shieldedAddressHash); event NewCommitment( uint256 commitment, int256 index, bytes encryptedOutput ); event Nullified(uint256 nullifier); event NewTransaction( address sender, uint256 timestamp, address erc20TokenAddress, int256 publicAmount ); event NewUtxo( uint256 amount, address erc20Address, uint256 randomization, uint256 stealthAddress, uint256 timeStamp, uint256 tokenId ); function setHinkalHelper(address _hinkalHelper) external; }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.17; import "./IRelayStore.sol"; import "./ICircomDataBuilder.sol"; import "./Dimensions.sol"; import "./IRelayStore.sol"; import "./IERC20TokenRegistry.sol"; interface IHinkalHelper is IRelayStore, IERC20TokenRegistry { function getRelayStore() external view returns (RelayEntry[] memory); function relayerIsValid(address relay) external view; function checkTokenRegistry( address[] calldata erc20TokenAddresses, int256[] calldata amountChanges ) external view; function performHinkalChecks( CircomData calldata circomData, Dimensions calldata dimensions ) external view returns (uint256[] memory); }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.17; interface IMerkle { struct MerkleConstructorArgs { uint128 levels; address poseidon2; address poseidon4; address poseidon5; } function hash2(uint256 a, uint256 b) external view returns (uint256); function getRootHash() external view returns (uint256); function rootHashExists(uint256 _root) external view returns (bool); function logarithm2(uint256 x) external pure returns (uint256); }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity >=0.8.0; interface IPoseidon2 { function poseidon(uint256[2] memory input) external pure returns (uint256); function poseidon(bytes32[2] memory input) external pure returns (bytes32); }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity >=0.8.0; interface IPoseidon4 { function poseidon(uint256[4] memory input) external pure returns (uint256); function poseidon(bytes32[4] memory input) external pure returns (bytes32); }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity >=0.8.0; interface IPoseidon5 { function poseidon(uint256[5] memory input) external pure returns (uint256); function poseidon(bytes32[5] memory input) external pure returns (bytes32); }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.17; struct RelayEntry { address relayAddress; string url; uint256 priority; } interface IRelayStore { event RelayPercentageChanged(uint32 newRelayPercentage); event RelayPercentageExternalChanged(uint32 newRelayPercentage); event RelayAddedOrSet(address relayAddress, string url, uint256 priority); event RelayRemoved(address relayAddress); function getRelayPercentage( uint256 amount, address erc20Address ) external view returns (uint32); function setRelayPercentage(uint32 _relayPercentage) external; function getRelayPercentageExternal( uint256 amount, address erc20Address, uint256 externalActionId ) external view returns (uint32); function setRelayPercentageExternal( uint32 _relayPercentageExternal ) external; function isRelayInList(address relay) external view returns (bool); function getRelayStore() external view returns (RelayEntry[] memory); function removeRelay(address _relayAddress) external; function addOrSetRelay( address relayAddress, string memory url, uint256 priority ) external; function calculateRelayFee( uint256 balance, address tokenAddress, uint256 flatFee, uint256 externalActionId ) external view returns (uint256 relayFee); }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.6; import "./CircomData.sol"; interface IPreTransactHook { function preTransact( CircomData calldata circomData, bytes calldata metadata ) external; } interface ITransactHook { function afterTransact( CircomData calldata circomData, bytes calldata metadata ) external; }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.6; interface IVerifier { function verifyProof( uint256[2] memory a, uint256[2][2] memory b, uint256[2] memory c, uint256[] memory input, uint256 verifierId ) view external returns (bool); }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.17; import "./IVerifier.sol"; import "./Dimensions.sol"; interface IVerifierFacade { event VerifierRegistered(uint256 verifierId, address verifierAddress); event VerifierRemoved(uint256 verifierId); function registerVerifiers( uint256[] calldata verifierIds, address[] calldata verifierAddresses ) external; function removeVerifier(uint256 verifierId) external; function buildVerifierId( Dimensions calldata dimensions, uint256 externalActionId ) external pure returns (uint256); }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.6; struct StealthAddressStructure { uint256 extraRandomization; uint256 stealthAddress; uint256 H0; uint256 H1; }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity >=0.8.0; import "./StealthAddressStructure.sol"; struct UTXO { uint256 amount; address erc20Address; StealthAddressStructure stealthAddressStructure; uint256 timeStamp; uint256 tokenId; } struct OnChainCommitment { UTXO utxo; uint256 commitment; }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.17; import "./OwnerHinkal.sol"; import "./types/Dimensions.sol"; import "./types/IVerifierFacade.sol"; import "./types/IVerifier.sol"; ///@title A Facade pattern for zk proof Verifiers contract VerifierFacade is IVerifierFacade, OwnerHinkal { mapping(uint256 => IVerifier) internal verifierMap; function registerVerifiers( uint256[] calldata verifierIds, address[] calldata verifierAddresses ) external onlyOwner { for (uint i = 0; i < verifierIds.length; i++) { verifierMap[verifierIds[i]] = IVerifier(verifierAddresses[i]); emit VerifierRegistered(verifierIds[i], verifierAddresses[i]); } } function removeVerifier(uint256 verifierId) external onlyOwner { delete verifierMap[verifierId]; emit VerifierRemoved(verifierId); } function buildVerifierId( Dimensions calldata dimensions, uint256 externalActionId ) public pure returns (uint256) { return uint256( keccak256( abi.encode( dimensions.tokenNumber, dimensions.nullifierAmount, dimensions.outputAmount, externalActionId ) ) ); } function verifyProof( uint256[2] calldata a, uint256[2][2] calldata b, uint256[2] calldata c, uint256[] memory input, uint256 verifierId ) internal view returns (bool) { IVerifier verifier = verifierMap[verifierId]; require( address(verifier) != address(0), "Cannot find appropriate verifier" ); return verifier.verifyProof(a, b, c, input, verifierId); } }
{ "optimizer": { "enabled": true, "runs": 1000 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- "Secure3" - Jan 29 th, 2023- Security Audit Report
Contract ABI
API[{"inputs":[{"components":[{"internalType":"uint128","name":"levels","type":"uint128"},{"internalType":"address","name":"poseidon2","type":"address"},{"internalType":"address","name":"poseidon4","type":"address"},{"internalType":"address","name":"poseidon5","type":"address"}],"internalType":"struct IMerkle.MerkleConstructorArgs","name":"constructorArgs","type":"tuple"},{"internalType":"address","name":"_hinkalHelper","type":"address"},{"internalType":"address","name":"_accessToken","type":"address"},{"internalType":"address","name":"_hinkalHelperManager","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"externalActionAddress","type":"address"}],"name":"ExternalActionRegistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"externalActionAddress","type":"address"}],"name":"ExternalActionRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"commitment","type":"uint256"},{"indexed":false,"internalType":"int256","name":"index","type":"int256"},{"indexed":false,"internalType":"bytes","name":"encryptedOutput","type":"bytes"}],"name":"NewCommitment","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"},{"indexed":false,"internalType":"address","name":"erc20TokenAddress","type":"address"},{"indexed":false,"internalType":"int256","name":"publicAmount","type":"int256"}],"name":"NewTransaction","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"erc20Address","type":"address"},{"indexed":false,"internalType":"uint256","name":"randomization","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"stealthAddress","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"timeStamp","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"NewUtxo","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"nullifier","type":"uint256"}],"name":"Nullified","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"ethereumAddress","type":"address"},{"indexed":false,"internalType":"bytes","name":"shieldedAddressHash","type":"bytes"}],"name":"Register","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"verifierId","type":"uint256"},{"indexed":false,"internalType":"address","name":"verifierAddress","type":"address"}],"name":"VerifierRegistered","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"verifierId","type":"uint256"}],"name":"VerifierRemoved","type":"event"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"HINKAL_HELPER_MANAGER","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"accessToken","outputs":[{"internalType":"contract ICrossChainAccessToken","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint16","name":"tokenNumber","type":"uint16"},{"internalType":"uint16","name":"nullifierAmount","type":"uint16"},{"internalType":"uint16","name":"outputAmount","type":"uint16"}],"internalType":"struct Dimensions","name":"dimensions","type":"tuple"},{"internalType":"uint256","name":"externalActionId","type":"uint256"}],"name":"buildVerifierId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getRootHash","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"a","type":"uint256"},{"internalType":"uint256","name":"b","type":"uint256"}],"name":"hash2","outputs":[{"internalType":"uint256","name":"poseidonHash","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"a0","type":"uint256"},{"internalType":"uint256","name":"a1","type":"uint256"},{"internalType":"uint256","name":"a2","type":"uint256"},{"internalType":"uint256","name":"a3","type":"uint256"}],"name":"hash4","outputs":[{"internalType":"uint256","name":"poseidonHash","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"a0","type":"uint256"},{"internalType":"uint256","name":"a1","type":"uint256"},{"internalType":"uint256","name":"a2","type":"uint256"},{"internalType":"uint256","name":"a3","type":"uint256"},{"internalType":"uint256","name":"a4","type":"uint256"}],"name":"hash5","outputs":[{"internalType":"uint256","name":"poseidonHash","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"hinkalHelper","outputs":[{"internalType":"contract IHinkalHelper","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"x","type":"uint256"}],"name":"logarithm2","outputs":[{"internalType":"uint256","name":"y","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"m_index","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"nullifiers","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC721Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"poseidon2","outputs":[{"internalType":"contract IPoseidon2","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"poseidon4","outputs":[{"internalType":"contract IPoseidon4","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"poseidon5","outputs":[{"internalType":"contract IPoseidon5","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"shieldedAddressHash","type":"bytes"}],"name":"register","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"externalActionId","type":"uint256"},{"internalType":"address","name":"externalActionAddress","type":"address"}],"name":"registerExternalAction","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"verifierIds","type":"uint256[]"},{"internalType":"address[]","name":"verifierAddresses","type":"address[]"}],"name":"registerVerifiers","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"externalActionId","type":"uint256"}],"name":"removeExternalAction","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"verifierId","type":"uint256"}],"name":"removeVerifier","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_root","type":"uint256"}],"name":"rootHashExists","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rootIndex","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_accessToken","type":"address"}],"name":"setAccessToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_hinkalHelper","type":"address"}],"name":"setHinkalHelper","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[2]","name":"a","type":"uint256[2]"},{"internalType":"uint256[2][2]","name":"b","type":"uint256[2][2]"},{"internalType":"uint256[2]","name":"c","type":"uint256[2]"},{"components":[{"internalType":"uint16","name":"tokenNumber","type":"uint16"},{"internalType":"uint16","name":"nullifierAmount","type":"uint16"},{"internalType":"uint16","name":"outputAmount","type":"uint16"}],"internalType":"struct Dimensions","name":"dimensions","type":"tuple"},{"components":[{"internalType":"uint256","name":"rootHashHinkal","type":"uint256"},{"internalType":"address[]","name":"erc20TokenAddresses","type":"address[]"},{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"internalType":"int256[]","name":"amountChanges","type":"int256[]"},{"internalType":"uint256[][]","name":"inputNullifiers","type":"uint256[][]"},{"internalType":"uint256[][]","name":"outCommitments","type":"uint256[][]"},{"internalType":"bytes[][]","name":"encryptedOutputs","type":"bytes[][]"},{"internalType":"uint256[]","name":"flatFees","type":"uint256[]"},{"internalType":"uint256","name":"timeStamp","type":"uint256"},{"components":[{"internalType":"uint256","name":"extraRandomization","type":"uint256"},{"internalType":"uint256","name":"stealthAddress","type":"uint256"},{"internalType":"uint256","name":"H0","type":"uint256"},{"internalType":"uint256","name":"H1","type":"uint256"}],"internalType":"struct StealthAddressStructure","name":"stealthAddressStructure","type":"tuple"},{"internalType":"uint256","name":"rootHashAccessToken","type":"uint256"},{"internalType":"uint256","name":"calldataHash","type":"uint256"},{"internalType":"uint16","name":"publicSignalCount","type":"uint16"},{"internalType":"address","name":"relay","type":"address"},{"internalType":"address","name":"externalAddress","type":"address"},{"internalType":"uint256","name":"externalActionId","type":"uint256"},{"internalType":"bytes","name":"externalActionMetadata","type":"bytes"},{"components":[{"internalType":"address","name":"preHookContract","type":"address"},{"internalType":"address","name":"hookContract","type":"address"},{"internalType":"bytes","name":"preHookMetadata","type":"bytes"},{"internalType":"bytes","name":"postHookMetadata","type":"bytes"}],"internalType":"struct HookData","name":"hookData","type":"tuple"}],"internalType":"struct CircomData","name":"circomData","type":"tuple"}],"name":"transact","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256[2]","name":"a","type":"uint256[2]"},{"internalType":"uint256[2][2]","name":"b","type":"uint256[2][2]"},{"internalType":"uint256[2]","name":"c","type":"uint256[2]"},{"components":[{"internalType":"uint16","name":"tokenNumber","type":"uint16"},{"internalType":"uint16","name":"nullifierAmount","type":"uint16"},{"internalType":"uint16","name":"outputAmount","type":"uint16"}],"internalType":"struct Dimensions","name":"dimensions","type":"tuple"},{"components":[{"internalType":"uint256","name":"rootHashHinkal","type":"uint256"},{"internalType":"address[]","name":"erc20TokenAddresses","type":"address[]"},{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"internalType":"int256[]","name":"amountChanges","type":"int256[]"},{"internalType":"uint256[][]","name":"inputNullifiers","type":"uint256[][]"},{"internalType":"uint256[][]","name":"outCommitments","type":"uint256[][]"},{"internalType":"bytes[][]","name":"encryptedOutputs","type":"bytes[][]"},{"internalType":"uint256[]","name":"flatFees","type":"uint256[]"},{"internalType":"uint256","name":"timeStamp","type":"uint256"},{"components":[{"internalType":"uint256","name":"extraRandomization","type":"uint256"},{"internalType":"uint256","name":"stealthAddress","type":"uint256"},{"internalType":"uint256","name":"H0","type":"uint256"},{"internalType":"uint256","name":"H1","type":"uint256"}],"internalType":"struct StealthAddressStructure","name":"stealthAddressStructure","type":"tuple"},{"internalType":"uint256","name":"rootHashAccessToken","type":"uint256"},{"internalType":"uint256","name":"calldataHash","type":"uint256"},{"internalType":"uint16","name":"publicSignalCount","type":"uint16"},{"internalType":"address","name":"relay","type":"address"},{"internalType":"address","name":"externalAddress","type":"address"},{"internalType":"uint256","name":"externalActionId","type":"uint256"},{"internalType":"bytes","name":"externalActionMetadata","type":"bytes"},{"components":[{"internalType":"address","name":"preHookContract","type":"address"},{"internalType":"address","name":"hookContract","type":"address"},{"internalType":"bytes","name":"preHookMetadata","type":"bytes"},{"internalType":"bytes","name":"postHookMetadata","type":"bytes"}],"internalType":"struct HookData","name":"hookData","type":"tuple"}],"internalType":"struct CircomData","name":"circomData","type":"tuple"}],"name":"transactWithExternalAction","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256[2]","name":"a","type":"uint256[2]"},{"internalType":"uint256[2][2]","name":"b","type":"uint256[2][2]"},{"internalType":"uint256[2]","name":"c","type":"uint256[2]"},{"components":[{"internalType":"uint16","name":"tokenNumber","type":"uint16"},{"internalType":"uint16","name":"nullifierAmount","type":"uint16"},{"internalType":"uint16","name":"outputAmount","type":"uint16"}],"internalType":"struct Dimensions","name":"dimensions","type":"tuple"},{"components":[{"internalType":"uint256","name":"rootHashHinkal","type":"uint256"},{"internalType":"address[]","name":"erc20TokenAddresses","type":"address[]"},{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"internalType":"int256[]","name":"amountChanges","type":"int256[]"},{"internalType":"uint256[][]","name":"inputNullifiers","type":"uint256[][]"},{"internalType":"uint256[][]","name":"outCommitments","type":"uint256[][]"},{"internalType":"bytes[][]","name":"encryptedOutputs","type":"bytes[][]"},{"internalType":"uint256[]","name":"flatFees","type":"uint256[]"},{"internalType":"uint256","name":"timeStamp","type":"uint256"},{"components":[{"internalType":"uint256","name":"extraRandomization","type":"uint256"},{"internalType":"uint256","name":"stealthAddress","type":"uint256"},{"internalType":"uint256","name":"H0","type":"uint256"},{"internalType":"uint256","name":"H1","type":"uint256"}],"internalType":"struct StealthAddressStructure","name":"stealthAddressStructure","type":"tuple"},{"internalType":"uint256","name":"rootHashAccessToken","type":"uint256"},{"internalType":"uint256","name":"calldataHash","type":"uint256"},{"internalType":"uint16","name":"publicSignalCount","type":"uint16"},{"internalType":"address","name":"relay","type":"address"},{"internalType":"address","name":"externalAddress","type":"address"},{"internalType":"uint256","name":"externalActionId","type":"uint256"},{"internalType":"bytes","name":"externalActionMetadata","type":"bytes"},{"components":[{"internalType":"address","name":"preHookContract","type":"address"},{"internalType":"address","name":"hookContract","type":"address"},{"internalType":"bytes","name":"preHookMetadata","type":"bytes"},{"internalType":"bytes","name":"postHookMetadata","type":"bytes"}],"internalType":"struct HookData","name":"hookData","type":"tuple"}],"internalType":"struct CircomData","name":"circomData","type":"tuple"}],"name":"transactWithExternalActionAndHook","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256[2]","name":"a","type":"uint256[2]"},{"internalType":"uint256[2][2]","name":"b","type":"uint256[2][2]"},{"internalType":"uint256[2]","name":"c","type":"uint256[2]"},{"components":[{"internalType":"uint16","name":"tokenNumber","type":"uint16"},{"internalType":"uint16","name":"nullifierAmount","type":"uint16"},{"internalType":"uint16","name":"outputAmount","type":"uint16"}],"internalType":"struct Dimensions","name":"dimensions","type":"tuple"},{"components":[{"internalType":"uint256","name":"rootHashHinkal","type":"uint256"},{"internalType":"address[]","name":"erc20TokenAddresses","type":"address[]"},{"internalType":"uint256[]","name":"tokenIds","type":"uint256[]"},{"internalType":"int256[]","name":"amountChanges","type":"int256[]"},{"internalType":"uint256[][]","name":"inputNullifiers","type":"uint256[][]"},{"internalType":"uint256[][]","name":"outCommitments","type":"uint256[][]"},{"internalType":"bytes[][]","name":"encryptedOutputs","type":"bytes[][]"},{"internalType":"uint256[]","name":"flatFees","type":"uint256[]"},{"internalType":"uint256","name":"timeStamp","type":"uint256"},{"components":[{"internalType":"uint256","name":"extraRandomization","type":"uint256"},{"internalType":"uint256","name":"stealthAddress","type":"uint256"},{"internalType":"uint256","name":"H0","type":"uint256"},{"internalType":"uint256","name":"H1","type":"uint256"}],"internalType":"struct StealthAddressStructure","name":"stealthAddressStructure","type":"tuple"},{"internalType":"uint256","name":"rootHashAccessToken","type":"uint256"},{"internalType":"uint256","name":"calldataHash","type":"uint256"},{"internalType":"uint16","name":"publicSignalCount","type":"uint16"},{"internalType":"address","name":"relay","type":"address"},{"internalType":"address","name":"externalAddress","type":"address"},{"internalType":"uint256","name":"externalActionId","type":"uint256"},{"internalType":"bytes","name":"externalActionMetadata","type":"bytes"},{"components":[{"internalType":"address","name":"preHookContract","type":"address"},{"internalType":"address","name":"hookContract","type":"address"},{"internalType":"bytes","name":"preHookMetadata","type":"bytes"},{"internalType":"bytes","name":"postHookMetadata","type":"bytes"}],"internalType":"struct HookData","name":"hookData","type":"tuple"}],"internalType":"struct CircomData","name":"circomData","type":"tuple"}],"name":"transactWithHook","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"tree","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
610120604052600280546001600160801b031690553480156200002157600080fd5b5060405162005d0838038062005d0883398101604081905262000044916200032a565b83516001600160801b031660808190528490849084908490849081906200006e906001906200041d565b6200007b90600262000544565b600280546001600160801b0319166001600160801b0392909216919091179055608051620000ac906001906200041d565b620000b990600262000544565b60a05260208101516001600160a01b0390811660c0526040820151811660e052606090910151166101005250620000f03362000176565b6001600755600980546001600160a01b038086166001600160a01b031992831617909255600a8054928516929091169190911790556200014060008051602062005ce883398151915280620001a0565b6200015b60008051602062005ce883398151915282620001eb565b62000168600033620001eb565b505050505050505062000562565b600480546001600160a01b03191690556200019d8162000276602090811b6200145417901c565b50565b600082815260066020526040808220600101805490849055905190918391839186917fbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff9190a4505050565b620001f78282620002c8565b620002725760008281526006602090815260408083206001600160a01b03851684529091529020805460ff19166001179055620002313390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45b5050565b600380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b60008281526006602090815260408083206001600160a01b038516845290915290205460ff165b92915050565b80516001600160801b03811681146200030d57600080fd5b919050565b80516001600160a01b03811681146200030d57600080fd5b60008060008084860360e08112156200034257600080fd5b60808112156200035157600080fd5b50604051608081016001600160401b03811182821017156200038357634e487b7160e01b600052604160045260246000fd5b6040526200039186620002f5565b8152620003a16020870162000312565b6020820152620003b46040870162000312565b6040820152620003c76060870162000312565b60608201529350620003dc6080860162000312565b9250620003ec60a0860162000312565b9150620003fc60c0860162000312565b905092959194509250565b634e487b7160e01b600052601160045260246000fd5b6001600160801b0382811682821603908082111562000440576200044062000407565b5092915050565b600181815b80851115620004885781600019048211156200046c576200046c62000407565b808516156200047a57918102915b93841c93908002906200044c565b509250929050565b600082620004a157506001620002ef565b81620004b057506000620002ef565b8160018114620004c95760028114620004d457620004f4565b6001915050620002ef565b60ff841115620004e857620004e862000407565b50506001821b620002ef565b5060208310610133831016604e8410600b841016171562000519575081810a620002ef565b62000525838362000447565b80600019048211156200053c576200053c62000407565b029392505050565b60006200055b6001600160801b0384168362000490565b9392505050565b60805160a05160c05160e0516101005161572c620005bc6000396000818161033201526113030152600081816107040152610c910152600081816107ab0152610d8a015260006136fc015260006135db015261572c6000f3fe6080604052600436106102ca5760003560e01c80637e5a921811610179578063ae669f0e116100d6578063d547741f1161008a578063ee6be04011610064578063ee6be0401461085b578063f2fde38b1461088f578063f46732c7146108af57600080fd5b8063d547741f146107fd578063e243c5fb1461081d578063e30c39781461083d57600080fd5b8063c98aeff5116100bb578063c98aeff514610779578063ca5ee4b214610799578063d21e82ab146107cd57600080fd5b8063ae669f0e14610746578063c21c358e1461076657600080fd5b8063944e8fb41161012d578063a217fddf11610112578063a217fddf146106dd578063a81a2688146106f2578063a83b67451461072657600080fd5b8063944e8fb4146106aa5780639671084a146106bd57600080fd5b806382fbdc9c1161015e57806382fbdc9c146106265780638da5cb5b1461064657806391d148541461066457600080fd5b80637e5a9218146105f157806380759f1f1461061157600080fd5b806336568abe11610227578063529dd5ea116101db578063715018a6116101c0578063715018a6146105a757806377eadab7146105bc57806379ba5097146105dc57600080fd5b8063529dd5ea146105485780635b9e89d31461058757600080fd5b80633abd53ca1161020c5780633abd53ca146104e85780633b3ccded14610508578063511c53ff1461052857600080fd5b806336568abe146104a8578063396f3e5f146104c857600080fd5b8063150b7a021161027e578063248a9ca311610263578063248a9ca31461041d5780632f2ff15d1461045b578063313529361461047b57600080fd5b8063150b7a021461039f5780631ce573ec146103fd57600080fd5b80630d1dafaa116102af5780630d1dafaa1461032057806313e44e601461036c57806313fbc8d41461038c57600080fd5b806301988136146102d657806301ffc9a7146102eb57600080fd5b366102d157005b600080fd5b6102e96102e43660046144b1565b6108cf565b005b3480156102f757600080fd5b5061030b610306366004614546565b6109f7565b60405190151581526020015b60405180910390f35b34801561032c57600080fd5b506103547f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610317565b34801561037857600080fd5b506102e9610387366004614590565b610a60565b6102e961039a3660046144b1565b610aad565b3480156103ab57600080fd5b506103e46103ba3660046145f6565b7f150b7a020000000000000000000000000000000000000000000000000000000095945050505050565b6040516001600160e01b03199091168152602001610317565b34801561040957600080fd5b506102e9610418366004614669565b610ab5565b34801561042957600080fd5b5061044d610438366004614669565b60009081526006602052604090206001015490565b604051908152602001610317565b34801561046757600080fd5b506102e9610476366004614682565b610b24565b34801561048757600080fd5b5061044d610496366004614669565b60006020819052908152604090205481565b3480156104b457600080fd5b506102e96104c3366004614682565b610b4e565b3480156104d457600080fd5b506102e96104e3366004614682565b610bda565b3480156104f457600080fd5b506102e9610503366004614590565b610c40565b34801561051457600080fd5b5061044d6105233660046146b2565b610c8d565b34801561053457600080fd5b5061044d6105433660046146e4565b610d45565b34801561055457600080fd5b5060025461056f90600160801b90046001600160801b031681565b6040516001600160801b039091168152602001610317565b34801561059357600080fd5b506102e96105a2366004614669565b610e05565b3480156105b357600080fd5b506102e9610e66565b3480156105c857600080fd5b5061044d6105d7366004614669565b610edc565b3480156105e857600080fd5b506102e9610ee9565b3480156105fd57600080fd5b506102e961060c36600461474b565b610f77565b34801561061d57600080fd5b5061044d611093565b34801561063257600080fd5b506102e96106413660046147b7565b6110ff565b34801561065257600080fd5b506003546001600160a01b0316610354565b34801561067057600080fd5b5061030b61067f366004614682565b60009182526006602090815260408084206001600160a01b0393909316845291905290205460ff1690565b6102e96106b83660046144b1565b6111b2565b3480156106c957600080fd5b50600954610354906001600160a01b031681565b3480156106e957600080fd5b5061044d600081565b3480156106fe57600080fd5b506103547f000000000000000000000000000000000000000000000000000000000000000081565b34801561073257600080fd5b5061030b610741366004614669565b61120f565b34801561075257600080fd5b5061044d6107613660046147f9565b611281565b6102e96107743660046144b1565b6112f7565b34801561078557600080fd5b5061044d610794366004614824565b6112ff565b3480156107a557600080fd5b506103547f000000000000000000000000000000000000000000000000000000000000000081565b3480156107d957600080fd5b5061030b6107e8366004614669565b60086020526000908152604090205460ff1681565b34801561080957600080fd5b506102e9610818366004614682565b6113be565b34801561082957600080fd5b50600a54610354906001600160a01b031681565b34801561084957600080fd5b506004546001600160a01b0316610354565b34801561086757600080fd5b5061044d7f47ddd44be4e69e3bb12e0b1ae411c5e2264c8a03557812e6728682c3b1a4a9dd81565b34801561089b57600080fd5b506102e96108aa366004614590565b6113e3565b3480156108bb57600080fd5b5060025461056f906001600160801b031681565b6108d76114a6565b8061024001356000036109315760405162461bcd60e51b815260206004820152601a60248201527f65787465726e616c41646472657373206973206d697373696e6700000000000060448201526064015b60405180910390fd5b600061094161028083018361485f565b610952906040810190602001614590565b6001600160a01b031614158061098d5750600061097361028083018361485f565b610981906020810190614590565b6001600160a01b031614155b6109d95760405162461bcd60e51b815260206004820152601760248201527f686f6f6b436f6e7472616374206973206d697373696e670000000000000000006044820152606401610928565b6109e685858585856114ff565b6109f06001600755565b5050505050565b60006001600160e01b031982167f7965db0b000000000000000000000000000000000000000000000000000000001480610a5a57507f01ffc9a7000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b92915050565b7f47ddd44be4e69e3bb12e0b1ae411c5e2264c8a03557812e6728682c3b1a4a9dd610a8a81611e8d565b50600a80546001600160a01b0319166001600160a01b0392909216919091179055565b6109d96114a6565b6000610ac081611e8d565b6000828152600b602090815260409182902080546001600160a01b0319811690915591516001600160a01b03909216808352917f5cc7d016d05c39a385ee58ffd86a154b6079ed6e14d3a266b94f6276e040cf0f91015b60405180910390a1505050565b600082815260066020526040902060010154610b3f81611e8d565b610b498383611e97565b505050565b6001600160a01b0381163314610bcc5760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201527f20726f6c657320666f722073656c6600000000000000000000000000000000006064820152608401610928565b610bd68282611f39565b5050565b6000610be581611e8d565b6000838152600b602090815260409182902080546001600160a01b0319166001600160a01b03861690811790915591519182527f5d494982f506adaf74c262193225f5396e00122e4d8b4da60ee1c60fa6e446ad9101610b17565b7f47ddd44be4e69e3bb12e0b1ae411c5e2264c8a03557812e6728682c3b1a4a9dd610c6a81611e8d565b50600980546001600160a01b0319166001600160a01b0392909216919091179055565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663248f66776040518060800160405280888152602001878152602001868152602001858152506040518263ffffffff1660e01b8152600401610cfb919061487f565b602060405180830381865afa158015610d18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d3c91906148b0565b95945050505050565b6040805180820182528381526020810183905290517f29a5f2f60000000000000000000000000000000000000000000000000000000081526000916001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016916329a5f2f691610dbd916004016148c9565b602060405180830381865afa158015610dda573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dfe91906148b0565b9392505050565b610e0d611fbc565b6000818152600560205260409081902080546001600160a01b0319169055517f2e4fe6c83a0e1e30adfe1958137de9f4abe532810e7286db4a2590b2782c118b90610e5b9083815260200190565b60405180910390a150565b610e6e611fbc565b60405162461bcd60e51b815260206004820152602160248201527f546865204f776e6572736869702063616e6e6f742062652072656e6f756e636560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610928565b6000610a5a826001612018565b60045433906001600160a01b03168114610f6b5760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f74207468652060448201527f6e6577206f776e657200000000000000000000000000000000000000000000006064820152608401610928565b610f7481612063565b50565b610f7f611fbc565b60005b838110156109f057828282818110610f9c57610f9c6148f1565b9050602002016020810190610fb19190614590565b60056000878785818110610fc757610fc76148f1565b90506020020135815260200190815260200160002060006101000a8154816001600160a01b0302191690836001600160a01b031602179055507f3d47d745bf8c193d19b6eff4f8bb5ff806af27c6fe2863b21a76c292b8f48e13858583818110611033576110336148f1565b9050602002013584848481811061104c5761104c6148f1565b90506020020160208101906110619190614590565b604080519283526001600160a01b0390911660208301520160405180910390a18061108b8161491d565b915050610f82565b6002546000906001908290600160801b90046001600160801b03166110c3576110be60016019614936565b6110e2565b6002546110e290600190600160801b90046001600160801b0316614936565b6001600160801b0316815260200190815260200160002054905090565b600a546040517f7800e7140000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0390911690637800e7149060240160006040518083038186803b15801561115b57600080fd5b505afa15801561116f573d6000803e3d6000fd5b505050507fbf6a48f464846d0bb8735df8832ed2e3151e50b349fa76f15510a3e62baf3ca23383836040516111a69392919061497f565b60405180910390a15050565b6111ba6114a6565b8061024001356000036109d95760405162461bcd60e51b815260206004820152601a60248201527f65787465726e616c41646472657373206973206d697373696e670000000000006044820152606401610928565b600254600090600160801b90046001600160801b03165b80600003611232575060195b8061123c816149a2565b6000818152600160205260409020549092508403905061125f5750600192915050565b600254600160801b90046001600160801b031681036112265750600092915050565b600061129060208401846149cb565b6112a060408501602086016149cb565b6112b060608601604087016149cb565b6040805161ffff94851660208201529284169083015290911660608201526080810183905260a00160408051601f1981840301815291905280516020909101209392505050565b6109316114a6565b60007f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316634937a2586040518060a00160405280898152602001888152602001878152602001868152602001858152506040518263ffffffff1660e01b815260040161137391906149e6565b602060405180830381865afa158015611390573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113b491906148b0565b9695505050505050565b6000828152600660205260409020600101546113d981611e8d565b610b498383611f39565b6113eb611fbc565b600480546001600160a01b0383166001600160a01b0319909116811790915561141c6003546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b600380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6002600754036114f85760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610928565b6002600755565b6009546040517fdee949280000000000000000000000000000000000000000000000000000000081526000916001600160a01b03169063dee949289061154b9085908790600401614ee7565b600060405180830381865afa158015611568573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526115909190810190614ff4565b90506115ad868686846115a888886102400135611281565b61207c565b6115f95760405162461bcd60e51b815260206004820152600d60248201527f496e76616c69642050726f6f66000000000000000000000000000000000000006044820152606401610928565b611603823561120f565b61164f5760405162461bcd60e51b815260206004820152601d60248201527f48696e6b616c20526f6f74204861736820697320496e636f72726563740000006044820152606401610928565b600a546040517f32f7a1400000000000000000000000000000000000000000000000000000000081526101a084013560048201523360248201526001600160a01b03909116906332f7a14090604401602060405180830381865afa1580156116bb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116df919061507f565b6117515760405162461bcd60e51b815260206004820152602360248201527f41636365737320546f6b656e20526f6f74204861736820697320496e636f727260448201527f65637400000000000000000000000000000000000000000000000000000000006064820152608401610928565b61175d6101a4426150a1565b82610100013511801561177f5750611777426101a46150b4565b826101000135105b6117f15760405162461bcd60e51b815260206004820152603360248201527f54696d657374616d702070726f766964656420646f6573206e6f7420616c696760448201527f6e20776974682063757272656e742074696d65000000000000000000000000006064820152608401610928565b506060600061180461028084018461485f565b611812906020810190614590565b6001600160a01b0316146118be57600061183061028084018461485f565b61183e906020810190614590565b90506001600160a01b03811663d6fd34f48461185e61028082018261485f565b61186c9060408101906150c7565b6040518463ffffffff1660e01b815260040161188a9392919061510e565b600060405180830381600087803b1580156118a457600080fd5b505af11580156118b8573d6000803e3d6000fd5b50505050505b60006118e26118d06020850185615134565b6118dd6040870187615134565b61217a565b90508261024001356000036118ff576118fa83612306565b61190b565b61190883612849565b91505b600061192a61191d6020860186615134565b6118dd6040880188615134565b90506000835167ffffffffffffffff81111561194857611948614f3d565b60405190808252806020026020018201604052801561198157816020015b61196e614407565b8152602001906001900390816119665790505b5090506000805b6119956020880188615134565b90508167ffffffffffffffff161015611d78576000806119b860208a018a615134565b8467ffffffffffffffff168181106119d2576119d26148f1565b90506020020160208101906119e79190614590565b6001600160a01b031603611a5957858267ffffffffffffffff1681518110611a1157611a116148f1565b602002602001015134868467ffffffffffffffff1681518110611a3657611a366148f1565b6020026020010151611a48919061517e565b611a52919061519e565b9050611aae565b858267ffffffffffffffff1681518110611a7557611a756148f1565b6020026020010151858367ffffffffffffffff1681518110611a9957611a996148f1565b6020026020010151611aab919061519e565b90505b611abb6060890189615134565b8367ffffffffffffffff16818110611ad557611ad56148f1565b90506020020135811215611b2b5760405162461bcd60e51b815260206004820152601b60248201527f496e62616c616e636520696e20746f6b656e20646574656374656400000000006044820152606401610928565b6000805b8851811015611c2a57611b4560208b018b615134565b8567ffffffffffffffff16818110611b5f57611b5f6148f1565b9050602002016020810190611b749190614590565b6001600160a01b0316898281518110611b8f57611b8f6148f1565b6020026020010151602001516001600160a01b031603611c1857888181518110611bbb57611bbb6148f1565b6020026020010151600001519150611beb898281518110611bde57611bde6148f1565b6020026020010151612a92565b8686611bf68161491d565b975081518110611c0857611c086148f1565b6020026020010181905250611c2a565b80611c228161491d565b915050611b2f565b50611c3860608a018a615134565b8467ffffffffffffffff16818110611c5257611c526148f1565b90506020020135611cb58a8060a00190611c6c9190615134565b8667ffffffffffffffff16818110611c8657611c866148f1565b9050602002810190611c989190615134565b6000818110611ca957611ca96148f1565b90506020020135612b1e565b611cbf91906151be565b611cc9908261517e565b8214611d635760405162461bcd60e51b815260206004820152604f60248201527f42616c616e636520446966662053686f756c6420626520657175616c20746f2060448201527f73756d206f66206f6e636861696e20616e64206f6666636861696e206372656160648201527f74656420636f6d6d69746d656e74730000000000000000000000000000000000608482015260a401610928565b50508080611d70906151ee565b915050611988565b506000611d8961028088018861485f565b611d9a906040810190602001614590565b6001600160a01b031614611e49576000611db861028088018861485f565b611dc9906040810190602001614590565b90506001600160a01b038116630448463988611de961028082018261485f565b611df79060608101906150c7565b6040518463ffffffff1660e01b8152600401611e159392919061510e565b600060405180830381600087803b158015611e2f57600080fd5b505af1158015611e43573d6000803e3d6000fd5b50505050505b611e5e611e596080880188615134565b612b3a565b611e81611e6e60a0880188615134565b611e7b60c08a018a615134565b86612d6d565b50505050505050505050565b610f7481336132e2565b60008281526006602090815260408083206001600160a01b038516845290915290205460ff16610bd65760008281526006602090815260408083206001600160a01b03851684529091529020805460ff19166001179055611ef53390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b60008281526006602090815260408083206001600160a01b038516845290915290205460ff1615610bd65760008281526006602090815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b6003546001600160a01b031633146120165760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610928565b565b60008061202484613357565b9050600183600281111561203a5761203a615215565b14801561204a575083816001901b105b612055576000612058565b60015b60ff16019392505050565b600480546001600160a01b0319169055610f7481611454565b6000818152600560205260408120546001600160a01b0316806120e15760405162461bcd60e51b815260206004820181905260248201527f43616e6e6f742066696e6420617070726f7072696174652076657269666965726044820152606401610928565b6040517f6743734c0000000000000000000000000000000000000000000000000000000081526001600160a01b03821690636743734c9061212e908a908a908a908a908a9060040161522b565b602060405180830381865afa15801561214b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061216f919061507f565b979650505050505050565b60608367ffffffffffffffff81111561219557612195614f3d565b6040519080825280602002602001820160405280156121be578160200160208202803683370190505b50905060005b67ffffffffffffffff81168511156122fd5783838267ffffffffffffffff168181106121f2576121f26148f1565b905060200201356000036122665761223986868367ffffffffffffffff1681811061221f5761221f6148f1565b90506020020160208101906122349190614590565b6133eb565b828267ffffffffffffffff1681518110612255576122556148f1565b6020026020010181815250506122eb565b6122c286868367ffffffffffffffff16818110612285576122856148f1565b905060200201602081019061229a9190614590565b85858467ffffffffffffffff168181106122b6576122b66148f1565b9050602002013561344e565b828267ffffffffffffffff16815181106122de576122de6148f1565b6020026020010181815250505b806122f5816151ee565b9150506121c4565b50949350505050565b60005b6123166020830183615134565b90508167ffffffffffffffff161015610bd65760006123386060840184615134565b8367ffffffffffffffff16818110612352576123526148f1565b9050602002013513156124a9573361237261024084016102208501614590565b6001600160a01b0316146123ee5760405162461bcd60e51b815260206004820152602360248201527f4465706f7369742073686f756c6420636f6d652066726f6d207468652073656e60448201527f64657200000000000000000000000000000000000000000000000000000000006064820152608401610928565b6124a46123fe6020840184615134565b8367ffffffffffffffff16818110612418576124186148f1565b905060200201602081019061242d9190614590565b61243f61024085016102208601614590565b3061244d6060870187615134565b8667ffffffffffffffff16818110612467576124676148f1565b9050602002013586806040019061247e9190615134565b8767ffffffffffffffff16818110612498576124986148f1565b9050602002013561350a565b612837565b60006124b86060840184615134565b8367ffffffffffffffff168181106124d2576124d26148f1565b905060200201351215612837576000806124f461022085016102008601614590565b6001600160a01b03161461276f576009546001600160a01b03166342a55d826125206060860186615134565b8567ffffffffffffffff1681811061253a5761253a6148f1565b9050602002013561254a906152ba565b6125576020870187615134565b8667ffffffffffffffff16818110612571576125716148f1565b90506020020160208101906125869190614590565b61259360e0880188615134565b8767ffffffffffffffff168181106125ad576125ad6148f1565b6040516001600160e01b031960e088901b16815260048101959095526001600160a01b039093166024850152506020909102013560448201526102408601356064820152608401602060405180830381865afa158015612611573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061263591906148b0565b90506126446060840184615134565b8367ffffffffffffffff1681811061265e5761265e6148f1565b9050602002013561266e906152ba565b8111156126e35760405162461bcd60e51b815260206004820152602160248201527f52656c617920466565206973206f76657220776974686472617720616d6f756e60448201527f74000000000000000000000000000000000000000000000000000000000000006064820152608401610928565b6126f06040840184615134565b8367ffffffffffffffff1681811061270a5761270a6148f1565b9050602002013560000361276f5761276f6127286020850185615134565b8467ffffffffffffffff16818110612742576127426148f1565b90506020020160208101906127579190614590565b61276961022086016102008701614590565b8361352f565b61283561277f6020850185615134565b8467ffffffffffffffff16818110612799576127996148f1565b90506020020160208101906127ae9190614590565b6127c061024086016102208701614590565b836127ce6060880188615134565b8767ffffffffffffffff168181106127e8576127e86148f1565b905060200201356127f8906152ba565b61280291906150a1565b61280f6040880188615134565b8767ffffffffffffffff16818110612829576128296148f1565b90506020020135613552565b505b80612841816151ee565b915050612309565b606061285d61024083016102208401614590565b6102408301356000908152600b60205260409020546001600160a01b0390811691161480156128a75750600061289b61024084016102208501614590565b6001600160a01b031614155b6128f35760405162461bcd60e51b815260206004820152601760248201527f556e6b6e6f776e2065787465726e616c416464726573730000000000000000006044820152606401610928565b60005b6129036020840184615134565b90508167ffffffffffffffff161015612a0d5760006129256060850185615134565b8367ffffffffffffffff1681811061293f5761293f6148f1565b9050602002013512156129fb576129fb61295c6020850185615134565b8367ffffffffffffffff16818110612976576129766148f1565b905060200201602081019061298b9190614590565b61299d61024086016102208701614590565b6129aa6060870187615134565b8567ffffffffffffffff168181106129c4576129c46148f1565b905060200201356129d4906152ba565b6129e16040880188615134565b8667ffffffffffffffff16818110612829576128296148f1565b80612a05816151ee565b9150506128f6565b50612a2061024083016102208401614590565b6001600160a01b03166382b4b88c836040518263ffffffff1660e01b8152600401612a4b91906152d6565b6000604051808303816000875af1158015612a6a573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610a5a91908101906152e9565b612a9a614407565b608082015160009015612adc57612ad5836000015184602001516001600160a01b0316856040015160200151866060015187608001516112ff565b9050612b08565b612b05836000015184602001516001600160a01b03168560400151602001518660600151610c8d565b90505b6040805180820190915292835260208301525090565b6000808211612b2e576000612b31565b60015b60ff1692915050565b60005b81811015610b495760005b838383818110612b5a57612b5a6148f1565b9050602002810190612b6c9190615134565b90508161ffff161015612d5a57838383818110612b8b57612b8b6148f1565b9050602002810190612b9d9190615134565b8261ffff16818110612bb157612bb16148f1565b9050602002013560000315612d485760086000858585818110612bd657612bd66148f1565b9050602002810190612be89190615134565b8461ffff16818110612bfc57612bfc6148f1565b602090810292909201358352508101919091526040016000205460ff1615612c665760405162461bcd60e51b815260206004820152601a60248201527f4e756c6c69666965722063616e6e6f74206265207265757365640000000000006044820152606401610928565b600160086000868686818110612c7e57612c7e6148f1565b9050602002810190612c909190615134565b8561ffff16818110612ca457612ca46148f1565b90506020020135815260200190815260200160002060006101000a81548160ff0219169083151502179055507fda5c236f484b8df30f1352feea0a68beb5b0981b991061fdc8cdf3ce135c08fe848484818110612d0357612d036148f1565b9050602002810190612d159190615134565b8361ffff16818110612d2957612d296148f1565b90506020020135604051612d3f91815260200190565b60405180910390a15b80612d52816153f9565b915050612b48565b5080612d658161491d565b915050612b3d565b6000805b61ffff8116861115612e255760005b87878361ffff16818110612d9657612d966148f1565b9050602002810190612da89190615134565b90508161ffff161015612e1257612df488888461ffff16818110612dce57612dce6148f1565b9050602002810190612de09190615134565b8361ffff16818110611ca957611ca96148f1565b612dfe90846150b4565b925080612e0a816153f9565b915050612d80565b5080612e1d816153f9565b915050612d71565b508151612e3290826150b4565b905080156132da5760008167ffffffffffffffff811115612e5557612e55614f3d565b604051908082528060200260200182016040528015612e7e578160200160208202803683370190505b5090506000805b61ffff8116881115612fa65760005b89898361ffff16818110612eaa57612eaa6148f1565b9050602002810190612ebc9190615134565b90508161ffff161015612f935789898361ffff16818110612edf57612edf6148f1565b9050602002810190612ef19190615134565b8261ffff16818110612f0557612f056148f1565b90506020020135600014612f815789898361ffff16818110612f2957612f296148f1565b9050602002810190612f3b9190615134565b8261ffff16818110612f4f57612f4f6148f1565b90506020020135848480612f629061491d565b955081518110612f7457612f746148f1565b6020026020010181815250505b80612f8b816153f9565b915050612e94565b5080612f9e816153f9565b915050612e85565b5060005b84518161ffff16101561301457848161ffff1681518110612fcd57612fcd6148f1565b602002602001015160200151838380612fe59061491d565b945081518110612ff757612ff76148f1565b60209081029190910101528061300c816153f9565b915050612faa565b5060006130208361357c565b90506000915060005b61ffff81168711156131a55760005b88888361ffff1681811061304e5761304e6148f1565b90506020028101906130609190615134565b90508161ffff161015613192578a8a8361ffff16818110613083576130836148f1565b90506020028101906130959190615134565b8261ffff168181106130a9576130a96148f1565b90506020020135600014613180577fc2e3bd2d00c3cf4d09298e5a0cfd317cf7a6e5bf15d467cfa805a91e1a4a221d8585815181106130ea576130ea6148f1565b6020026020010151848681518110613104576131046148f1565b60200260200101518b8b8661ffff16818110613122576131226148f1565b90506020028101906131349190615134565b8561ffff16818110613148576131486148f1565b905060200281019061315a91906150c7565b60405161316a9493929190615410565b60405180910390a18361317c8161491d565b9450505b8061318a816153f9565b915050613038565b508061319d816153f9565b915050613029565b5060005b85518161ffff161015611e81577fc2e3bd2d00c3cf4d09298e5a0cfd317cf7a6e5bf15d467cfa805a91e1a4a221d8484815181106131e9576131e96148f1565b60200260200101518385806131fd9061491d565b96508151811061320f5761320f6148f1565b602002602001015160001961322491906151be565b888461ffff168151811061323a5761323a6148f1565b6020908102919091018101515160408051825181850152828401516001600160a01b031681830152818301518051606080840191909152948101516080808401919091529281015160a083015284015160c08201529282015160e084015201516101008201526101200160408051601f19818403018152908290526132c0939291615480565b60405180910390a1806132d2816153f9565b9150506131a9565b505050505050565b60008281526006602090815260408083206001600160a01b038516845290915290205460ff16610bd657613315816138bb565b6133208360206138cd565b60405160200161333192919061549f565b60408051601f198184030181529082905262461bcd60e51b825261092891600401615520565b600080608083901c1561336c57608092831c92015b604083901c1561337e57604092831c92015b602083901c1561339057602092831c92015b601083901c156133a257601092831c92015b600883901c156133b457600892831c92015b600483901c156133c657600492831c92015b600283901c156133d857600292831c92015b600183901c15610a5a5760010192915050565b60006001600160a01b038216613402575047919050565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015282906001600160a01b038216906370a0823190602401610dbd565b919050565b6040517f6352211e0000000000000000000000000000000000000000000000000000000081526004810182905260009083906001600160a01b03821690636352211e90602401602060405180830381865afa9250505080156134cd575060408051601f3d908101601f191682019092526134ca91810190615533565b60015b6134db576000915050610a5a565b306001600160a01b038216036134f657600192505050610a5a565b600092505050610a5a565b505b5092915050565b806000036135235761351e85858585613aae565b6109f0565b6109f085858584613b57565b6001600160a01b03831661354757610b498282613be0565b610b49838383613c83565b8060000361356a5761356584848461352f565b613576565b61357684308584613b57565b50505050565b805160028054606092919060009061359e9084906001600160801b0316615550565b82546101009290920a6001600160801b038181021990931691831602179091556002548451911691506000906135d490836150a1565b90506136017f00000000000000000000000000000000000000000000000000000000000000006002615654565b6002546001600160801b0316111561365b5760405162461bcd60e51b815260206004820152600d60248201527f547265652069732066756c6c2e000000000000000000000000000000000000006044820152606401610928565b835167ffffffffffffffff81111561367557613675614f3d565b60405190808252806020026020018201604052801561369e578160200160208202803683370190505b50925060005b83518110156136e6576136b781836150b4565b8482815181106136c9576136c96148f1565b6020908102919091010152806136de8161491d565b9150506136a4565b5060006136f38583613c97565b905060006137217f0000000000000000000000000000000000000000000000000000000000000000856150a1565b9050600061372e82610edc565b905060005b835181101561383e5783818151811061374e5761374e6148f1565b6020026020010151516001036137ac576137a78561376b8161491d565b965083868481518110613780576137806148f1565b602002602001015160008151811061379a5761379a6148f1565b6020026020010151613f5e565b61382c565b61381e8482815181106137c1576137c16148f1565b60200260200101516000815181106137db576137db6148f1565b60200260200101518583815181106137f5576137f56148f1565b602002602001015160018151811061380f5761380f6148f1565b60200260200101518785613fea565b6138296002866150b4565b94505b806138368161491d565b915050613733565b5060008181526020818152604080832054600280546001600160801b03600160801b918290048116875260019586905293909520919091555460199361388993910490911690615550565b613893919061567f565b600280546001600160801b03928316600160801b029216919091179055509395945050505050565b6060610a5a6001600160a01b03831660145b606060006138dc8360026156a5565b6138e79060026150b4565b67ffffffffffffffff8111156138ff576138ff614f3d565b6040519080825280601f01601f191660200182016040528015613929576020820181803683370190505b5090507f300000000000000000000000000000000000000000000000000000000000000081600081518110613960576139606148f1565b60200101906001600160f81b031916908160001a9053507f7800000000000000000000000000000000000000000000000000000000000000816001815181106139ab576139ab6148f1565b60200101906001600160f81b031916908160001a90535060006139cf8460026156a5565b6139da9060016150b4565b90505b6001811115613a5f577f303132333435363738396162636465660000000000000000000000000000000085600f1660108110613a1b57613a1b6148f1565b1a60f81b828281518110613a3157613a316148f1565b60200101906001600160f81b031916908160001a90535060049490941c93613a58816149a2565b90506139dd565b508315610dfe5760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610928565b6001600160a01b038416613b4b57803414613b315760405162461bcd60e51b815260206004820152602560248201527f6d73672e76616c756520646f65736e2774206d61746368206e6565646564206160448201527f6d6f756e740000000000000000000000000000000000000000000000000000006064820152608401610928565b6001600160a01b0382163014613565576135658282613be0565b61357684848484614091565b6040517f42842e0e0000000000000000000000000000000000000000000000000000000081526001600160a01b0384811660048301528381166024830152604482018390528516906342842e0e90606401600060405180830381600087803b158015613bc257600080fd5b505af1158015613bd6573d6000803e3d6000fd5b5050505050505050565b6000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114613c2d576040519150601f19603f3d011682016040523d82523d6000602084013e613c32565b606091505b5050905080610b495760405162461bcd60e51b815260206004820152600f60248201527f5472616e73666572204661696c656400000000000000000000000000000000006044820152606401610928565b610b496001600160a01b03841683836140a6565b81516060906000613ca96002856156bc565b15159050600081613cbb576000613cbe565b60015b60ff1690506000613ccf82856150a1565b90506000613cde6002836156bc565b15613cff576002613cf08360016150b4565b613cfa91906156d0565b613d0a565b613d0a6002836156d0565b9050613d1681846150b4565b67ffffffffffffffff811115613d2e57613d2e614f3d565b604051908082528060200260200182016040528015613d6157816020015b6060815260200190600190039081613d4c5790505b5095508315613de7576040805160018082528183019092526000916020808301908036833701905050905088600081518110613d9f57613d9f6148f1565b602002602001015181600081518110613dba57613dba6148f1565b6020026020010181815250508087600081518110613dda57613dda6148f1565b6020026020010181905250505b600084613df5576000613df8565b60015b60ff169050805b86821015613f5157606087613e158460016150b4565b1015613ebc5760408051600280825260608201835290916020830190803683370190505090508a8381518110613e4d57613e4d6148f1565b602002602001015181600081518110613e6857613e686148f1565b60209081029190910101528a613e7d8461491d565b93508381518110613e9057613e906148f1565b602002602001015181600181518110613eab57613eab6148f1565b602002602001018181525050613f16565b60408051600180825281830190925290602080830190803683370190505090508a8381518110613eee57613eee6148f1565b602002602001015181600081518110613f0957613f096148f1565b6020026020010181815250505b808983613f228161491d565b945081518110613f3457613f346148f1565b602002602001018190525082613f499061491d565b925050613dff565b5050505050505092915050565b60005b82811161357657613f736002856156bc565b1580613f7f5750836001145b15613faf576000818152602081905260409020829055828114613faa57613fa7826000610d45565b91505b613fcb565b600081815260208190526040902054613fc89083610d45565b91505b613fd66002856156d0565b935080613fe28161491d565b915050613f61565b6000613ff68585610d45565b90506140036002846156d0565b925060015b8281116132da5761401a6002856156bc565b15806140265750836001145b156140565760008181526020819052604090208290558281146140515761404e826000610d45565b91505b614072565b60008181526020819052604090205461406f9083610d45565b91505b61407d6002856156d0565b9350806140898161491d565b915050614008565b6135766001600160a01b038516848484614137565b6040516001600160a01b038316602482015260448101829052610b499084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166001600160e01b031990931692909217909152614188565b6040516001600160a01b03808516602483015283166044820152606481018290526135769085907f23b872dd00000000000000000000000000000000000000000000000000000000906084016140eb565b60006141dd826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166142709092919063ffffffff16565b90508051600014806141fe5750808060200190518101906141fe919061507f565b610b495760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610928565b606061427f8484600085614287565b949350505050565b6060824710156142ff5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610928565b600080866001600160a01b0316858760405161431b91906156e4565b60006040518083038185875af1925050503d8060008114614358576040519150601f19603f3d011682016040523d82523d6000602084013e61435d565b606091505b509150915061216f87838387606083156143d85782516000036143d1576001600160a01b0385163b6143d15760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610928565b508161427f565b61427f83838151156143ed5781518083602001fd5b8060405162461bcd60e51b81526004016109289190615520565b604051806040016040528061441a614427565b8152602001600081525090565b6040518060a001604052806000815260200160006001600160a01b031681526020016144746040518060800160405280600081526020016000815260200160008152602001600081525090565b815260200160008152602001600081525090565b8060408101831015610a5a57600080fd5b6000606082840312156144ab57600080fd5b50919050565b600080600080600061018086880312156144ca57600080fd5b6144d48787614488565b945060c08601878111156144e757600080fd5b6040870194506144f78882614488565b935050614508876101008801614499565b915061016086013567ffffffffffffffff81111561452557600080fd5b86016102a0818903121561453857600080fd5b809150509295509295909350565b60006020828403121561455857600080fd5b81356001600160e01b031981168114610dfe57600080fd5b6001600160a01b0381168114610f7457600080fd5b803561344981614570565b6000602082840312156145a257600080fd5b8135610dfe81614570565b60008083601f8401126145bf57600080fd5b50813567ffffffffffffffff8111156145d757600080fd5b6020830191508360208285010111156145ef57600080fd5b9250929050565b60008060008060006080868803121561460e57600080fd5b853561461981614570565b9450602086013561462981614570565b935060408601359250606086013567ffffffffffffffff81111561464c57600080fd5b614658888289016145ad565b969995985093965092949392505050565b60006020828403121561467b57600080fd5b5035919050565b6000806040838503121561469557600080fd5b8235915060208301356146a781614570565b809150509250929050565b600080600080608085870312156146c857600080fd5b5050823594602084013594506040840135936060013592509050565b600080604083850312156146f757600080fd5b50508035926020909101359150565b60008083601f84011261471857600080fd5b50813567ffffffffffffffff81111561473057600080fd5b6020830191508360208260051b85010111156145ef57600080fd5b6000806000806040858703121561476157600080fd5b843567ffffffffffffffff8082111561477957600080fd5b61478588838901614706565b9096509450602087013591508082111561479e57600080fd5b506147ab87828801614706565b95989497509550505050565b600080602083850312156147ca57600080fd5b823567ffffffffffffffff8111156147e157600080fd5b6147ed858286016145ad565b90969095509350505050565b6000806080838503121561480c57600080fd5b6148168484614499565b946060939093013593505050565b600080600080600060a0868803121561483c57600080fd5b505083359560208501359550604085013594606081013594506080013592509050565b60008235607e1983360301811261487557600080fd5b9190910192915050565b60808101818360005b60048110156148a7578151835260209283019290910190600101614888565b50505092915050565b6000602082840312156148c257600080fd5b5051919050565b60408101818360005b60028110156148a75781518352602092830192909101906001016148d2565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b60006001820161492f5761492f614907565b5060010190565b6001600160801b0382811682821603908082111561350357613503614907565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6001600160a01b0384168152604060208201526000610d3c604083018486614956565b6000816149b1576149b1614907565b506000190190565b803561ffff8116811461344957600080fd5b6000602082840312156149dd57600080fd5b610dfe826149b9565b60a08101818360005b60058110156148a75781518352602092830192909101906001016149ef565b6000808335601e19843603018112614a2557600080fd5b830160208101925035905067ffffffffffffffff811115614a4557600080fd5b8060051b36038213156145ef57600080fd5b8183526000602080850194508260005b85811015614a95578135614a7a81614570565b6001600160a01b031687529582019590820190600101614a67565b509495945050505050565b81835260007f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff831115614ad257600080fd5b8260051b80836020870137939093016020019392505050565b8183526000602080850194508260005b85811015614a9557813587529582019590820190600101614afb565b81835260006020808501808196508560051b810191508460005b87811015614b67578284038952614b488288614a0e565b614b53868284614aa0565b9a87019a9550505090840190600101614b31565b5091979650505050505050565b6000808335601e19843603018112614b8b57600080fd5b830160208101925035905067ffffffffffffffff811115614bab57600080fd5b8036038213156145ef57600080fd5b81835260006020808501808196506005915085821b8101856000805b89811015614c4e578484038b52614bed838a614a0e565b80865288860181891b87018a0183865b84811015614c3757898303601f19018452614c188287614b74565b614c23858284614956565b958f019594505050908c0190600101614bfd565b50509d8a019d965050509287019250600101614bd6565b50919998505050505050505050565b60008235607e19833603018112614c7357600080fd5b90910192915050565b60008135614c8981614570565b6001600160a01b039081168452602083013590614ca582614570565b166020840152614cb86040830183614b74565b60806040860152614ccd608086018284614956565b915050614cdd6060840184614b74565b85830360608701526113b4838284614956565b60006102a082358452614d066020840184614a0e565b826020870152614d198387018284614a57565b92505050614d2a6040840184614a0e565b8583036040870152614d3d838284614aa0565b92505050614d4e6060840184614a0e565b8583036060870152614d61838284614aeb565b92505050614d726080840184614a0e565b8583036080870152614d85838284614b17565b92505050614d9660a0840184614a0e565b85830360a0870152614da9838284614b17565b92505050614dba60c0840184614a0e565b85830360c0870152614dcd838284614bba565b92505050614dde60e0840184614a0e565b85830360e0870152614df1838284614aa0565b92505050610100808401358186015250610120614e33818601828601803582526020810135602083015260408101356040830152606081013560608301525050565b506101a083810135908501526101c080840135908501526101e0614e588185016149b9565b61ffff1690850152610200614e6e848201614585565b6001600160a01b031690850152610220614e89848201614585565b6001600160a01b0316908501526102408381013590850152610260614eb081850185614b74565b86840383880152614ec2848284614956565b9350505050610280614ed681850185614c5d565b858303828701526113b48382614c7c565b608081526000614efa6080830185614cf0565b905061ffff80614f09856149b9565b16602084015280614f1c602086016149b9565b16604084015280614f2f604086016149b9565b166060840152509392505050565b634e487b7160e01b600052604160045260246000fd5b60405160a0810167ffffffffffffffff81118282101715614f7657614f76614f3d565b60405290565b6040516080810167ffffffffffffffff81118282101715614f7657614f76614f3d565b604051601f8201601f1916810167ffffffffffffffff81118282101715614fc857614fc8614f3d565b604052919050565b600067ffffffffffffffff821115614fea57614fea614f3d565b5060051b60200190565b6000602080838503121561500757600080fd5b825167ffffffffffffffff81111561501e57600080fd5b8301601f8101851361502f57600080fd5b805161504261503d82614fd0565b614f9f565b81815260059190911b8201830190838101908783111561506157600080fd5b928401925b8284101561216f57835182529284019290840190615066565b60006020828403121561509157600080fd5b81518015158114610dfe57600080fd5b81810381811115610a5a57610a5a614907565b80820180821115610a5a57610a5a614907565b6000808335601e198436030181126150de57600080fd5b83018035915067ffffffffffffffff8211156150f957600080fd5b6020019150368190038213156145ef57600080fd5b6040815260006151216040830186614cf0565b82810360208401526113b4818587614956565b6000808335601e1984360301811261514b57600080fd5b83018035915067ffffffffffffffff82111561516657600080fd5b6020019150600581901b36038213156145ef57600080fd5b808201828112600083128015821682158216171561350157613501614907565b818103600083128015838313168383128216171561350357613503614907565b80820260008212600160ff1b841416156151da576151da614907565b8181058314821517610a5a57610a5a614907565b600067ffffffffffffffff80831681810361520b5761520b614907565b6001019392505050565b634e487b7160e01b600052602160045260246000fd5b60006101408083016040808a86378085018960005b600281101561525d57838284379183019190830190600101615240565b505050808860c08701375061010084019190915284519081905261016083019060209081870160005b828110156152a257815185529383019390830190600101615286565b50505050610120929092019290925295945050505050565b6000600160ff1b82036152cf576152cf614907565b5060000390565b602081526000610dfe6020830184614cf0565b600060208083850312156152fc57600080fd5b825167ffffffffffffffff81111561531357600080fd5b8301601f8101851361532457600080fd5b805161533261503d82614fd0565b81815260089190911b8201830190838101908783111561535157600080fd5b928401925b8284101561216f578388036101008112156153715760008081fd5b615379614f53565b855181528686015161538a81614570565b8188015260406080603f1984018113156153a45760008081fd5b6153ac614f7c565b8883015181526060808a01518b830152828a01518483015260a08a0151818301529284015260c08801519183019190915260e0870151908201528352506101009093019290840190615356565b600061ffff80831681810361520b5761520b614907565b8481528360208201526060604082015260006113b4606083018486614956565b60005b8381101561544b578181015183820152602001615433565b50506000910152565b6000815180845261546c816020860160208601615430565b601f01601f19169290920160200192915050565b838152826020820152606060408201526000610d3c6060830184615454565b7f416363657373436f6e74726f6c3a206163636f756e74200000000000000000008152600083516154d7816017850160208801615430565b7f206973206d697373696e6720726f6c65200000000000000000000000000000006017918401918201528351615514816028840160208801615430565b01602801949350505050565b602081526000610dfe6020830184615454565b60006020828403121561554557600080fd5b8151610dfe81614570565b6001600160801b0381811683821601908082111561350357613503614907565b600181815b808511156155ab57816000190482111561559157615591614907565b8085161561559e57918102915b93841c9390800290615575565b509250929050565b6000826155c257506001610a5a565b816155cf57506000610a5a565b81600181146155e557600281146155ef5761560b565b6001915050610a5a565b60ff84111561560057615600614907565b50506001821b610a5a565b5060208310610133831016604e8410600b841016171561562e575081810a610a5a565b6156388383615570565b806000190482111561564c5761564c614907565b029392505050565b6000610dfe6001600160801b038416836155b3565b634e487b7160e01b600052601260045260246000fd5b60006001600160801b038084168061569957615699615669565b92169190910692915050565b8082028115828204841417610a5a57610a5a614907565b6000826156cb576156cb615669565b500690565b6000826156df576156df615669565b500490565b6000825161487581846020870161543056fea264697066735822122068962a878d3cd21b4be9fe8751a72f8385768ea6a148bd95850518ed06cf382e64736f6c6343000811003347ddd44be4e69e3bb12e0b1ae411c5e2264c8a03557812e6728682c3b1a4a9dd0000000000000000000000000000000000000000000000000000000000000019000000000000000000000000cb9e6bfe2c27b90f39a04a1a3ffb6e97c2faa02d000000000000000000000000e90481f96af203bf4cff149edeaa656a894a4c84000000000000000000000000d5235593bffa74442c552dff384fb8c9d6b7971e0000000000000000000000000036e884cab4f427193839788edebb4b92b9a0690000000000000000000000008f899971c3e0b91820b983cfd57bc551291d2ba200000000000000000000000053a1eeb0c182144b27ca0a2010939da33ebc207d
Deployed Bytecode
0x6080604052600436106102ca5760003560e01c80637e5a921811610179578063ae669f0e116100d6578063d547741f1161008a578063ee6be04011610064578063ee6be0401461085b578063f2fde38b1461088f578063f46732c7146108af57600080fd5b8063d547741f146107fd578063e243c5fb1461081d578063e30c39781461083d57600080fd5b8063c98aeff5116100bb578063c98aeff514610779578063ca5ee4b214610799578063d21e82ab146107cd57600080fd5b8063ae669f0e14610746578063c21c358e1461076657600080fd5b8063944e8fb41161012d578063a217fddf11610112578063a217fddf146106dd578063a81a2688146106f2578063a83b67451461072657600080fd5b8063944e8fb4146106aa5780639671084a146106bd57600080fd5b806382fbdc9c1161015e57806382fbdc9c146106265780638da5cb5b1461064657806391d148541461066457600080fd5b80637e5a9218146105f157806380759f1f1461061157600080fd5b806336568abe11610227578063529dd5ea116101db578063715018a6116101c0578063715018a6146105a757806377eadab7146105bc57806379ba5097146105dc57600080fd5b8063529dd5ea146105485780635b9e89d31461058757600080fd5b80633abd53ca1161020c5780633abd53ca146104e85780633b3ccded14610508578063511c53ff1461052857600080fd5b806336568abe146104a8578063396f3e5f146104c857600080fd5b8063150b7a021161027e578063248a9ca311610263578063248a9ca31461041d5780632f2ff15d1461045b578063313529361461047b57600080fd5b8063150b7a021461039f5780631ce573ec146103fd57600080fd5b80630d1dafaa116102af5780630d1dafaa1461032057806313e44e601461036c57806313fbc8d41461038c57600080fd5b806301988136146102d657806301ffc9a7146102eb57600080fd5b366102d157005b600080fd5b6102e96102e43660046144b1565b6108cf565b005b3480156102f757600080fd5b5061030b610306366004614546565b6109f7565b60405190151581526020015b60405180910390f35b34801561032c57600080fd5b506103547f000000000000000000000000d5235593bffa74442c552dff384fb8c9d6b7971e81565b6040516001600160a01b039091168152602001610317565b34801561037857600080fd5b506102e9610387366004614590565b610a60565b6102e961039a3660046144b1565b610aad565b3480156103ab57600080fd5b506103e46103ba3660046145f6565b7f150b7a020000000000000000000000000000000000000000000000000000000095945050505050565b6040516001600160e01b03199091168152602001610317565b34801561040957600080fd5b506102e9610418366004614669565b610ab5565b34801561042957600080fd5b5061044d610438366004614669565b60009081526006602052604090206001015490565b604051908152602001610317565b34801561046757600080fd5b506102e9610476366004614682565b610b24565b34801561048757600080fd5b5061044d610496366004614669565b60006020819052908152604090205481565b3480156104b457600080fd5b506102e96104c3366004614682565b610b4e565b3480156104d457600080fd5b506102e96104e3366004614682565b610bda565b3480156104f457600080fd5b506102e9610503366004614590565b610c40565b34801561051457600080fd5b5061044d6105233660046146b2565b610c8d565b34801561053457600080fd5b5061044d6105433660046146e4565b610d45565b34801561055457600080fd5b5060025461056f90600160801b90046001600160801b031681565b6040516001600160801b039091168152602001610317565b34801561059357600080fd5b506102e96105a2366004614669565b610e05565b3480156105b357600080fd5b506102e9610e66565b3480156105c857600080fd5b5061044d6105d7366004614669565b610edc565b3480156105e857600080fd5b506102e9610ee9565b3480156105fd57600080fd5b506102e961060c36600461474b565b610f77565b34801561061d57600080fd5b5061044d611093565b34801561063257600080fd5b506102e96106413660046147b7565b6110ff565b34801561065257600080fd5b506003546001600160a01b0316610354565b34801561067057600080fd5b5061030b61067f366004614682565b60009182526006602090815260408084206001600160a01b0393909316845291905290205460ff1690565b6102e96106b83660046144b1565b6111b2565b3480156106c957600080fd5b50600954610354906001600160a01b031681565b3480156106e957600080fd5b5061044d600081565b3480156106fe57600080fd5b506103547f000000000000000000000000e90481f96af203bf4cff149edeaa656a894a4c8481565b34801561073257600080fd5b5061030b610741366004614669565b61120f565b34801561075257600080fd5b5061044d6107613660046147f9565b611281565b6102e96107743660046144b1565b6112f7565b34801561078557600080fd5b5061044d610794366004614824565b6112ff565b3480156107a557600080fd5b506103547f000000000000000000000000cb9e6bfe2c27b90f39a04a1a3ffb6e97c2faa02d81565b3480156107d957600080fd5b5061030b6107e8366004614669565b60086020526000908152604090205460ff1681565b34801561080957600080fd5b506102e9610818366004614682565b6113be565b34801561082957600080fd5b50600a54610354906001600160a01b031681565b34801561084957600080fd5b506004546001600160a01b0316610354565b34801561086757600080fd5b5061044d7f47ddd44be4e69e3bb12e0b1ae411c5e2264c8a03557812e6728682c3b1a4a9dd81565b34801561089b57600080fd5b506102e96108aa366004614590565b6113e3565b3480156108bb57600080fd5b5060025461056f906001600160801b031681565b6108d76114a6565b8061024001356000036109315760405162461bcd60e51b815260206004820152601a60248201527f65787465726e616c41646472657373206973206d697373696e6700000000000060448201526064015b60405180910390fd5b600061094161028083018361485f565b610952906040810190602001614590565b6001600160a01b031614158061098d5750600061097361028083018361485f565b610981906020810190614590565b6001600160a01b031614155b6109d95760405162461bcd60e51b815260206004820152601760248201527f686f6f6b436f6e7472616374206973206d697373696e670000000000000000006044820152606401610928565b6109e685858585856114ff565b6109f06001600755565b5050505050565b60006001600160e01b031982167f7965db0b000000000000000000000000000000000000000000000000000000001480610a5a57507f01ffc9a7000000000000000000000000000000000000000000000000000000006001600160e01b03198316145b92915050565b7f47ddd44be4e69e3bb12e0b1ae411c5e2264c8a03557812e6728682c3b1a4a9dd610a8a81611e8d565b50600a80546001600160a01b0319166001600160a01b0392909216919091179055565b6109d96114a6565b6000610ac081611e8d565b6000828152600b602090815260409182902080546001600160a01b0319811690915591516001600160a01b03909216808352917f5cc7d016d05c39a385ee58ffd86a154b6079ed6e14d3a266b94f6276e040cf0f91015b60405180910390a1505050565b600082815260066020526040902060010154610b3f81611e8d565b610b498383611e97565b505050565b6001600160a01b0381163314610bcc5760405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201527f20726f6c657320666f722073656c6600000000000000000000000000000000006064820152608401610928565b610bd68282611f39565b5050565b6000610be581611e8d565b6000838152600b602090815260409182902080546001600160a01b0319166001600160a01b03861690811790915591519182527f5d494982f506adaf74c262193225f5396e00122e4d8b4da60ee1c60fa6e446ad9101610b17565b7f47ddd44be4e69e3bb12e0b1ae411c5e2264c8a03557812e6728682c3b1a4a9dd610c6a81611e8d565b50600980546001600160a01b0319166001600160a01b0392909216919091179055565b60007f000000000000000000000000e90481f96af203bf4cff149edeaa656a894a4c846001600160a01b031663248f66776040518060800160405280888152602001878152602001868152602001858152506040518263ffffffff1660e01b8152600401610cfb919061487f565b602060405180830381865afa158015610d18573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d3c91906148b0565b95945050505050565b6040805180820182528381526020810183905290517f29a5f2f60000000000000000000000000000000000000000000000000000000081526000916001600160a01b037f000000000000000000000000cb9e6bfe2c27b90f39a04a1a3ffb6e97c2faa02d16916329a5f2f691610dbd916004016148c9565b602060405180830381865afa158015610dda573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610dfe91906148b0565b9392505050565b610e0d611fbc565b6000818152600560205260409081902080546001600160a01b0319169055517f2e4fe6c83a0e1e30adfe1958137de9f4abe532810e7286db4a2590b2782c118b90610e5b9083815260200190565b60405180910390a150565b610e6e611fbc565b60405162461bcd60e51b815260206004820152602160248201527f546865204f776e6572736869702063616e6e6f742062652072656e6f756e636560448201527f64000000000000000000000000000000000000000000000000000000000000006064820152608401610928565b6000610a5a826001612018565b60045433906001600160a01b03168114610f6b5760405162461bcd60e51b815260206004820152602960248201527f4f776e61626c6532537465703a2063616c6c6572206973206e6f74207468652060448201527f6e6577206f776e657200000000000000000000000000000000000000000000006064820152608401610928565b610f7481612063565b50565b610f7f611fbc565b60005b838110156109f057828282818110610f9c57610f9c6148f1565b9050602002016020810190610fb19190614590565b60056000878785818110610fc757610fc76148f1565b90506020020135815260200190815260200160002060006101000a8154816001600160a01b0302191690836001600160a01b031602179055507f3d47d745bf8c193d19b6eff4f8bb5ff806af27c6fe2863b21a76c292b8f48e13858583818110611033576110336148f1565b9050602002013584848481811061104c5761104c6148f1565b90506020020160208101906110619190614590565b604080519283526001600160a01b0390911660208301520160405180910390a18061108b8161491d565b915050610f82565b6002546000906001908290600160801b90046001600160801b03166110c3576110be60016019614936565b6110e2565b6002546110e290600190600160801b90046001600160801b0316614936565b6001600160801b0316815260200190815260200160002054905090565b600a546040517f7800e7140000000000000000000000000000000000000000000000000000000081523360048201526001600160a01b0390911690637800e7149060240160006040518083038186803b15801561115b57600080fd5b505afa15801561116f573d6000803e3d6000fd5b505050507fbf6a48f464846d0bb8735df8832ed2e3151e50b349fa76f15510a3e62baf3ca23383836040516111a69392919061497f565b60405180910390a15050565b6111ba6114a6565b8061024001356000036109d95760405162461bcd60e51b815260206004820152601a60248201527f65787465726e616c41646472657373206973206d697373696e670000000000006044820152606401610928565b600254600090600160801b90046001600160801b03165b80600003611232575060195b8061123c816149a2565b6000818152600160205260409020549092508403905061125f5750600192915050565b600254600160801b90046001600160801b031681036112265750600092915050565b600061129060208401846149cb565b6112a060408501602086016149cb565b6112b060608601604087016149cb565b6040805161ffff94851660208201529284169083015290911660608201526080810183905260a00160408051601f1981840301815291905280516020909101209392505050565b6109316114a6565b60007f000000000000000000000000d5235593bffa74442c552dff384fb8c9d6b7971e6001600160a01b0316634937a2586040518060a00160405280898152602001888152602001878152602001868152602001858152506040518263ffffffff1660e01b815260040161137391906149e6565b602060405180830381865afa158015611390573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113b491906148b0565b9695505050505050565b6000828152600660205260409020600101546113d981611e8d565b610b498383611f39565b6113eb611fbc565b600480546001600160a01b0383166001600160a01b0319909116811790915561141c6003546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b600380546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a35050565b6002600754036114f85760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610928565b6002600755565b6009546040517fdee949280000000000000000000000000000000000000000000000000000000081526000916001600160a01b03169063dee949289061154b9085908790600401614ee7565b600060405180830381865afa158015611568573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526115909190810190614ff4565b90506115ad868686846115a888886102400135611281565b61207c565b6115f95760405162461bcd60e51b815260206004820152600d60248201527f496e76616c69642050726f6f66000000000000000000000000000000000000006044820152606401610928565b611603823561120f565b61164f5760405162461bcd60e51b815260206004820152601d60248201527f48696e6b616c20526f6f74204861736820697320496e636f72726563740000006044820152606401610928565b600a546040517f32f7a1400000000000000000000000000000000000000000000000000000000081526101a084013560048201523360248201526001600160a01b03909116906332f7a14090604401602060405180830381865afa1580156116bb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116df919061507f565b6117515760405162461bcd60e51b815260206004820152602360248201527f41636365737320546f6b656e20526f6f74204861736820697320496e636f727260448201527f65637400000000000000000000000000000000000000000000000000000000006064820152608401610928565b61175d6101a4426150a1565b82610100013511801561177f5750611777426101a46150b4565b826101000135105b6117f15760405162461bcd60e51b815260206004820152603360248201527f54696d657374616d702070726f766964656420646f6573206e6f7420616c696760448201527f6e20776974682063757272656e742074696d65000000000000000000000000006064820152608401610928565b506060600061180461028084018461485f565b611812906020810190614590565b6001600160a01b0316146118be57600061183061028084018461485f565b61183e906020810190614590565b90506001600160a01b03811663d6fd34f48461185e61028082018261485f565b61186c9060408101906150c7565b6040518463ffffffff1660e01b815260040161188a9392919061510e565b600060405180830381600087803b1580156118a457600080fd5b505af11580156118b8573d6000803e3d6000fd5b50505050505b60006118e26118d06020850185615134565b6118dd6040870187615134565b61217a565b90508261024001356000036118ff576118fa83612306565b61190b565b61190883612849565b91505b600061192a61191d6020860186615134565b6118dd6040880188615134565b90506000835167ffffffffffffffff81111561194857611948614f3d565b60405190808252806020026020018201604052801561198157816020015b61196e614407565b8152602001906001900390816119665790505b5090506000805b6119956020880188615134565b90508167ffffffffffffffff161015611d78576000806119b860208a018a615134565b8467ffffffffffffffff168181106119d2576119d26148f1565b90506020020160208101906119e79190614590565b6001600160a01b031603611a5957858267ffffffffffffffff1681518110611a1157611a116148f1565b602002602001015134868467ffffffffffffffff1681518110611a3657611a366148f1565b6020026020010151611a48919061517e565b611a52919061519e565b9050611aae565b858267ffffffffffffffff1681518110611a7557611a756148f1565b6020026020010151858367ffffffffffffffff1681518110611a9957611a996148f1565b6020026020010151611aab919061519e565b90505b611abb6060890189615134565b8367ffffffffffffffff16818110611ad557611ad56148f1565b90506020020135811215611b2b5760405162461bcd60e51b815260206004820152601b60248201527f496e62616c616e636520696e20746f6b656e20646574656374656400000000006044820152606401610928565b6000805b8851811015611c2a57611b4560208b018b615134565b8567ffffffffffffffff16818110611b5f57611b5f6148f1565b9050602002016020810190611b749190614590565b6001600160a01b0316898281518110611b8f57611b8f6148f1565b6020026020010151602001516001600160a01b031603611c1857888181518110611bbb57611bbb6148f1565b6020026020010151600001519150611beb898281518110611bde57611bde6148f1565b6020026020010151612a92565b8686611bf68161491d565b975081518110611c0857611c086148f1565b6020026020010181905250611c2a565b80611c228161491d565b915050611b2f565b50611c3860608a018a615134565b8467ffffffffffffffff16818110611c5257611c526148f1565b90506020020135611cb58a8060a00190611c6c9190615134565b8667ffffffffffffffff16818110611c8657611c866148f1565b9050602002810190611c989190615134565b6000818110611ca957611ca96148f1565b90506020020135612b1e565b611cbf91906151be565b611cc9908261517e565b8214611d635760405162461bcd60e51b815260206004820152604f60248201527f42616c616e636520446966662053686f756c6420626520657175616c20746f2060448201527f73756d206f66206f6e636861696e20616e64206f6666636861696e206372656160648201527f74656420636f6d6d69746d656e74730000000000000000000000000000000000608482015260a401610928565b50508080611d70906151ee565b915050611988565b506000611d8961028088018861485f565b611d9a906040810190602001614590565b6001600160a01b031614611e49576000611db861028088018861485f565b611dc9906040810190602001614590565b90506001600160a01b038116630448463988611de961028082018261485f565b611df79060608101906150c7565b6040518463ffffffff1660e01b8152600401611e159392919061510e565b600060405180830381600087803b158015611e2f57600080fd5b505af1158015611e43573d6000803e3d6000fd5b50505050505b611e5e611e596080880188615134565b612b3a565b611e81611e6e60a0880188615134565b611e7b60c08a018a615134565b86612d6d565b50505050505050505050565b610f7481336132e2565b60008281526006602090815260408083206001600160a01b038516845290915290205460ff16610bd65760008281526006602090815260408083206001600160a01b03851684529091529020805460ff19166001179055611ef53390565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b60008281526006602090815260408083206001600160a01b038516845290915290205460ff1615610bd65760008281526006602090815260408083206001600160a01b0385168085529252808320805460ff1916905551339285917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a45050565b6003546001600160a01b031633146120165760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152606401610928565b565b60008061202484613357565b9050600183600281111561203a5761203a615215565b14801561204a575083816001901b105b612055576000612058565b60015b60ff16019392505050565b600480546001600160a01b0319169055610f7481611454565b6000818152600560205260408120546001600160a01b0316806120e15760405162461bcd60e51b815260206004820181905260248201527f43616e6e6f742066696e6420617070726f7072696174652076657269666965726044820152606401610928565b6040517f6743734c0000000000000000000000000000000000000000000000000000000081526001600160a01b03821690636743734c9061212e908a908a908a908a908a9060040161522b565b602060405180830381865afa15801561214b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061216f919061507f565b979650505050505050565b60608367ffffffffffffffff81111561219557612195614f3d565b6040519080825280602002602001820160405280156121be578160200160208202803683370190505b50905060005b67ffffffffffffffff81168511156122fd5783838267ffffffffffffffff168181106121f2576121f26148f1565b905060200201356000036122665761223986868367ffffffffffffffff1681811061221f5761221f6148f1565b90506020020160208101906122349190614590565b6133eb565b828267ffffffffffffffff1681518110612255576122556148f1565b6020026020010181815250506122eb565b6122c286868367ffffffffffffffff16818110612285576122856148f1565b905060200201602081019061229a9190614590565b85858467ffffffffffffffff168181106122b6576122b66148f1565b9050602002013561344e565b828267ffffffffffffffff16815181106122de576122de6148f1565b6020026020010181815250505b806122f5816151ee565b9150506121c4565b50949350505050565b60005b6123166020830183615134565b90508167ffffffffffffffff161015610bd65760006123386060840184615134565b8367ffffffffffffffff16818110612352576123526148f1565b9050602002013513156124a9573361237261024084016102208501614590565b6001600160a01b0316146123ee5760405162461bcd60e51b815260206004820152602360248201527f4465706f7369742073686f756c6420636f6d652066726f6d207468652073656e60448201527f64657200000000000000000000000000000000000000000000000000000000006064820152608401610928565b6124a46123fe6020840184615134565b8367ffffffffffffffff16818110612418576124186148f1565b905060200201602081019061242d9190614590565b61243f61024085016102208601614590565b3061244d6060870187615134565b8667ffffffffffffffff16818110612467576124676148f1565b9050602002013586806040019061247e9190615134565b8767ffffffffffffffff16818110612498576124986148f1565b9050602002013561350a565b612837565b60006124b86060840184615134565b8367ffffffffffffffff168181106124d2576124d26148f1565b905060200201351215612837576000806124f461022085016102008601614590565b6001600160a01b03161461276f576009546001600160a01b03166342a55d826125206060860186615134565b8567ffffffffffffffff1681811061253a5761253a6148f1565b9050602002013561254a906152ba565b6125576020870187615134565b8667ffffffffffffffff16818110612571576125716148f1565b90506020020160208101906125869190614590565b61259360e0880188615134565b8767ffffffffffffffff168181106125ad576125ad6148f1565b6040516001600160e01b031960e088901b16815260048101959095526001600160a01b039093166024850152506020909102013560448201526102408601356064820152608401602060405180830381865afa158015612611573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061263591906148b0565b90506126446060840184615134565b8367ffffffffffffffff1681811061265e5761265e6148f1565b9050602002013561266e906152ba565b8111156126e35760405162461bcd60e51b815260206004820152602160248201527f52656c617920466565206973206f76657220776974686472617720616d6f756e60448201527f74000000000000000000000000000000000000000000000000000000000000006064820152608401610928565b6126f06040840184615134565b8367ffffffffffffffff1681811061270a5761270a6148f1565b9050602002013560000361276f5761276f6127286020850185615134565b8467ffffffffffffffff16818110612742576127426148f1565b90506020020160208101906127579190614590565b61276961022086016102008701614590565b8361352f565b61283561277f6020850185615134565b8467ffffffffffffffff16818110612799576127996148f1565b90506020020160208101906127ae9190614590565b6127c061024086016102208701614590565b836127ce6060880188615134565b8767ffffffffffffffff168181106127e8576127e86148f1565b905060200201356127f8906152ba565b61280291906150a1565b61280f6040880188615134565b8767ffffffffffffffff16818110612829576128296148f1565b90506020020135613552565b505b80612841816151ee565b915050612309565b606061285d61024083016102208401614590565b6102408301356000908152600b60205260409020546001600160a01b0390811691161480156128a75750600061289b61024084016102208501614590565b6001600160a01b031614155b6128f35760405162461bcd60e51b815260206004820152601760248201527f556e6b6e6f776e2065787465726e616c416464726573730000000000000000006044820152606401610928565b60005b6129036020840184615134565b90508167ffffffffffffffff161015612a0d5760006129256060850185615134565b8367ffffffffffffffff1681811061293f5761293f6148f1565b9050602002013512156129fb576129fb61295c6020850185615134565b8367ffffffffffffffff16818110612976576129766148f1565b905060200201602081019061298b9190614590565b61299d61024086016102208701614590565b6129aa6060870187615134565b8567ffffffffffffffff168181106129c4576129c46148f1565b905060200201356129d4906152ba565b6129e16040880188615134565b8667ffffffffffffffff16818110612829576128296148f1565b80612a05816151ee565b9150506128f6565b50612a2061024083016102208401614590565b6001600160a01b03166382b4b88c836040518263ffffffff1660e01b8152600401612a4b91906152d6565b6000604051808303816000875af1158015612a6a573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052610a5a91908101906152e9565b612a9a614407565b608082015160009015612adc57612ad5836000015184602001516001600160a01b0316856040015160200151866060015187608001516112ff565b9050612b08565b612b05836000015184602001516001600160a01b03168560400151602001518660600151610c8d565b90505b6040805180820190915292835260208301525090565b6000808211612b2e576000612b31565b60015b60ff1692915050565b60005b81811015610b495760005b838383818110612b5a57612b5a6148f1565b9050602002810190612b6c9190615134565b90508161ffff161015612d5a57838383818110612b8b57612b8b6148f1565b9050602002810190612b9d9190615134565b8261ffff16818110612bb157612bb16148f1565b9050602002013560000315612d485760086000858585818110612bd657612bd66148f1565b9050602002810190612be89190615134565b8461ffff16818110612bfc57612bfc6148f1565b602090810292909201358352508101919091526040016000205460ff1615612c665760405162461bcd60e51b815260206004820152601a60248201527f4e756c6c69666965722063616e6e6f74206265207265757365640000000000006044820152606401610928565b600160086000868686818110612c7e57612c7e6148f1565b9050602002810190612c909190615134565b8561ffff16818110612ca457612ca46148f1565b90506020020135815260200190815260200160002060006101000a81548160ff0219169083151502179055507fda5c236f484b8df30f1352feea0a68beb5b0981b991061fdc8cdf3ce135c08fe848484818110612d0357612d036148f1565b9050602002810190612d159190615134565b8361ffff16818110612d2957612d296148f1565b90506020020135604051612d3f91815260200190565b60405180910390a15b80612d52816153f9565b915050612b48565b5080612d658161491d565b915050612b3d565b6000805b61ffff8116861115612e255760005b87878361ffff16818110612d9657612d966148f1565b9050602002810190612da89190615134565b90508161ffff161015612e1257612df488888461ffff16818110612dce57612dce6148f1565b9050602002810190612de09190615134565b8361ffff16818110611ca957611ca96148f1565b612dfe90846150b4565b925080612e0a816153f9565b915050612d80565b5080612e1d816153f9565b915050612d71565b508151612e3290826150b4565b905080156132da5760008167ffffffffffffffff811115612e5557612e55614f3d565b604051908082528060200260200182016040528015612e7e578160200160208202803683370190505b5090506000805b61ffff8116881115612fa65760005b89898361ffff16818110612eaa57612eaa6148f1565b9050602002810190612ebc9190615134565b90508161ffff161015612f935789898361ffff16818110612edf57612edf6148f1565b9050602002810190612ef19190615134565b8261ffff16818110612f0557612f056148f1565b90506020020135600014612f815789898361ffff16818110612f2957612f296148f1565b9050602002810190612f3b9190615134565b8261ffff16818110612f4f57612f4f6148f1565b90506020020135848480612f629061491d565b955081518110612f7457612f746148f1565b6020026020010181815250505b80612f8b816153f9565b915050612e94565b5080612f9e816153f9565b915050612e85565b5060005b84518161ffff16101561301457848161ffff1681518110612fcd57612fcd6148f1565b602002602001015160200151838380612fe59061491d565b945081518110612ff757612ff76148f1565b60209081029190910101528061300c816153f9565b915050612faa565b5060006130208361357c565b90506000915060005b61ffff81168711156131a55760005b88888361ffff1681811061304e5761304e6148f1565b90506020028101906130609190615134565b90508161ffff161015613192578a8a8361ffff16818110613083576130836148f1565b90506020028101906130959190615134565b8261ffff168181106130a9576130a96148f1565b90506020020135600014613180577fc2e3bd2d00c3cf4d09298e5a0cfd317cf7a6e5bf15d467cfa805a91e1a4a221d8585815181106130ea576130ea6148f1565b6020026020010151848681518110613104576131046148f1565b60200260200101518b8b8661ffff16818110613122576131226148f1565b90506020028101906131349190615134565b8561ffff16818110613148576131486148f1565b905060200281019061315a91906150c7565b60405161316a9493929190615410565b60405180910390a18361317c8161491d565b9450505b8061318a816153f9565b915050613038565b508061319d816153f9565b915050613029565b5060005b85518161ffff161015611e81577fc2e3bd2d00c3cf4d09298e5a0cfd317cf7a6e5bf15d467cfa805a91e1a4a221d8484815181106131e9576131e96148f1565b60200260200101518385806131fd9061491d565b96508151811061320f5761320f6148f1565b602002602001015160001961322491906151be565b888461ffff168151811061323a5761323a6148f1565b6020908102919091018101515160408051825181850152828401516001600160a01b031681830152818301518051606080840191909152948101516080808401919091529281015160a083015284015160c08201529282015160e084015201516101008201526101200160408051601f19818403018152908290526132c0939291615480565b60405180910390a1806132d2816153f9565b9150506131a9565b505050505050565b60008281526006602090815260408083206001600160a01b038516845290915290205460ff16610bd657613315816138bb565b6133208360206138cd565b60405160200161333192919061549f565b60408051601f198184030181529082905262461bcd60e51b825261092891600401615520565b600080608083901c1561336c57608092831c92015b604083901c1561337e57604092831c92015b602083901c1561339057602092831c92015b601083901c156133a257601092831c92015b600883901c156133b457600892831c92015b600483901c156133c657600492831c92015b600283901c156133d857600292831c92015b600183901c15610a5a5760010192915050565b60006001600160a01b038216613402575047919050565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815230600482015282906001600160a01b038216906370a0823190602401610dbd565b919050565b6040517f6352211e0000000000000000000000000000000000000000000000000000000081526004810182905260009083906001600160a01b03821690636352211e90602401602060405180830381865afa9250505080156134cd575060408051601f3d908101601f191682019092526134ca91810190615533565b60015b6134db576000915050610a5a565b306001600160a01b038216036134f657600192505050610a5a565b600092505050610a5a565b505b5092915050565b806000036135235761351e85858585613aae565b6109f0565b6109f085858584613b57565b6001600160a01b03831661354757610b498282613be0565b610b49838383613c83565b8060000361356a5761356584848461352f565b613576565b61357684308584613b57565b50505050565b805160028054606092919060009061359e9084906001600160801b0316615550565b82546101009290920a6001600160801b038181021990931691831602179091556002548451911691506000906135d490836150a1565b90506136017f00000000000000000000000000000000000000000000000000000000000000196002615654565b6002546001600160801b0316111561365b5760405162461bcd60e51b815260206004820152600d60248201527f547265652069732066756c6c2e000000000000000000000000000000000000006044820152606401610928565b835167ffffffffffffffff81111561367557613675614f3d565b60405190808252806020026020018201604052801561369e578160200160208202803683370190505b50925060005b83518110156136e6576136b781836150b4565b8482815181106136c9576136c96148f1565b6020908102919091010152806136de8161491d565b9150506136a4565b5060006136f38583613c97565b905060006137217f0000000000000000000000000000000000000000000000000000000001000000856150a1565b9050600061372e82610edc565b905060005b835181101561383e5783818151811061374e5761374e6148f1565b6020026020010151516001036137ac576137a78561376b8161491d565b965083868481518110613780576137806148f1565b602002602001015160008151811061379a5761379a6148f1565b6020026020010151613f5e565b61382c565b61381e8482815181106137c1576137c16148f1565b60200260200101516000815181106137db576137db6148f1565b60200260200101518583815181106137f5576137f56148f1565b602002602001015160018151811061380f5761380f6148f1565b60200260200101518785613fea565b6138296002866150b4565b94505b806138368161491d565b915050613733565b5060008181526020818152604080832054600280546001600160801b03600160801b918290048116875260019586905293909520919091555460199361388993910490911690615550565b613893919061567f565b600280546001600160801b03928316600160801b029216919091179055509395945050505050565b6060610a5a6001600160a01b03831660145b606060006138dc8360026156a5565b6138e79060026150b4565b67ffffffffffffffff8111156138ff576138ff614f3d565b6040519080825280601f01601f191660200182016040528015613929576020820181803683370190505b5090507f300000000000000000000000000000000000000000000000000000000000000081600081518110613960576139606148f1565b60200101906001600160f81b031916908160001a9053507f7800000000000000000000000000000000000000000000000000000000000000816001815181106139ab576139ab6148f1565b60200101906001600160f81b031916908160001a90535060006139cf8460026156a5565b6139da9060016150b4565b90505b6001811115613a5f577f303132333435363738396162636465660000000000000000000000000000000085600f1660108110613a1b57613a1b6148f1565b1a60f81b828281518110613a3157613a316148f1565b60200101906001600160f81b031916908160001a90535060049490941c93613a58816149a2565b90506139dd565b508315610dfe5760405162461bcd60e51b815260206004820181905260248201527f537472696e67733a20686578206c656e67746820696e73756666696369656e746044820152606401610928565b6001600160a01b038416613b4b57803414613b315760405162461bcd60e51b815260206004820152602560248201527f6d73672e76616c756520646f65736e2774206d61746368206e6565646564206160448201527f6d6f756e740000000000000000000000000000000000000000000000000000006064820152608401610928565b6001600160a01b0382163014613565576135658282613be0565b61357684848484614091565b6040517f42842e0e0000000000000000000000000000000000000000000000000000000081526001600160a01b0384811660048301528381166024830152604482018390528516906342842e0e90606401600060405180830381600087803b158015613bc257600080fd5b505af1158015613bd6573d6000803e3d6000fd5b5050505050505050565b6000826001600160a01b03168260405160006040518083038185875af1925050503d8060008114613c2d576040519150601f19603f3d011682016040523d82523d6000602084013e613c32565b606091505b5050905080610b495760405162461bcd60e51b815260206004820152600f60248201527f5472616e73666572204661696c656400000000000000000000000000000000006044820152606401610928565b610b496001600160a01b03841683836140a6565b81516060906000613ca96002856156bc565b15159050600081613cbb576000613cbe565b60015b60ff1690506000613ccf82856150a1565b90506000613cde6002836156bc565b15613cff576002613cf08360016150b4565b613cfa91906156d0565b613d0a565b613d0a6002836156d0565b9050613d1681846150b4565b67ffffffffffffffff811115613d2e57613d2e614f3d565b604051908082528060200260200182016040528015613d6157816020015b6060815260200190600190039081613d4c5790505b5095508315613de7576040805160018082528183019092526000916020808301908036833701905050905088600081518110613d9f57613d9f6148f1565b602002602001015181600081518110613dba57613dba6148f1565b6020026020010181815250508087600081518110613dda57613dda6148f1565b6020026020010181905250505b600084613df5576000613df8565b60015b60ff169050805b86821015613f5157606087613e158460016150b4565b1015613ebc5760408051600280825260608201835290916020830190803683370190505090508a8381518110613e4d57613e4d6148f1565b602002602001015181600081518110613e6857613e686148f1565b60209081029190910101528a613e7d8461491d565b93508381518110613e9057613e906148f1565b602002602001015181600181518110613eab57613eab6148f1565b602002602001018181525050613f16565b60408051600180825281830190925290602080830190803683370190505090508a8381518110613eee57613eee6148f1565b602002602001015181600081518110613f0957613f096148f1565b6020026020010181815250505b808983613f228161491d565b945081518110613f3457613f346148f1565b602002602001018190525082613f499061491d565b925050613dff565b5050505050505092915050565b60005b82811161357657613f736002856156bc565b1580613f7f5750836001145b15613faf576000818152602081905260409020829055828114613faa57613fa7826000610d45565b91505b613fcb565b600081815260208190526040902054613fc89083610d45565b91505b613fd66002856156d0565b935080613fe28161491d565b915050613f61565b6000613ff68585610d45565b90506140036002846156d0565b925060015b8281116132da5761401a6002856156bc565b15806140265750836001145b156140565760008181526020819052604090208290558281146140515761404e826000610d45565b91505b614072565b60008181526020819052604090205461406f9083610d45565b91505b61407d6002856156d0565b9350806140898161491d565b915050614008565b6135766001600160a01b038516848484614137565b6040516001600160a01b038316602482015260448101829052610b499084907fa9059cbb00000000000000000000000000000000000000000000000000000000906064015b60408051601f198184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff166001600160e01b031990931692909217909152614188565b6040516001600160a01b03808516602483015283166044820152606481018290526135769085907f23b872dd00000000000000000000000000000000000000000000000000000000906084016140eb565b60006141dd826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166142709092919063ffffffff16565b90508051600014806141fe5750808060200190518101906141fe919061507f565b610b495760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f742073756363656564000000000000000000000000000000000000000000006064820152608401610928565b606061427f8484600085614287565b949350505050565b6060824710156142ff5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610928565b600080866001600160a01b0316858760405161431b91906156e4565b60006040518083038185875af1925050503d8060008114614358576040519150601f19603f3d011682016040523d82523d6000602084013e61435d565b606091505b509150915061216f87838387606083156143d85782516000036143d1576001600160a01b0385163b6143d15760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610928565b508161427f565b61427f83838151156143ed5781518083602001fd5b8060405162461bcd60e51b81526004016109289190615520565b604051806040016040528061441a614427565b8152602001600081525090565b6040518060a001604052806000815260200160006001600160a01b031681526020016144746040518060800160405280600081526020016000815260200160008152602001600081525090565b815260200160008152602001600081525090565b8060408101831015610a5a57600080fd5b6000606082840312156144ab57600080fd5b50919050565b600080600080600061018086880312156144ca57600080fd5b6144d48787614488565b945060c08601878111156144e757600080fd5b6040870194506144f78882614488565b935050614508876101008801614499565b915061016086013567ffffffffffffffff81111561452557600080fd5b86016102a0818903121561453857600080fd5b809150509295509295909350565b60006020828403121561455857600080fd5b81356001600160e01b031981168114610dfe57600080fd5b6001600160a01b0381168114610f7457600080fd5b803561344981614570565b6000602082840312156145a257600080fd5b8135610dfe81614570565b60008083601f8401126145bf57600080fd5b50813567ffffffffffffffff8111156145d757600080fd5b6020830191508360208285010111156145ef57600080fd5b9250929050565b60008060008060006080868803121561460e57600080fd5b853561461981614570565b9450602086013561462981614570565b935060408601359250606086013567ffffffffffffffff81111561464c57600080fd5b614658888289016145ad565b969995985093965092949392505050565b60006020828403121561467b57600080fd5b5035919050565b6000806040838503121561469557600080fd5b8235915060208301356146a781614570565b809150509250929050565b600080600080608085870312156146c857600080fd5b5050823594602084013594506040840135936060013592509050565b600080604083850312156146f757600080fd5b50508035926020909101359150565b60008083601f84011261471857600080fd5b50813567ffffffffffffffff81111561473057600080fd5b6020830191508360208260051b85010111156145ef57600080fd5b6000806000806040858703121561476157600080fd5b843567ffffffffffffffff8082111561477957600080fd5b61478588838901614706565b9096509450602087013591508082111561479e57600080fd5b506147ab87828801614706565b95989497509550505050565b600080602083850312156147ca57600080fd5b823567ffffffffffffffff8111156147e157600080fd5b6147ed858286016145ad565b90969095509350505050565b6000806080838503121561480c57600080fd5b6148168484614499565b946060939093013593505050565b600080600080600060a0868803121561483c57600080fd5b505083359560208501359550604085013594606081013594506080013592509050565b60008235607e1983360301811261487557600080fd5b9190910192915050565b60808101818360005b60048110156148a7578151835260209283019290910190600101614888565b50505092915050565b6000602082840312156148c257600080fd5b5051919050565b60408101818360005b60028110156148a75781518352602092830192909101906001016148d2565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b60006001820161492f5761492f614907565b5060010190565b6001600160801b0382811682821603908082111561350357613503614907565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6001600160a01b0384168152604060208201526000610d3c604083018486614956565b6000816149b1576149b1614907565b506000190190565b803561ffff8116811461344957600080fd5b6000602082840312156149dd57600080fd5b610dfe826149b9565b60a08101818360005b60058110156148a75781518352602092830192909101906001016149ef565b6000808335601e19843603018112614a2557600080fd5b830160208101925035905067ffffffffffffffff811115614a4557600080fd5b8060051b36038213156145ef57600080fd5b8183526000602080850194508260005b85811015614a95578135614a7a81614570565b6001600160a01b031687529582019590820190600101614a67565b509495945050505050565b81835260007f07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff831115614ad257600080fd5b8260051b80836020870137939093016020019392505050565b8183526000602080850194508260005b85811015614a9557813587529582019590820190600101614afb565b81835260006020808501808196508560051b810191508460005b87811015614b67578284038952614b488288614a0e565b614b53868284614aa0565b9a87019a9550505090840190600101614b31565b5091979650505050505050565b6000808335601e19843603018112614b8b57600080fd5b830160208101925035905067ffffffffffffffff811115614bab57600080fd5b8036038213156145ef57600080fd5b81835260006020808501808196506005915085821b8101856000805b89811015614c4e578484038b52614bed838a614a0e565b80865288860181891b87018a0183865b84811015614c3757898303601f19018452614c188287614b74565b614c23858284614956565b958f019594505050908c0190600101614bfd565b50509d8a019d965050509287019250600101614bd6565b50919998505050505050505050565b60008235607e19833603018112614c7357600080fd5b90910192915050565b60008135614c8981614570565b6001600160a01b039081168452602083013590614ca582614570565b166020840152614cb86040830183614b74565b60806040860152614ccd608086018284614956565b915050614cdd6060840184614b74565b85830360608701526113b4838284614956565b60006102a082358452614d066020840184614a0e565b826020870152614d198387018284614a57565b92505050614d2a6040840184614a0e565b8583036040870152614d3d838284614aa0565b92505050614d4e6060840184614a0e565b8583036060870152614d61838284614aeb565b92505050614d726080840184614a0e565b8583036080870152614d85838284614b17565b92505050614d9660a0840184614a0e565b85830360a0870152614da9838284614b17565b92505050614dba60c0840184614a0e565b85830360c0870152614dcd838284614bba565b92505050614dde60e0840184614a0e565b85830360e0870152614df1838284614aa0565b92505050610100808401358186015250610120614e33818601828601803582526020810135602083015260408101356040830152606081013560608301525050565b506101a083810135908501526101c080840135908501526101e0614e588185016149b9565b61ffff1690850152610200614e6e848201614585565b6001600160a01b031690850152610220614e89848201614585565b6001600160a01b0316908501526102408381013590850152610260614eb081850185614b74565b86840383880152614ec2848284614956565b9350505050610280614ed681850185614c5d565b858303828701526113b48382614c7c565b608081526000614efa6080830185614cf0565b905061ffff80614f09856149b9565b16602084015280614f1c602086016149b9565b16604084015280614f2f604086016149b9565b166060840152509392505050565b634e487b7160e01b600052604160045260246000fd5b60405160a0810167ffffffffffffffff81118282101715614f7657614f76614f3d565b60405290565b6040516080810167ffffffffffffffff81118282101715614f7657614f76614f3d565b604051601f8201601f1916810167ffffffffffffffff81118282101715614fc857614fc8614f3d565b604052919050565b600067ffffffffffffffff821115614fea57614fea614f3d565b5060051b60200190565b6000602080838503121561500757600080fd5b825167ffffffffffffffff81111561501e57600080fd5b8301601f8101851361502f57600080fd5b805161504261503d82614fd0565b614f9f565b81815260059190911b8201830190838101908783111561506157600080fd5b928401925b8284101561216f57835182529284019290840190615066565b60006020828403121561509157600080fd5b81518015158114610dfe57600080fd5b81810381811115610a5a57610a5a614907565b80820180821115610a5a57610a5a614907565b6000808335601e198436030181126150de57600080fd5b83018035915067ffffffffffffffff8211156150f957600080fd5b6020019150368190038213156145ef57600080fd5b6040815260006151216040830186614cf0565b82810360208401526113b4818587614956565b6000808335601e1984360301811261514b57600080fd5b83018035915067ffffffffffffffff82111561516657600080fd5b6020019150600581901b36038213156145ef57600080fd5b808201828112600083128015821682158216171561350157613501614907565b818103600083128015838313168383128216171561350357613503614907565b80820260008212600160ff1b841416156151da576151da614907565b8181058314821517610a5a57610a5a614907565b600067ffffffffffffffff80831681810361520b5761520b614907565b6001019392505050565b634e487b7160e01b600052602160045260246000fd5b60006101408083016040808a86378085018960005b600281101561525d57838284379183019190830190600101615240565b505050808860c08701375061010084019190915284519081905261016083019060209081870160005b828110156152a257815185529383019390830190600101615286565b50505050610120929092019290925295945050505050565b6000600160ff1b82036152cf576152cf614907565b5060000390565b602081526000610dfe6020830184614cf0565b600060208083850312156152fc57600080fd5b825167ffffffffffffffff81111561531357600080fd5b8301601f8101851361532457600080fd5b805161533261503d82614fd0565b81815260089190911b8201830190838101908783111561535157600080fd5b928401925b8284101561216f578388036101008112156153715760008081fd5b615379614f53565b855181528686015161538a81614570565b8188015260406080603f1984018113156153a45760008081fd5b6153ac614f7c565b8883015181526060808a01518b830152828a01518483015260a08a0151818301529284015260c08801519183019190915260e0870151908201528352506101009093019290840190615356565b600061ffff80831681810361520b5761520b614907565b8481528360208201526060604082015260006113b4606083018486614956565b60005b8381101561544b578181015183820152602001615433565b50506000910152565b6000815180845261546c816020860160208601615430565b601f01601f19169290920160200192915050565b838152826020820152606060408201526000610d3c6060830184615454565b7f416363657373436f6e74726f6c3a206163636f756e74200000000000000000008152600083516154d7816017850160208801615430565b7f206973206d697373696e6720726f6c65200000000000000000000000000000006017918401918201528351615514816028840160208801615430565b01602801949350505050565b602081526000610dfe6020830184615454565b60006020828403121561554557600080fd5b8151610dfe81614570565b6001600160801b0381811683821601908082111561350357613503614907565b600181815b808511156155ab57816000190482111561559157615591614907565b8085161561559e57918102915b93841c9390800290615575565b509250929050565b6000826155c257506001610a5a565b816155cf57506000610a5a565b81600181146155e557600281146155ef5761560b565b6001915050610a5a565b60ff84111561560057615600614907565b50506001821b610a5a565b5060208310610133831016604e8410600b841016171561562e575081810a610a5a565b6156388383615570565b806000190482111561564c5761564c614907565b029392505050565b6000610dfe6001600160801b038416836155b3565b634e487b7160e01b600052601260045260246000fd5b60006001600160801b038084168061569957615699615669565b92169190910692915050565b8082028115828204841417610a5a57610a5a614907565b6000826156cb576156cb615669565b500690565b6000826156df576156df615669565b500490565b6000825161487581846020870161543056fea264697066735822122068962a878d3cd21b4be9fe8751a72f8385768ea6a148bd95850518ed06cf382e64736f6c63430008110033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000000000000000000000000000000000000000000019000000000000000000000000cb9e6bfe2c27b90f39a04a1a3ffb6e97c2faa02d000000000000000000000000e90481f96af203bf4cff149edeaa656a894a4c84000000000000000000000000d5235593bffa74442c552dff384fb8c9d6b7971e0000000000000000000000000036e884cab4f427193839788edebb4b92b9a0690000000000000000000000008f899971c3e0b91820b983cfd57bc551291d2ba200000000000000000000000053a1eeb0c182144b27ca0a2010939da33ebc207d
-----Decoded View---------------
Arg [0] : constructorArgs (tuple): System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput]
Arg [1] : _hinkalHelper (address): 0x0036E884Cab4F427193839788EDEBB4B92B9a069
Arg [2] : _accessToken (address): 0x8f899971c3E0B91820B983cFd57BC551291D2bA2
Arg [3] : _hinkalHelperManager (address): 0x53a1EEB0c182144B27Ca0a2010939DA33ebc207d
-----Encoded View---------------
7 Constructor Arguments found :
Arg [0] : 0000000000000000000000000000000000000000000000000000000000000019
Arg [1] : 000000000000000000000000cb9e6bfe2c27b90f39a04a1a3ffb6e97c2faa02d
Arg [2] : 000000000000000000000000e90481f96af203bf4cff149edeaa656a894a4c84
Arg [3] : 000000000000000000000000d5235593bffa74442c552dff384fb8c9d6b7971e
Arg [4] : 0000000000000000000000000036e884cab4f427193839788edebb4b92b9a069
Arg [5] : 0000000000000000000000008f899971c3e0b91820b983cfd57bc551291d2ba2
Arg [6] : 00000000000000000000000053a1eeb0c182144b27ca0a2010939da33ebc207d
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|---|---|---|---|---|
ARB | 57.70% | $5,968.14 | 10.2 | $60,875.03 | |
ARB | 10.55% | $0.329538 | 33,774.1069 | $11,129.85 | |
ARB | 4.19% | $1 | 4,416.4563 | $4,416.46 | |
ARB | 3.44% | $1,795.01 | 2.0246 | $3,634.17 | |
ARB | 2.57% | $0.999895 | 2,713.2677 | $2,712.98 | |
ARB | 1.02% | $14.86 | 72.6532 | $1,079.63 | |
ARB | 0.19% | $0.999895 | 202.5044 | $202.48 | |
ARB | 0.13% | $92,918 | 0.0014618 | $135.83 | |
ARB | 0.13% | $93,005 | 0.00145677 | $135.49 | |
ARB | 0.03% | $1,796.42 | 0.0184 | $33.02 | |
ARB | 0.03% | $385.32 | 0.074 | $28.51 | |
ARB | 0.01% | $0.697289 | 20.2534 | $14.12 | |
ARB | <0.01% | $0.999484 | 8.6711 | $8.67 | |
ARB | <0.01% | $0.206506 | 12.3874 | $2.56 | |
ARB | <0.01% | $14.36 | 0.1704 | $2.45 | |
ARB | <0.01% | $0.999662 | 0.2644 | $0.2643 | |
BASE | 6.69% | $0.999896 | 7,058.4868 | $7,057.75 | |
BASE | 4.26% | $0.697217 | 6,445.784 | $4,494.11 | |
BASE | 1.75% | $1,793.99 | 1.0274 | $1,843.2 | |
BASE | 0.62% | $0.999507 | 655.8185 | $655.5 | |
BASE | 0.25% | $1,960.22 | 0.1352 | $264.97 | |
BASE | 0.05% | $0.999859 | 47.8621 | $47.86 | |
BASE | 0.01% | $1,918.14 | 0.00721835 | $13.85 | |
BASE | <0.01% | $1,878.96 | 0.00526133 | $9.89 | |
BASE | <0.01% | $1,796.43 | 0.004708 | $8.46 | |
BASE | <0.01% | $2,152.62 | 0.00230485 | $4.96 | |
BASE | <0.01% | $0.999975 | 3.6361 | $3.64 | |
BASE | <0.01% | $0.47443 | 3.6288 | $1.72 | |
BASE | <0.01% | $0.000002 | 740,000 | $1.19 | |
BASE | <0.01% | $2.71 | 0.1524 | $0.4129 | |
BASE | <0.01% | $0.999662 | 0.2782 | $0.2781 | |
BASE | <0.01% | $0.003755 | 29.9989 | $0.1126 | |
OP | 2.29% | $1,794.66 | 1.3454 | $2,414.5 | |
OP | 1.09% | $1 | 1,148.3642 | $1,148.36 | |
OP | 0.82% | $0.999896 | 861.6904 | $861.6 | |
OP | 0.23% | $0.751838 | 320.3723 | $240.87 | |
OP | 0.14% | $0.049181 | 3,042.2745 | $149.62 | |
OP | 0.03% | $0.999896 | 27.9965 | $27.99 | |
OP | 0.03% | $2,152.62 | 0.0128 | $27.55 | |
OP | <0.01% | $0.999988 | 5.6476 | $5.65 | |
OP | <0.01% | $162.45 | 0.0119 | $1.93 | |
OP | <0.01% | $0.202241 | 8.9378 | $1.81 | |
OP | <0.01% | $17,685.6 | 0.00004432 | $0.7838 | |
OP | <0.01% | $0.697217 | 1.1042 | $0.7698 | |
OP | <0.01% | $92,924 | 0.00000544 | $0.5055 | |
OP | <0.01% | $0.999996 | 0.2742 | $0.2742 | |
OP | <0.01% | $1,796.43 | 0.00011577 | $0.2079 | |
AVAX | 1.51% | $0.999881 | 1,594.7101 | $1,594.52 | |
AVAX | 0.13% | $92,884 | 0.001515 | $140.72 | |
AVAX | 0.06% | $22.52 | 2.7038 | $60.88 | |
AVAX | <0.01% | $1 | 6.8093 | $6.81 | |
AVAX | <0.01% | $1 | 1.3466 | $1.35 | |
AVAX | <0.01% | $1 | 0.9467 | $0.9469 | |
AVAX | <0.01% | $0.999881 | 0.5961 | $0.596 | |
AVAX | <0.01% | $162.45 | 0.00135321 | $0.2198 | |
ETH | <0.01% | $1 | 1 | $1 |
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.