Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 1 from a total of 1 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
Value | ||||
---|---|---|---|---|---|---|---|---|---|
0x60c06040 | 18323496 | 271 days ago | IN | Create: ERC20Tornado | 0 ETH | 0.01811115 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
ERC20Tornado
Compiler Version
v0.8.19+commit.7dd6d404
Contract Source Code (Solidity Standard Json-Input format)
// https://tornado.cash /* * d888888P dP a88888b. dP * 88 88 d8' `88 88 * 88 .d8888b. 88d888b. 88d888b. .d8888b. .d888b88 .d8888b. 88 .d8888b. .d8888b. 88d888b. * 88 88' `88 88' `88 88' `88 88' `88 88' `88 88' `88 88 88' `88 Y8ooooo. 88' `88 * 88 88. .88 88 88 88 88. .88 88. .88 88. .88 dP Y8. .88 88. .88 88 88 88 * dP `88888P' dP dP dP `88888P8 `88888P8 `88888P' 88 Y88888P' `88888P8 `88888P' dP dP * ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo */ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./Tornado.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; contract ERC20Tornado is Tornado { using SafeERC20 for IERC20; IERC20 public token; constructor( IVerifier _verifier, IHasher _hasher, uint256 _denomination, uint32 _merkleTreeHeight, IERC20 _token ) Tornado(_verifier, _hasher, _denomination, _merkleTreeHeight) { token = _token; } function _processDeposit() internal override { require( msg.value == 0, "ETH value is supposed to be 0 for ERC20 instance" ); token.safeTransferFrom(msg.sender, address(this), denomination); } function _processWithdraw( address payable _recipient, address payable _relayer, uint256 _fee, uint256 _refund ) internal override { require( msg.value == _refund, "Incorrect refund amount received by the contract" ); token.safeTransfer(_recipient, denomination - _fee); if (_fee > 0) { token.safeTransfer(_relayer, _fee); } if (_refund > 0) { (bool success, ) = _recipient.call{value: _refund}(""); if (!success) { // let's return _refund back to the relayer _relayer.transfer(_refund); } } } }
// 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.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.0) (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. */ 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]. */ 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/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. Compatible with tokens that require the approval to be set to * 0 before setting it to a non-zero value. */ 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) (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 pragma solidity ^0.8.0; interface IHasher { function poseidon(bytes32[2] calldata inputs) external pure returns (bytes32); function poseidon(bytes32[3] calldata inputs) external pure returns (bytes32); function MiMCSponge( uint256 in_xL, uint256 in_xR ) external pure returns (uint256 xL, uint256 xR); }
// https://tornado.cash /* * d888888P dP a88888b. dP * 88 88 d8' `88 88 * 88 .d8888b. 88d888b. 88d888b. .d8888b. .d888b88 .d8888b. 88 .d8888b. .d8888b. 88d888b. * 88 88' `88 88' `88 88' `88 88' `88 88' `88 88' `88 88 88' `88 Y8ooooo. 88' `88 * 88 88. .88 88 88 88 88. .88 88. .88 88. .88 dP Y8. .88 88. .88 88 88 88 * dP `88888P' dP dP dP `88888P8 `88888P8 `88888P' 88 Y88888P' `88888P8 `88888P' dP dP * ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo */ import "../interfaces/IHasher.sol"; // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; contract MerkleTreeWithHistory { uint256 public constant FIELD_SIZE = 21888242871839275222246405745257275088548364400416034343698204186575808495617; uint256 public constant ZERO_VALUE = 21663839004416932945382355908790599225266501822907911457504978515578255421292; // = keccak256("tornado") % FIELD_SIZE IHasher public immutable hasher; uint32 public levels; // the following variables are made public for easier testing and debugging and // are not supposed to be accessed in regular code // filledSubtrees and roots could be bytes32[size], but using mappings makes it cheaper because // it removes index range check on every interaction mapping(uint256 => bytes32) public filledSubtrees; mapping(uint256 => bytes32) public roots; uint32 public constant ROOT_HISTORY_SIZE = 30; uint32 public currentRootIndex = 0; uint32 public nextIndex = 0; constructor(uint32 _levels, IHasher _hasher) { require(_levels > 0, "_levels should be greater than zero"); require(_levels < 32, "_levels should be less than 32"); levels = _levels; hasher = _hasher; for (uint32 i = 0; i < _levels; i++) { filledSubtrees[i] = zeros(i); } roots[0] = zeros(_levels - 1); } /** @dev Hash 2 tree leaves, returns MiMC(_left, _right) */ function hashLeftRight( IHasher _hasher, bytes32 _left, bytes32 _right ) public pure returns (bytes32) { require( uint256(_left) < FIELD_SIZE, "_left should be inside the field" ); require( uint256(_right) < FIELD_SIZE, "_right should be inside the field" ); uint256 R = uint256(_left); uint256 C = 0; (R, C) = _hasher.MiMCSponge(R, C); R = addmod(R, uint256(_right), FIELD_SIZE); (R, C) = _hasher.MiMCSponge(R, C); return bytes32(R); } function _insert(bytes32 _leaf) internal returns (uint32 index) { uint32 _nextIndex = nextIndex; require( _nextIndex != uint32(2) ** levels, "Merkle tree is full. No more leaves can be added" ); uint32 currentIndex = _nextIndex; bytes32 currentLevelHash = _leaf; bytes32 left; bytes32 right; for (uint32 i = 0; i < levels; i++) { if (currentIndex % 2 == 0) { left = currentLevelHash; right = zeros(i); filledSubtrees[i] = currentLevelHash; } else { left = filledSubtrees[i]; right = currentLevelHash; } currentLevelHash = hashLeftRight(hasher, left, right); currentIndex /= 2; } uint32 newRootIndex = (currentRootIndex + 1) % ROOT_HISTORY_SIZE; currentRootIndex = newRootIndex; roots[newRootIndex] = currentLevelHash; nextIndex = _nextIndex + 1; return _nextIndex; } /** @dev Whether the root is present in the root history */ function isKnownRoot(bytes32 _root) public view returns (bool) { if (_root == 0) { return false; } uint32 _currentRootIndex = currentRootIndex; uint32 i = _currentRootIndex; do { if (_root == roots[i]) { return true; } if (i == 0) { i = ROOT_HISTORY_SIZE; } i--; } while (i != _currentRootIndex); return false; } /** @dev Returns the last root */ function getLastRoot() public view returns (bytes32) { return roots[currentRootIndex]; } /// @dev provides Zero (Empty) elements for a MiMC MerkleTree. Up to 32 levels function zeros(uint256 i) public pure returns (bytes32) { if (i == 0) return bytes32( 0x2fe54c60d3acabf3343a35b6eba15db4821b340f76e741e2249685ed4899af6c ); else if (i == 1) return bytes32( 0x256a6135777eee2fd26f54b8b7037a25439d5235caee224154186d2b8a52e31d ); else if (i == 2) return bytes32( 0x1151949895e82ab19924de92c40a3d6f7bcb60d92b00504b8199613683f0c200 ); else if (i == 3) return bytes32( 0x20121ee811489ff8d61f09fb89e313f14959a0f28bb428a20dba6b0b068b3bdb ); else if (i == 4) return bytes32( 0x0a89ca6ffa14cc462cfedb842c30ed221a50a3d6bf022a6a57dc82ab24c157c9 ); else if (i == 5) return bytes32( 0x24ca05c2b5cd42e890d6be94c68d0689f4f21c9cec9c0f13fe41d566dfb54959 ); else if (i == 6) return bytes32( 0x1ccb97c932565a92c60156bdba2d08f3bf1377464e025cee765679e604a7315c ); else if (i == 7) return bytes32( 0x19156fbd7d1a8bf5cba8909367de1b624534ebab4f0f79e003bccdd1b182bdb4 ); else if (i == 8) return bytes32( 0x261af8c1f0912e465744641409f622d466c3920ac6e5ff37e36604cb11dfff80 ); else if (i == 9) return bytes32( 0x0058459724ff6ca5a1652fcbc3e82b93895cf08e975b19beab3f54c217d1c007 ); else if (i == 10) return bytes32( 0x1f04ef20dee48d39984d8eabe768a70eafa6310ad20849d4573c3c40c2ad1e30 ); else if (i == 11) return bytes32( 0x1bea3dec5dab51567ce7e200a30f7ba6d4276aeaa53e2686f962a46c66d511e5 ); else if (i == 12) return bytes32( 0x0ee0f941e2da4b9e31c3ca97a40d8fa9ce68d97c084177071b3cb46cd3372f0f ); else if (i == 13) return bytes32( 0x1ca9503e8935884501bbaf20be14eb4c46b89772c97b96e3b2ebf3a36a948bbd ); else if (i == 14) return bytes32( 0x133a80e30697cd55d8f7d4b0965b7be24057ba5dc3da898ee2187232446cb108 ); else if (i == 15) return bytes32( 0x13e6d8fc88839ed76e182c2a779af5b2c0da9dd18c90427a644f7e148a6253b6 ); else if (i == 16) return bytes32( 0x1eb16b057a477f4bc8f572ea6bee39561098f78f15bfb3699dcbb7bd8db61854 ); else if (i == 17) return bytes32( 0x0da2cb16a1ceaabf1c16b838f7a9e3f2a3a3088d9e0a6debaa748114620696ea ); else if (i == 18) return bytes32( 0x24a3b3d822420b14b5d8cb6c28a574f01e98ea9e940551d2ebd75cee12649f9d ); else if (i == 19) return bytes32( 0x198622acbd783d1b0d9064105b1fc8e4d8889de95c4c519b3f635809fe6afc05 ); else if (i == 20) return bytes32( 0x29d7ed391256ccc3ea596c86e933b89ff339d25ea8ddced975ae2fe30b5296d4 ); else if (i == 21) return bytes32( 0x19be59f2f0413ce78c0c3703a3a5451b1d7f39629fa33abd11548a76065b2967 ); else if (i == 22) return bytes32( 0x1ff3f61797e538b70e619310d33f2a063e7eb59104e112e95738da1254dc3453 ); else if (i == 23) return bytes32( 0x10c16ae9959cf8358980d9dd9616e48228737310a10e2b6b731c1a548f036c48 ); else if (i == 24) return bytes32( 0x0ba433a63174a90ac20992e75e3095496812b652685b5e1a2eae0b1bf4e8fcd1 ); else if (i == 25) return bytes32( 0x019ddb9df2bc98d987d0dfeca9d2b643deafab8f7036562e627c3667266a044c ); else if (i == 26) return bytes32( 0x2d3c88b23175c5a5565db928414c66d1912b11acf974b2e644caaac04739ce99 ); else if (i == 27) return bytes32( 0x2eab55f6ae4e66e32c5189eed5c470840863445760f5ed7e7b69b2a62600f354 ); else if (i == 28) return bytes32( 0x002df37a2642621802383cf952bf4dd1f32e05433beeb1fd41031fb7eace979d ); else if (i == 29) return bytes32( 0x104aeb41435db66c3e62feccc1d6f5d98d0a0ed75d1374db457cf462e3a1f427 ); else if (i == 30) return bytes32( 0x1f3c6fd858e9a7d4b0d1f38e256a09d81d5a5e3c963987e2d4b814cfab7c6ebb ); else if (i == 31) return bytes32( 0x2c7a07d20dff79d01fecedc1134284a8d08436606c93693b67e333f671bf69cc ); else revert("Index out of bounds"); } }
// https://tornado.cash /* * d888888P dP a88888b. dP * 88 88 d8' `88 88 * 88 .d8888b. 88d888b. 88d888b. .d8888b. .d888b88 .d8888b. 88 .d8888b. .d8888b. 88d888b. * 88 88' `88 88' `88 88' `88 88' `88 88' `88 88' `88 88 88' `88 Y8ooooo. 88' `88 * 88 88. .88 88 88 88 88. .88 88. .88 88. .88 dP Y8. .88 88. .88 88 88 88 * dP `88888P' dP dP dP `88888P8 `88888P8 `88888P' 88 Y88888P' `88888P8 `88888P' dP dP * ooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo */ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; import "./MerkleTreeWithHistory.sol"; import "@openzeppelin/contracts/security/ReentrancyGuard.sol"; interface IVerifier { function verifyProof( bytes memory _proof, uint256[6] memory _input ) external returns (bool); } abstract contract Tornado is MerkleTreeWithHistory, ReentrancyGuard { IVerifier public immutable verifier; uint256 public denomination; mapping(bytes32 => bool) public nullifierHashes; // we store all commitments just to prevent accidental deposits with the same commitment mapping(bytes32 => bool) public commitments; event Deposit( bytes32 indexed commitment, uint32 leafIndex, uint256 timestamp ); event Withdrawal( address to, bytes32 nullifierHash, address indexed relayer, uint256 fee ); /** @dev The constructor @param _verifier the address of SNARK verifier for this contract @param _hasher the address of MiMC hash contract @param _denomination transfer amount for each deposit @param _merkleTreeHeight the height of deposits' Merkle Tree */ constructor( IVerifier _verifier, IHasher _hasher, uint256 _denomination, uint32 _merkleTreeHeight ) MerkleTreeWithHistory(_merkleTreeHeight, _hasher) { require(_denomination > 0, "denomination should be greater than 0"); verifier = _verifier; denomination = _denomination; } /** @dev Deposit funds into the contract. The caller must send (for ETH) or approve (for ERC20) value equal to or `denomination` of this instance. @param _commitment the note commitment, which is PedersenHash(nullifier + secret) */ function deposit(bytes32 _commitment) external payable nonReentrant { require(!commitments[_commitment], "The commitment has been submitted"); uint32 insertedIndex = _insert(_commitment); commitments[_commitment] = true; _processDeposit(); emit Deposit(_commitment, insertedIndex, block.timestamp); } /** @dev this function is defined in a child contract */ function _processDeposit() internal virtual; /** @dev Withdraw a deposit from the contract. `proof` is a zkSNARK proof data, and input is an array of circuit public inputs `input` array consists of: - merkle root of all deposits in the contract - hash of unique deposit nullifier to prevent double spends - the recipient of funds - optional fee that goes to the transaction sender (usually a relay) */ function withdraw( bytes calldata _proof, bytes32 _root, bytes32 _nullifierHash, address payable _recipient, address payable _relayer, uint256 _fee, uint256 _refund ) external payable nonReentrant { require(_fee <= denomination, "Fee exceeds transfer value"); require( !nullifierHashes[_nullifierHash], "The note has been already spent" ); require(isKnownRoot(_root), "Cannot find your merkle root"); // Make sure to use a recent one require(verifier.verifyProof(_proof, [uint256(_root), uint256(_nullifierHash), uint256(uint160(address(_recipient))), uint256(uint160(address(_relayer))), _fee, _refund]), "Invalid withdraw proof"); nullifierHashes[_nullifierHash] = true; _processWithdraw(_recipient, _relayer, _fee, _refund); emit Withdrawal(_recipient, _nullifierHash, _relayer, _fee); } /** @dev this function is defined in a child contract */ function _processWithdraw( address payable _recipient, address payable _relayer, uint256 _fee, uint256 _refund ) internal virtual; /** @dev whether a note is already spent */ function isSpent(bytes32 _nullifierHash) public view returns (bool) { return nullifierHashes[_nullifierHash]; } /** @dev whether an array of notes is already spent */ function isSpentArray( bytes32[] calldata _nullifierHashes ) external view returns (bool[] memory spent) { spent = new bool[](_nullifierHashes.length); for (uint256 i = 0; i < _nullifierHashes.length; i++) { if (isSpent(_nullifierHashes[i])) { spent[i] = true; } } } }
{ "evmVersion": "paris", "libraries": {}, "metadata": { "bytecodeHash": "ipfs", "useLiteralContent": true }, "optimizer": { "enabled": true, "runs": 200 }, "remappings": [], "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"contract IVerifier","name":"_verifier","type":"address"},{"internalType":"contract IHasher","name":"_hasher","type":"address"},{"internalType":"uint256","name":"_denomination","type":"uint256"},{"internalType":"uint32","name":"_merkleTreeHeight","type":"uint32"},{"internalType":"contract IERC20","name":"_token","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"commitment","type":"bytes32"},{"indexed":false,"internalType":"uint32","name":"leafIndex","type":"uint32"},{"indexed":false,"internalType":"uint256","name":"timestamp","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"bytes32","name":"nullifierHash","type":"bytes32"},{"indexed":true,"internalType":"address","name":"relayer","type":"address"},{"indexed":false,"internalType":"uint256","name":"fee","type":"uint256"}],"name":"Withdrawal","type":"event"},{"inputs":[],"name":"FIELD_SIZE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ROOT_HISTORY_SIZE","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ZERO_VALUE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"commitments","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentRootIndex","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"denomination","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_commitment","type":"bytes32"}],"name":"deposit","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"filledSubtrees","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getLastRoot","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IHasher","name":"_hasher","type":"address"},{"internalType":"bytes32","name":"_left","type":"bytes32"},{"internalType":"bytes32","name":"_right","type":"bytes32"}],"name":"hashLeftRight","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"hasher","outputs":[{"internalType":"contract IHasher","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_root","type":"bytes32"}],"name":"isKnownRoot","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_nullifierHash","type":"bytes32"}],"name":"isSpent","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"_nullifierHashes","type":"bytes32[]"}],"name":"isSpentArray","outputs":[{"internalType":"bool[]","name":"spent","type":"bool[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"levels","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"nextIndex","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"nullifierHashes","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"roots","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"token","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"verifier","outputs":[{"internalType":"contract IVerifier","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"_proof","type":"bytes"},{"internalType":"bytes32","name":"_root","type":"bytes32"},{"internalType":"bytes32","name":"_nullifierHash","type":"bytes32"},{"internalType":"address payable","name":"_recipient","type":"address"},{"internalType":"address payable","name":"_relayer","type":"address"},{"internalType":"uint256","name":"_fee","type":"uint256"},{"internalType":"uint256","name":"_refund","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"i","type":"uint256"}],"name":"zeros","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"}]
Contract Creation Code
60c0604052600380546001600160401b03191690553480156200002157600080fd5b5060405162002822380380620028228339810160408190526200004491620008c3565b84848484808360008263ffffffff1611620000b25760405162461bcd60e51b815260206004820152602360248201527f5f6c6576656c732073686f756c642062652067726561746572207468616e207a60448201526265726f60e81b60648201526084015b60405180910390fd5b60208263ffffffff16106200010a5760405162461bcd60e51b815260206004820152601e60248201527f5f6c6576656c732073686f756c64206265206c657373207468616e20333200006044820152606401620000a9565b6000805463ffffffff191663ffffffff84161781556001600160a01b0382166080525b8263ffffffff168163ffffffff1610156200017e576200015363ffffffff821662000261565b63ffffffff821660009081526001602052604090205580620001758162000955565b9150506200012d565b506200019c620001906001846200097b565b63ffffffff1662000261565b6000805260026020527fac33ff75c19e70fe83507db0d683fd3465c996598dc972688b7ace676c89077b5550506001600455816200022b5760405162461bcd60e51b815260206004820152602560248201527f64656e6f6d696e6174696f6e2073686f756c6420626520677265617465722074604482015264068616e20360dc1b6064820152608401620000a9565b506001600160a01b0392831660a05260055550600880546001600160a01b0319169290911691909117905550620009a292505050565b6000816000036200029357507f2fe54c60d3acabf3343a35b6eba15db4821b340f76e741e2249685ed4899af6c919050565b81600103620002c357507f256a6135777eee2fd26f54b8b7037a25439d5235caee224154186d2b8a52e31d919050565b81600203620002f357507f1151949895e82ab19924de92c40a3d6f7bcb60d92b00504b8199613683f0c200919050565b816003036200032357507f20121ee811489ff8d61f09fb89e313f14959a0f28bb428a20dba6b0b068b3bdb919050565b816004036200035357507f0a89ca6ffa14cc462cfedb842c30ed221a50a3d6bf022a6a57dc82ab24c157c9919050565b816005036200038357507f24ca05c2b5cd42e890d6be94c68d0689f4f21c9cec9c0f13fe41d566dfb54959919050565b81600603620003b357507f1ccb97c932565a92c60156bdba2d08f3bf1377464e025cee765679e604a7315c919050565b81600703620003e357507f19156fbd7d1a8bf5cba8909367de1b624534ebab4f0f79e003bccdd1b182bdb4919050565b816008036200041357507f261af8c1f0912e465744641409f622d466c3920ac6e5ff37e36604cb11dfff80919050565b816009036200044257507e58459724ff6ca5a1652fcbc3e82b93895cf08e975b19beab3f54c217d1c007919050565b81600a036200047257507f1f04ef20dee48d39984d8eabe768a70eafa6310ad20849d4573c3c40c2ad1e30919050565b81600b03620004a257507f1bea3dec5dab51567ce7e200a30f7ba6d4276aeaa53e2686f962a46c66d511e5919050565b81600c03620004d257507f0ee0f941e2da4b9e31c3ca97a40d8fa9ce68d97c084177071b3cb46cd3372f0f919050565b81600d036200050257507f1ca9503e8935884501bbaf20be14eb4c46b89772c97b96e3b2ebf3a36a948bbd919050565b81600e036200053257507f133a80e30697cd55d8f7d4b0965b7be24057ba5dc3da898ee2187232446cb108919050565b81600f036200056257507f13e6d8fc88839ed76e182c2a779af5b2c0da9dd18c90427a644f7e148a6253b6919050565b816010036200059257507f1eb16b057a477f4bc8f572ea6bee39561098f78f15bfb3699dcbb7bd8db61854919050565b81601103620005c257507f0da2cb16a1ceaabf1c16b838f7a9e3f2a3a3088d9e0a6debaa748114620696ea919050565b81601203620005f257507f24a3b3d822420b14b5d8cb6c28a574f01e98ea9e940551d2ebd75cee12649f9d919050565b816013036200062257507f198622acbd783d1b0d9064105b1fc8e4d8889de95c4c519b3f635809fe6afc05919050565b816014036200065257507f29d7ed391256ccc3ea596c86e933b89ff339d25ea8ddced975ae2fe30b5296d4919050565b816015036200068257507f19be59f2f0413ce78c0c3703a3a5451b1d7f39629fa33abd11548a76065b2967919050565b81601603620006b257507f1ff3f61797e538b70e619310d33f2a063e7eb59104e112e95738da1254dc3453919050565b81601703620006e257507f10c16ae9959cf8358980d9dd9616e48228737310a10e2b6b731c1a548f036c48919050565b816018036200071257507f0ba433a63174a90ac20992e75e3095496812b652685b5e1a2eae0b1bf4e8fcd1919050565b816019036200074257507f019ddb9df2bc98d987d0dfeca9d2b643deafab8f7036562e627c3667266a044c919050565b81601a036200077257507f2d3c88b23175c5a5565db928414c66d1912b11acf974b2e644caaac04739ce99919050565b81601b03620007a257507f2eab55f6ae4e66e32c5189eed5c470840863445760f5ed7e7b69b2a62600f354919050565b81601c03620007d157507e2df37a2642621802383cf952bf4dd1f32e05433beeb1fd41031fb7eace979d919050565b81601d036200080157507f104aeb41435db66c3e62feccc1d6f5d98d0a0ed75d1374db457cf462e3a1f427919050565b81601e036200083157507f1f3c6fd858e9a7d4b0d1f38e256a09d81d5a5e3c963987e2d4b814cfab7c6ebb919050565b81601f036200086157507f2c7a07d20dff79d01fecedc1134284a8d08436606c93693b67e333f671bf69cc919050565b60405162461bcd60e51b815260206004820152601360248201527f496e646578206f7574206f6620626f756e6473000000000000000000000000006044820152606401620000a9565b6001600160a01b0381168114620008c057600080fd5b50565b600080600080600060a08688031215620008dc57600080fd5b8551620008e981620008aa565b6020870151909550620008fc81620008aa565b60408701516060880151919550935063ffffffff811681146200091e57600080fd5b60808701519092506200093181620008aa565b809150509295509295909350565b634e487b7160e01b600052601160045260246000fd5b600063ffffffff8083168181036200097157620009716200093f565b6001019392505050565b63ffffffff8281168282160390808211156200099b576200099b6200093f565b5092915050565b60805160a051611e4c620009d6600039600081816101a6015261061501526000818161042701526114410152611e4c6000f3fe6080604052600436106101355760003560e01c8063b214faa5116100ab578063e82955881161006f578063e8295588146103c1578063ec732959146103e1578063ed33639f14610415578063f178e47c14610449578063fc0c546a14610476578063fc7e9c6f1461049657600080fd5b8063b214faa514610312578063ba70f75714610325578063c2b40ae41461034f578063cd87a3b41461037c578063e5285dcc1461039157600080fd5b80636d9833e3116100fd5780636d9833e314610242578063839df945146102625780638bca6d16146102925780638ea3099e146102a857806390eeb02b146102c85780639fa12d0b146102e557600080fd5b806317cc915c1461013a57806321a0adb61461017f5780632b7ac3f314610194578063414a37ba146101e05780634ecf518b14610210575b600080fd5b34801561014657600080fd5b5061016a6101553660046118a3565b60066020526000908152604090205460ff1681565b60405190151581526020015b60405180910390f35b61019261018d3660046118dc565b6104bb565b005b3480156101a057600080fd5b506101c87f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610176565b3480156101ec57600080fd5b50610202600080516020611df783398151915281565b604051908152602001610176565b34801561021c57600080fd5b5060005461022d9063ffffffff1681565b60405163ffffffff9091168152602001610176565b34801561024e57600080fd5b5061016a61025d3660046118a3565b61075e565b34801561026e57600080fd5b5061016a61027d3660046118a3565b60076020526000908152604090205460ff1681565b34801561029e57600080fd5b5061020260055481565b3480156102b457600080fd5b506102026102c3366004611992565b6107dc565b3480156102d457600080fd5b5060035461022d9063ffffffff1681565b3480156102f157600080fd5b506103056103003660046119c7565b6109a9565b6040516101769190611a3c565b6101926103203660046118a3565b610a6f565b34801561033157600080fd5b5060035463ffffffff16600090815260026020526040902054610202565b34801561035b57600080fd5b5061020261036a3660046118a3565b60026020526000908152604090205481565b34801561038857600080fd5b5061022d601e81565b34801561039d57600080fd5b5061016a6103ac3660046118a3565b60009081526006602052604090205460ff1690565b3480156103cd57600080fd5b506102026103dc3660046118a3565b610b5c565b3480156103ed57600080fd5b506102027f2fe54c60d3acabf3343a35b6eba15db4821b340f76e741e2249685ed4899af6c81565b34801561042157600080fd5b506101c87f000000000000000000000000000000000000000000000000000000000000000081565b34801561045557600080fd5b506102026104643660046118a3565b60016020526000908152604090205481565b34801561048257600080fd5b506008546101c8906001600160a01b031681565b3480156104a257600080fd5b5060035461022d90640100000000900463ffffffff1681565b6104c361117f565b60055482111561051a5760405162461bcd60e51b815260206004820152601a60248201527f4665652065786365656473207472616e736665722076616c756500000000000060448201526064015b60405180910390fd5b60008581526006602052604090205460ff16156105795760405162461bcd60e51b815260206004820152601f60248201527f546865206e6f746520686173206265656e20616c7265616479207370656e74006044820152606401610511565b6105828661075e565b6105ce5760405162461bcd60e51b815260206004820152601c60248201527f43616e6e6f742066696e6420796f7572206d65726b6c6520726f6f74000000006044820152606401610511565b6040805160c081018252878152602081018790526001600160a01b038681168284015285811660608301526080820185905260a08201849052915163695ef6f960e01b81527f00000000000000000000000000000000000000000000000000000000000000009092169163695ef6f99161064e918c918c91600401611a82565b6020604051808303816000875af115801561066d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106919190611ae0565b6106d65760405162461bcd60e51b815260206004820152601660248201527524b73b30b634b2103bb4ba34323930bb90383937b7b360511b6044820152606401610511565b6000858152600660205260409020805460ff191660011790556106fb848484846111d8565b604080516001600160a01b03868116825260208201889052918101849052908416907fe9e508bad6d4c3227e881ca19068f099da81b5164dd6d62b2eaf1e8bc6c349319060600160405180910390a26107546001600455565b5050505050505050565b600081810361076f57506000919050565b60035463ffffffff16805b63ffffffff811660009081526002602052604090205484036107a0575060019392505050565b8063ffffffff166000036107b25750601e5b806107bc81611b1f565b9150508163ffffffff168163ffffffff160361077a575060009392505050565b6000600080516020611df7833981519152831061083b5760405162461bcd60e51b815260206004820181905260248201527f5f6c6566742073686f756c6420626520696e7369646520746865206669656c646044820152606401610511565b600080516020611df783398151915282106108a25760405162461bcd60e51b815260206004820152602160248201527f5f72696768742073686f756c6420626520696e7369646520746865206669656c6044820152601960fa1b6064820152608401610511565b60405163f47d33b560e01b81526004810184905260006024820181905284916001600160a01b0387169063f47d33b5906044016040805180830381865afa1580156108f1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109159190611b3f565b9092509050600080516020611df783398151915284830860405163f47d33b560e01b815260048101829052602481018390529092506001600160a01b0387169063f47d33b5906044016040805180830381865afa15801561097a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061099e9190611b3f565b509695505050505050565b60608167ffffffffffffffff8111156109c4576109c4611b79565b6040519080825280602002602001820160405280156109ed578160200160208202803683370190505b50905060005b82811015610a6857610a2c848483818110610a1057610a10611b8f565b9050602002013560009081526006602052604090205460ff1690565b15610a56576001828281518110610a4557610a45611b8f565b911515602092830291909101909101525b80610a6081611ba5565b9150506109f3565b5092915050565b610a7761117f565b60008181526007602052604090205460ff1615610ae05760405162461bcd60e51b815260206004820152602160248201527f54686520636f6d6d69746d656e7420686173206265656e207375626d697474656044820152601960fa1b6064820152608401610511565b6000610aeb82611323565b6000838152600760205260409020805460ff191660011790559050610b0e611516565b6040805163ffffffff8316815242602082015283917fa945e51eec50ab98c161376f0db4cf2aeba3ec92755fe2fcd388bdbbb80ff196910160405180910390a250610b596001600455565b50565b600081600003610b8d57507f2fe54c60d3acabf3343a35b6eba15db4821b340f76e741e2249685ed4899af6c919050565b81600103610bbc57507f256a6135777eee2fd26f54b8b7037a25439d5235caee224154186d2b8a52e31d919050565b81600203610beb57507f1151949895e82ab19924de92c40a3d6f7bcb60d92b00504b8199613683f0c200919050565b81600303610c1a57507f20121ee811489ff8d61f09fb89e313f14959a0f28bb428a20dba6b0b068b3bdb919050565b81600403610c4957507f0a89ca6ffa14cc462cfedb842c30ed221a50a3d6bf022a6a57dc82ab24c157c9919050565b81600503610c7857507f24ca05c2b5cd42e890d6be94c68d0689f4f21c9cec9c0f13fe41d566dfb54959919050565b81600603610ca757507f1ccb97c932565a92c60156bdba2d08f3bf1377464e025cee765679e604a7315c919050565b81600703610cd657507f19156fbd7d1a8bf5cba8909367de1b624534ebab4f0f79e003bccdd1b182bdb4919050565b81600803610d0557507f261af8c1f0912e465744641409f622d466c3920ac6e5ff37e36604cb11dfff80919050565b81600903610d3357507e58459724ff6ca5a1652fcbc3e82b93895cf08e975b19beab3f54c217d1c007919050565b81600a03610d6257507f1f04ef20dee48d39984d8eabe768a70eafa6310ad20849d4573c3c40c2ad1e30919050565b81600b03610d9157507f1bea3dec5dab51567ce7e200a30f7ba6d4276aeaa53e2686f962a46c66d511e5919050565b81600c03610dc057507f0ee0f941e2da4b9e31c3ca97a40d8fa9ce68d97c084177071b3cb46cd3372f0f919050565b81600d03610def57507f1ca9503e8935884501bbaf20be14eb4c46b89772c97b96e3b2ebf3a36a948bbd919050565b81600e03610e1e57507f133a80e30697cd55d8f7d4b0965b7be24057ba5dc3da898ee2187232446cb108919050565b81600f03610e4d57507f13e6d8fc88839ed76e182c2a779af5b2c0da9dd18c90427a644f7e148a6253b6919050565b81601003610e7c57507f1eb16b057a477f4bc8f572ea6bee39561098f78f15bfb3699dcbb7bd8db61854919050565b81601103610eab57507f0da2cb16a1ceaabf1c16b838f7a9e3f2a3a3088d9e0a6debaa748114620696ea919050565b81601203610eda57507f24a3b3d822420b14b5d8cb6c28a574f01e98ea9e940551d2ebd75cee12649f9d919050565b81601303610f0957507f198622acbd783d1b0d9064105b1fc8e4d8889de95c4c519b3f635809fe6afc05919050565b81601403610f3857507f29d7ed391256ccc3ea596c86e933b89ff339d25ea8ddced975ae2fe30b5296d4919050565b81601503610f6757507f19be59f2f0413ce78c0c3703a3a5451b1d7f39629fa33abd11548a76065b2967919050565b81601603610f9657507f1ff3f61797e538b70e619310d33f2a063e7eb59104e112e95738da1254dc3453919050565b81601703610fc557507f10c16ae9959cf8358980d9dd9616e48228737310a10e2b6b731c1a548f036c48919050565b81601803610ff457507f0ba433a63174a90ac20992e75e3095496812b652685b5e1a2eae0b1bf4e8fcd1919050565b8160190361102357507f019ddb9df2bc98d987d0dfeca9d2b643deafab8f7036562e627c3667266a044c919050565b81601a0361105257507f2d3c88b23175c5a5565db928414c66d1912b11acf974b2e644caaac04739ce99919050565b81601b0361108157507f2eab55f6ae4e66e32c5189eed5c470840863445760f5ed7e7b69b2a62600f354919050565b81601c036110af57507e2df37a2642621802383cf952bf4dd1f32e05433beeb1fd41031fb7eace979d919050565b81601d036110de57507f104aeb41435db66c3e62feccc1d6f5d98d0a0ed75d1374db457cf462e3a1f427919050565b81601e0361110d57507f1f3c6fd858e9a7d4b0d1f38e256a09d81d5a5e3c963987e2d4b814cfab7c6ebb919050565b81601f0361113c57507f2c7a07d20dff79d01fecedc1134284a8d08436606c93693b67e333f671bf69cc919050565b60405162461bcd60e51b8152602060048201526013602482015272496e646578206f7574206f6620626f756e647360681b6044820152606401610511565b919050565b6002600454036111d15760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610511565b6002600455565b8034146112405760405162461bcd60e51b815260206004820152603060248201527f496e636f727265637420726566756e6420616d6f756e7420726563656976656460448201526f08189e481d1a194818dbdb9d1c9858dd60821b6064820152608401610511565b61126584836005546112529190611bbe565b6008546001600160a01b0316919061159e565b811561128257600854611282906001600160a01b0316848461159e565b801561131d576000846001600160a01b03168260405160006040518083038185875af1925050503d80600081146112d5576040519150601f19603f3d011682016040523d82523d6000602084013e6112da565b606091505b505090508061131b576040516001600160a01b0385169083156108fc029084906000818181858888f19350505050158015611319573d6000803e3d6000fd5b505b505b50505050565b60035460008054909163ffffffff64010000000090910481169161134991166002611ce8565b63ffffffff168163ffffffff16036113bc5760405162461bcd60e51b815260206004820152603060248201527f4d65726b6c6520747265652069732066756c6c2e204e6f206d6f7265206c656160448201526f1d995cc818d85b88189948185919195960821b6064820152608401610511565b8083600080805b60005463ffffffff9081169082161015611488576113e2600286611cfd565b63ffffffff16600003611420578392506114018163ffffffff16610b5c565b63ffffffff82166000908152600160205260409020859055915061143c565b63ffffffff811660009081526001602052604090205492508391505b6114677f000000000000000000000000000000000000000000000000000000000000000084846107dc565b9350611474600286611d20565b94508061148081611d43565b9150506113c3565b50600354600090601e906114a39063ffffffff166001611d66565b6114ad9190611cfd565b6003805463ffffffff191663ffffffff8316908117909155600090815260026020526040902085905590506114e3866001611d66565b6003805463ffffffff929092166401000000000267ffffffff000000001990921691909117905550939695505050505050565b341561157d5760405162461bcd60e51b815260206004820152603060248201527f4554482076616c756520697320737570706f73656420746f206265203020666f60448201526f7220455243323020696e7374616e636560801b6064820152608401610511565b60055460085461159c916001600160a01b039091169033903090611606565b565b6040516001600160a01b03831660248201526044810182905261160190849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915261163e565b505050565b6040516001600160a01b038085166024830152831660448201526064810182905261131d9085906323b872dd60e01b906084016115ca565b6000611693826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166117139092919063ffffffff16565b90508051600014806116b45750808060200190518101906116b49190611ae0565b6116015760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610511565b6060611722848460008561172a565b949350505050565b60608247101561178b5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610511565b600080866001600160a01b031685876040516117a79190611da7565b60006040518083038185875af1925050503d80600081146117e4576040519150601f19603f3d011682016040523d82523d6000602084013e6117e9565b606091505b50915091506117fa87838387611805565b979650505050505050565b6060831561187457825160000361186d576001600160a01b0385163b61186d5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610511565b5081611722565b61172283838151156118895781518083602001fd5b8060405162461bcd60e51b81526004016105119190611dc3565b6000602082840312156118b557600080fd5b5035919050565b6001600160a01b0381168114610b5957600080fd5b803561117a816118bc565b60008060008060008060008060e0898b0312156118f857600080fd5b883567ffffffffffffffff8082111561191057600080fd5b818b0191508b601f83011261192457600080fd5b81358181111561193357600080fd5b8c602082850101111561194557600080fd5b60209283019a5098505089013595506040890135945061196760608a016118d1565b935061197560808a016118d1565b925060a0890135915060c089013590509295985092959890939650565b6000806000606084860312156119a757600080fd5b83356119b2816118bc565b95602085013595506040909401359392505050565b600080602083850312156119da57600080fd5b823567ffffffffffffffff808211156119f257600080fd5b818501915085601f830112611a0657600080fd5b813581811115611a1557600080fd5b8660208260051b8501011115611a2a57600080fd5b60209290920196919550909350505050565b6020808252825182820181905260009190848201906040850190845b81811015611a76578351151583529284019291840191600101611a58565b50909695505050505050565b60e081528260e08201526000610100848682850137600081868501015280601f19601f87011684010191505060208083018460005b6006811015611ad457815183529183019190830190600101611ab7565b50505050949350505050565b600060208284031215611af257600080fd5b81518015158114611b0257600080fd5b9392505050565b634e487b7160e01b600052601160045260246000fd5b600063ffffffff821680611b3557611b35611b09565b6000190192915050565b60008060408385031215611b5257600080fd5b505080516020909101519092909150565b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b600060018201611bb757611bb7611b09565b5060010190565b81810381811115611bd157611bd1611b09565b92915050565b600181815b80851115611c14578163ffffffff04821115611bfa57611bfa611b09565b80851615611c0757918102915b93841c9390800290611bdc565b509250929050565b600082611c2b57506001611bd1565b81611c3857506000611bd1565b8160018114611c4e5760028114611c5857611c89565b6001915050611bd1565b60ff841115611c6957611c69611b09565b6001841b915063ffffffff821115611c8357611c83611b09565b50611bd1565b5060208310610133831016604e8410600b8410161715611cc0575081810a63ffffffff811115611cbb57611cbb611b09565b611bd1565b611cca8383611bd7565b8063ffffffff04821115611ce057611ce0611b09565b029392505050565b600063ffffffff611722818516828516611c1c565b600063ffffffff80841680611d1457611d14611b63565b92169190910692915050565b600063ffffffff80841680611d3757611d37611b63565b92169190910492915050565b600063ffffffff808316818103611d5c57611d5c611b09565b6001019392505050565b63ffffffff818116838216019080821115610a6857610a68611b09565b60005b83811015611d9e578181015183820152602001611d86565b50506000910152565b60008251611db9818460208701611d83565b9190910192915050565b6020815260008251806020840152611de2816040850160208701611d83565b601f01601f1916919091016040019291505056fe30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001a2646970667358221220ee74c689b13cc4fba50bfce319cf76801d3532b989563d26c4ea35b504c05f9b64736f6c634300081300330000000000000000000000001c868af8840e062572a38ad84f0dc51d7e44ab25000000000000000000000000a7e6d649031c9aa4eb4584eeb99d4dad3d4997660000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000dc038781e421babf1742ff16fc7d2d550d153cbc
Deployed Bytecode
0x6080604052600436106101355760003560e01c8063b214faa5116100ab578063e82955881161006f578063e8295588146103c1578063ec732959146103e1578063ed33639f14610415578063f178e47c14610449578063fc0c546a14610476578063fc7e9c6f1461049657600080fd5b8063b214faa514610312578063ba70f75714610325578063c2b40ae41461034f578063cd87a3b41461037c578063e5285dcc1461039157600080fd5b80636d9833e3116100fd5780636d9833e314610242578063839df945146102625780638bca6d16146102925780638ea3099e146102a857806390eeb02b146102c85780639fa12d0b146102e557600080fd5b806317cc915c1461013a57806321a0adb61461017f5780632b7ac3f314610194578063414a37ba146101e05780634ecf518b14610210575b600080fd5b34801561014657600080fd5b5061016a6101553660046118a3565b60066020526000908152604090205460ff1681565b60405190151581526020015b60405180910390f35b61019261018d3660046118dc565b6104bb565b005b3480156101a057600080fd5b506101c87f0000000000000000000000001c868af8840e062572a38ad84f0dc51d7e44ab2581565b6040516001600160a01b039091168152602001610176565b3480156101ec57600080fd5b50610202600080516020611df783398151915281565b604051908152602001610176565b34801561021c57600080fd5b5060005461022d9063ffffffff1681565b60405163ffffffff9091168152602001610176565b34801561024e57600080fd5b5061016a61025d3660046118a3565b61075e565b34801561026e57600080fd5b5061016a61027d3660046118a3565b60076020526000908152604090205460ff1681565b34801561029e57600080fd5b5061020260055481565b3480156102b457600080fd5b506102026102c3366004611992565b6107dc565b3480156102d457600080fd5b5060035461022d9063ffffffff1681565b3480156102f157600080fd5b506103056103003660046119c7565b6109a9565b6040516101769190611a3c565b6101926103203660046118a3565b610a6f565b34801561033157600080fd5b5060035463ffffffff16600090815260026020526040902054610202565b34801561035b57600080fd5b5061020261036a3660046118a3565b60026020526000908152604090205481565b34801561038857600080fd5b5061022d601e81565b34801561039d57600080fd5b5061016a6103ac3660046118a3565b60009081526006602052604090205460ff1690565b3480156103cd57600080fd5b506102026103dc3660046118a3565b610b5c565b3480156103ed57600080fd5b506102027f2fe54c60d3acabf3343a35b6eba15db4821b340f76e741e2249685ed4899af6c81565b34801561042157600080fd5b506101c87f000000000000000000000000a7e6d649031c9aa4eb4584eeb99d4dad3d49976681565b34801561045557600080fd5b506102026104643660046118a3565b60016020526000908152604090205481565b34801561048257600080fd5b506008546101c8906001600160a01b031681565b3480156104a257600080fd5b5060035461022d90640100000000900463ffffffff1681565b6104c361117f565b60055482111561051a5760405162461bcd60e51b815260206004820152601a60248201527f4665652065786365656473207472616e736665722076616c756500000000000060448201526064015b60405180910390fd5b60008581526006602052604090205460ff16156105795760405162461bcd60e51b815260206004820152601f60248201527f546865206e6f746520686173206265656e20616c7265616479207370656e74006044820152606401610511565b6105828661075e565b6105ce5760405162461bcd60e51b815260206004820152601c60248201527f43616e6e6f742066696e6420796f7572206d65726b6c6520726f6f74000000006044820152606401610511565b6040805160c081018252878152602081018790526001600160a01b038681168284015285811660608301526080820185905260a08201849052915163695ef6f960e01b81527f0000000000000000000000001c868af8840e062572a38ad84f0dc51d7e44ab259092169163695ef6f99161064e918c918c91600401611a82565b6020604051808303816000875af115801561066d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106919190611ae0565b6106d65760405162461bcd60e51b815260206004820152601660248201527524b73b30b634b2103bb4ba34323930bb90383937b7b360511b6044820152606401610511565b6000858152600660205260409020805460ff191660011790556106fb848484846111d8565b604080516001600160a01b03868116825260208201889052918101849052908416907fe9e508bad6d4c3227e881ca19068f099da81b5164dd6d62b2eaf1e8bc6c349319060600160405180910390a26107546001600455565b5050505050505050565b600081810361076f57506000919050565b60035463ffffffff16805b63ffffffff811660009081526002602052604090205484036107a0575060019392505050565b8063ffffffff166000036107b25750601e5b806107bc81611b1f565b9150508163ffffffff168163ffffffff160361077a575060009392505050565b6000600080516020611df7833981519152831061083b5760405162461bcd60e51b815260206004820181905260248201527f5f6c6566742073686f756c6420626520696e7369646520746865206669656c646044820152606401610511565b600080516020611df783398151915282106108a25760405162461bcd60e51b815260206004820152602160248201527f5f72696768742073686f756c6420626520696e7369646520746865206669656c6044820152601960fa1b6064820152608401610511565b60405163f47d33b560e01b81526004810184905260006024820181905284916001600160a01b0387169063f47d33b5906044016040805180830381865afa1580156108f1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109159190611b3f565b9092509050600080516020611df783398151915284830860405163f47d33b560e01b815260048101829052602481018390529092506001600160a01b0387169063f47d33b5906044016040805180830381865afa15801561097a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061099e9190611b3f565b509695505050505050565b60608167ffffffffffffffff8111156109c4576109c4611b79565b6040519080825280602002602001820160405280156109ed578160200160208202803683370190505b50905060005b82811015610a6857610a2c848483818110610a1057610a10611b8f565b9050602002013560009081526006602052604090205460ff1690565b15610a56576001828281518110610a4557610a45611b8f565b911515602092830291909101909101525b80610a6081611ba5565b9150506109f3565b5092915050565b610a7761117f565b60008181526007602052604090205460ff1615610ae05760405162461bcd60e51b815260206004820152602160248201527f54686520636f6d6d69746d656e7420686173206265656e207375626d697474656044820152601960fa1b6064820152608401610511565b6000610aeb82611323565b6000838152600760205260409020805460ff191660011790559050610b0e611516565b6040805163ffffffff8316815242602082015283917fa945e51eec50ab98c161376f0db4cf2aeba3ec92755fe2fcd388bdbbb80ff196910160405180910390a250610b596001600455565b50565b600081600003610b8d57507f2fe54c60d3acabf3343a35b6eba15db4821b340f76e741e2249685ed4899af6c919050565b81600103610bbc57507f256a6135777eee2fd26f54b8b7037a25439d5235caee224154186d2b8a52e31d919050565b81600203610beb57507f1151949895e82ab19924de92c40a3d6f7bcb60d92b00504b8199613683f0c200919050565b81600303610c1a57507f20121ee811489ff8d61f09fb89e313f14959a0f28bb428a20dba6b0b068b3bdb919050565b81600403610c4957507f0a89ca6ffa14cc462cfedb842c30ed221a50a3d6bf022a6a57dc82ab24c157c9919050565b81600503610c7857507f24ca05c2b5cd42e890d6be94c68d0689f4f21c9cec9c0f13fe41d566dfb54959919050565b81600603610ca757507f1ccb97c932565a92c60156bdba2d08f3bf1377464e025cee765679e604a7315c919050565b81600703610cd657507f19156fbd7d1a8bf5cba8909367de1b624534ebab4f0f79e003bccdd1b182bdb4919050565b81600803610d0557507f261af8c1f0912e465744641409f622d466c3920ac6e5ff37e36604cb11dfff80919050565b81600903610d3357507e58459724ff6ca5a1652fcbc3e82b93895cf08e975b19beab3f54c217d1c007919050565b81600a03610d6257507f1f04ef20dee48d39984d8eabe768a70eafa6310ad20849d4573c3c40c2ad1e30919050565b81600b03610d9157507f1bea3dec5dab51567ce7e200a30f7ba6d4276aeaa53e2686f962a46c66d511e5919050565b81600c03610dc057507f0ee0f941e2da4b9e31c3ca97a40d8fa9ce68d97c084177071b3cb46cd3372f0f919050565b81600d03610def57507f1ca9503e8935884501bbaf20be14eb4c46b89772c97b96e3b2ebf3a36a948bbd919050565b81600e03610e1e57507f133a80e30697cd55d8f7d4b0965b7be24057ba5dc3da898ee2187232446cb108919050565b81600f03610e4d57507f13e6d8fc88839ed76e182c2a779af5b2c0da9dd18c90427a644f7e148a6253b6919050565b81601003610e7c57507f1eb16b057a477f4bc8f572ea6bee39561098f78f15bfb3699dcbb7bd8db61854919050565b81601103610eab57507f0da2cb16a1ceaabf1c16b838f7a9e3f2a3a3088d9e0a6debaa748114620696ea919050565b81601203610eda57507f24a3b3d822420b14b5d8cb6c28a574f01e98ea9e940551d2ebd75cee12649f9d919050565b81601303610f0957507f198622acbd783d1b0d9064105b1fc8e4d8889de95c4c519b3f635809fe6afc05919050565b81601403610f3857507f29d7ed391256ccc3ea596c86e933b89ff339d25ea8ddced975ae2fe30b5296d4919050565b81601503610f6757507f19be59f2f0413ce78c0c3703a3a5451b1d7f39629fa33abd11548a76065b2967919050565b81601603610f9657507f1ff3f61797e538b70e619310d33f2a063e7eb59104e112e95738da1254dc3453919050565b81601703610fc557507f10c16ae9959cf8358980d9dd9616e48228737310a10e2b6b731c1a548f036c48919050565b81601803610ff457507f0ba433a63174a90ac20992e75e3095496812b652685b5e1a2eae0b1bf4e8fcd1919050565b8160190361102357507f019ddb9df2bc98d987d0dfeca9d2b643deafab8f7036562e627c3667266a044c919050565b81601a0361105257507f2d3c88b23175c5a5565db928414c66d1912b11acf974b2e644caaac04739ce99919050565b81601b0361108157507f2eab55f6ae4e66e32c5189eed5c470840863445760f5ed7e7b69b2a62600f354919050565b81601c036110af57507e2df37a2642621802383cf952bf4dd1f32e05433beeb1fd41031fb7eace979d919050565b81601d036110de57507f104aeb41435db66c3e62feccc1d6f5d98d0a0ed75d1374db457cf462e3a1f427919050565b81601e0361110d57507f1f3c6fd858e9a7d4b0d1f38e256a09d81d5a5e3c963987e2d4b814cfab7c6ebb919050565b81601f0361113c57507f2c7a07d20dff79d01fecedc1134284a8d08436606c93693b67e333f671bf69cc919050565b60405162461bcd60e51b8152602060048201526013602482015272496e646578206f7574206f6620626f756e647360681b6044820152606401610511565b919050565b6002600454036111d15760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606401610511565b6002600455565b8034146112405760405162461bcd60e51b815260206004820152603060248201527f496e636f727265637420726566756e6420616d6f756e7420726563656976656460448201526f08189e481d1a194818dbdb9d1c9858dd60821b6064820152608401610511565b61126584836005546112529190611bbe565b6008546001600160a01b0316919061159e565b811561128257600854611282906001600160a01b0316848461159e565b801561131d576000846001600160a01b03168260405160006040518083038185875af1925050503d80600081146112d5576040519150601f19603f3d011682016040523d82523d6000602084013e6112da565b606091505b505090508061131b576040516001600160a01b0385169083156108fc029084906000818181858888f19350505050158015611319573d6000803e3d6000fd5b505b505b50505050565b60035460008054909163ffffffff64010000000090910481169161134991166002611ce8565b63ffffffff168163ffffffff16036113bc5760405162461bcd60e51b815260206004820152603060248201527f4d65726b6c6520747265652069732066756c6c2e204e6f206d6f7265206c656160448201526f1d995cc818d85b88189948185919195960821b6064820152608401610511565b8083600080805b60005463ffffffff9081169082161015611488576113e2600286611cfd565b63ffffffff16600003611420578392506114018163ffffffff16610b5c565b63ffffffff82166000908152600160205260409020859055915061143c565b63ffffffff811660009081526001602052604090205492508391505b6114677f000000000000000000000000a7e6d649031c9aa4eb4584eeb99d4dad3d49976684846107dc565b9350611474600286611d20565b94508061148081611d43565b9150506113c3565b50600354600090601e906114a39063ffffffff166001611d66565b6114ad9190611cfd565b6003805463ffffffff191663ffffffff8316908117909155600090815260026020526040902085905590506114e3866001611d66565b6003805463ffffffff929092166401000000000267ffffffff000000001990921691909117905550939695505050505050565b341561157d5760405162461bcd60e51b815260206004820152603060248201527f4554482076616c756520697320737570706f73656420746f206265203020666f60448201526f7220455243323020696e7374616e636560801b6064820152608401610511565b60055460085461159c916001600160a01b039091169033903090611606565b565b6040516001600160a01b03831660248201526044810182905261160190849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915261163e565b505050565b6040516001600160a01b038085166024830152831660448201526064810182905261131d9085906323b872dd60e01b906084016115ca565b6000611693826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b03166117139092919063ffffffff16565b90508051600014806116b45750808060200190518101906116b49190611ae0565b6116015760405162461bcd60e51b815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6044820152691bdd081cdd58d8d9595960b21b6064820152608401610511565b6060611722848460008561172a565b949350505050565b60608247101561178b5760405162461bcd60e51b815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f6044820152651c8818d85b1b60d21b6064820152608401610511565b600080866001600160a01b031685876040516117a79190611da7565b60006040518083038185875af1925050503d80600081146117e4576040519150601f19603f3d011682016040523d82523d6000602084013e6117e9565b606091505b50915091506117fa87838387611805565b979650505050505050565b6060831561187457825160000361186d576001600160a01b0385163b61186d5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610511565b5081611722565b61172283838151156118895781518083602001fd5b8060405162461bcd60e51b81526004016105119190611dc3565b6000602082840312156118b557600080fd5b5035919050565b6001600160a01b0381168114610b5957600080fd5b803561117a816118bc565b60008060008060008060008060e0898b0312156118f857600080fd5b883567ffffffffffffffff8082111561191057600080fd5b818b0191508b601f83011261192457600080fd5b81358181111561193357600080fd5b8c602082850101111561194557600080fd5b60209283019a5098505089013595506040890135945061196760608a016118d1565b935061197560808a016118d1565b925060a0890135915060c089013590509295985092959890939650565b6000806000606084860312156119a757600080fd5b83356119b2816118bc565b95602085013595506040909401359392505050565b600080602083850312156119da57600080fd5b823567ffffffffffffffff808211156119f257600080fd5b818501915085601f830112611a0657600080fd5b813581811115611a1557600080fd5b8660208260051b8501011115611a2a57600080fd5b60209290920196919550909350505050565b6020808252825182820181905260009190848201906040850190845b81811015611a76578351151583529284019291840191600101611a58565b50909695505050505050565b60e081528260e08201526000610100848682850137600081868501015280601f19601f87011684010191505060208083018460005b6006811015611ad457815183529183019190830190600101611ab7565b50505050949350505050565b600060208284031215611af257600080fd5b81518015158114611b0257600080fd5b9392505050565b634e487b7160e01b600052601160045260246000fd5b600063ffffffff821680611b3557611b35611b09565b6000190192915050565b60008060408385031215611b5257600080fd5b505080516020909101519092909150565b634e487b7160e01b600052601260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b600060018201611bb757611bb7611b09565b5060010190565b81810381811115611bd157611bd1611b09565b92915050565b600181815b80851115611c14578163ffffffff04821115611bfa57611bfa611b09565b80851615611c0757918102915b93841c9390800290611bdc565b509250929050565b600082611c2b57506001611bd1565b81611c3857506000611bd1565b8160018114611c4e5760028114611c5857611c89565b6001915050611bd1565b60ff841115611c6957611c69611b09565b6001841b915063ffffffff821115611c8357611c83611b09565b50611bd1565b5060208310610133831016604e8410600b8410161715611cc0575081810a63ffffffff811115611cbb57611cbb611b09565b611bd1565b611cca8383611bd7565b8063ffffffff04821115611ce057611ce0611b09565b029392505050565b600063ffffffff611722818516828516611c1c565b600063ffffffff80841680611d1457611d14611b63565b92169190910692915050565b600063ffffffff80841680611d3757611d37611b63565b92169190910492915050565b600063ffffffff808316818103611d5c57611d5c611b09565b6001019392505050565b63ffffffff818116838216019080821115610a6857610a68611b09565b60005b83811015611d9e578181015183820152602001611d86565b50506000910152565b60008251611db9818460208701611d83565b9190910192915050565b6020815260008251806020840152611de2816040850160208701611d83565b601f01601f1916919091016040019291505056fe30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001a2646970667358221220ee74c689b13cc4fba50bfce319cf76801d3532b989563d26c4ea35b504c05f9b64736f6c63430008130033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000001c868af8840e062572a38ad84f0dc51d7e44ab25000000000000000000000000a7e6d649031c9aa4eb4584eeb99d4dad3d4997660000000000000000000000000000000000000000000000008ac7230489e800000000000000000000000000000000000000000000000000000000000000000014000000000000000000000000dc038781e421babf1742ff16fc7d2d550d153cbc
-----Decoded View---------------
Arg [0] : _verifier (address): 0x1C868af8840e062572A38AD84F0dc51d7E44Ab25
Arg [1] : _hasher (address): 0xa7E6D649031c9AA4Eb4584EeB99d4DAD3d499766
Arg [2] : _denomination (uint256): 10000000000000000000
Arg [3] : _merkleTreeHeight (uint32): 20
Arg [4] : _token (address): 0xdC038781e421BaBF1742Ff16fC7D2d550d153cbC
-----Encoded View---------------
5 Constructor Arguments found :
Arg [0] : 0000000000000000000000001c868af8840e062572a38ad84f0dc51d7e44ab25
Arg [1] : 000000000000000000000000a7e6d649031c9aa4eb4584eeb99d4dad3d499766
Arg [2] : 0000000000000000000000000000000000000000000000008ac7230489e80000
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000014
Arg [4] : 000000000000000000000000dc038781e421babf1742ff16fc7d2d550d153cbc
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 26 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.