Source Code
Overview
ETH Balance
0 ETH
Token Holdings
More Info
ContractCreator
Multichain Info
N/A
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Latest 1 internal transaction
Advanced mode:
Parent Transaction Hash | Block |
From
|
To
|
|||
---|---|---|---|---|---|---|
5421918 | 317 days ago | Contract Creation | 0 ETH |
Loading...
Loading
Contract Name:
Vesting
Compiler Version
v0.8.17+commit.8df45f5f
Contract Source Code (Solidity)
/** *Submitted for verification at Etherscan.io on 2024-03-06 */ // SPDX-License-Identifier: UNLICENSED pragma solidity 0.8.17; // OpenZeppelin Contracts (last updated v4.9.2) (utils/cryptography/MerkleProof.sol) /** * @dev These functions deal with verification of Merkle Tree proofs. * * The tree and the proofs can be generated using our * https://github.com/OpenZeppelin/merkle-tree[JavaScript library]. * You will find a quickstart guide in the readme. * * WARNING: You should avoid using leaf values that are 64 bytes long prior to * hashing, or use a hash function other than keccak256 for hashing leaves. * This is because the concatenation of a sorted pair of internal nodes in * the merkle tree could be reinterpreted as a leaf value. * OpenZeppelin's JavaScript library generates merkle trees that are safe * against this attack out of the box. */ library MerkleProof { /** * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree * defined by `root`. For this, a `proof` must be provided, containing * sibling hashes on the branch from the leaf to the root of the tree. Each * pair of leaves and each pair of pre-images are assumed to be sorted. */ function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) internal pure returns (bool) { return processProof(proof, leaf) == root; } /** * @dev Calldata version of {verify} * * _Available since v4.7._ */ function verifyCalldata(bytes32[] calldata proof, bytes32 root, bytes32 leaf) internal pure returns (bool) { return processProofCalldata(proof, leaf) == root; } /** * @dev Returns the rebuilt hash obtained by traversing a Merkle tree up * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt * hash matches the root of the tree. When processing the proof, the pairs * of leafs & pre-images are assumed to be sorted. * * _Available since v4.4._ */ function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) { bytes32 computedHash = leaf; for (uint256 i = 0; i < proof.length; i++) { computedHash = _hashPair(computedHash, proof[i]); } return computedHash; } /** * @dev Calldata version of {processProof} * * _Available since v4.7._ */ function processProofCalldata(bytes32[] calldata proof, bytes32 leaf) internal pure returns (bytes32) { bytes32 computedHash = leaf; for (uint256 i = 0; i < proof.length; i++) { computedHash = _hashPair(computedHash, proof[i]); } return computedHash; } /** * @dev Returns true if the `leaves` can be simultaneously proven to be a part of a merkle tree defined by * `root`, according to `proof` and `proofFlags` as described in {processMultiProof}. * * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details. * * _Available since v4.7._ */ function multiProofVerify( bytes32[] memory proof, bool[] memory proofFlags, bytes32 root, bytes32[] memory leaves ) internal pure returns (bool) { return processMultiProof(proof, proofFlags, leaves) == root; } /** * @dev Calldata version of {multiProofVerify} * * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details. * * _Available since v4.7._ */ function multiProofVerifyCalldata( bytes32[] calldata proof, bool[] calldata proofFlags, bytes32 root, bytes32[] memory leaves ) internal pure returns (bool) { return processMultiProofCalldata(proof, proofFlags, leaves) == root; } /** * @dev Returns the root of a tree reconstructed from `leaves` and sibling nodes in `proof`. The reconstruction * proceeds by incrementally reconstructing all inner nodes by combining a leaf/inner node with either another * leaf/inner node or a proof sibling node, depending on whether each `proofFlags` item is true or false * respectively. * * CAUTION: Not all merkle trees admit multiproofs. To use multiproofs, it is sufficient to ensure that: 1) the tree * is complete (but not necessarily perfect), 2) the leaves to be proven are in the opposite order they are in the * tree (i.e., as seen from right to left starting at the deepest layer and continuing at the next layer). * * _Available since v4.7._ */ function processMultiProof( bytes32[] memory proof, bool[] memory proofFlags, bytes32[] memory leaves ) internal pure returns (bytes32 merkleRoot) { // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of // the merkle tree. uint256 leavesLen = leaves.length; uint256 proofLen = proof.length; uint256 totalHashes = proofFlags.length; // Check proof validity. require(leavesLen + proofLen - 1 == totalHashes, "MerkleProof: invalid multiproof"); // The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop". bytes32[] memory hashes = new bytes32[](totalHashes); uint256 leafPos = 0; uint256 hashPos = 0; uint256 proofPos = 0; // At each step, we compute the next hash using two values: // - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we // get the next hash. // - depending on the flag, either another value from the "main queue" (merging branches) or an element from the // `proof` array. for (uint256 i = 0; i < totalHashes; i++) { bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]; bytes32 b = proofFlags[i] ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]) : proof[proofPos++]; hashes[i] = _hashPair(a, b); } if (totalHashes > 0) { require(proofPos == proofLen, "MerkleProof: invalid multiproof"); unchecked { return hashes[totalHashes - 1]; } } else if (leavesLen > 0) { return leaves[0]; } else { return proof[0]; } } /** * @dev Calldata version of {processMultiProof}. * * CAUTION: Not all merkle trees admit multiproofs. See {processMultiProof} for details. * * _Available since v4.7._ */ function processMultiProofCalldata( bytes32[] calldata proof, bool[] calldata proofFlags, bytes32[] memory leaves ) internal pure returns (bytes32 merkleRoot) { // This function rebuilds the root hash by traversing the tree up from the leaves. The root is rebuilt by // consuming and producing values on a queue. The queue starts with the `leaves` array, then goes onto the // `hashes` array. At the end of the process, the last hash in the `hashes` array should contain the root of // the merkle tree. uint256 leavesLen = leaves.length; uint256 proofLen = proof.length; uint256 totalHashes = proofFlags.length; // Check proof validity. require(leavesLen + proofLen - 1 == totalHashes, "MerkleProof: invalid multiproof"); // The xxxPos values are "pointers" to the next value to consume in each array. All accesses are done using // `xxx[xxxPos++]`, which return the current value and increment the pointer, thus mimicking a queue's "pop". bytes32[] memory hashes = new bytes32[](totalHashes); uint256 leafPos = 0; uint256 hashPos = 0; uint256 proofPos = 0; // At each step, we compute the next hash using two values: // - a value from the "main queue". If not all leaves have been consumed, we get the next leaf, otherwise we // get the next hash. // - depending on the flag, either another value from the "main queue" (merging branches) or an element from the // `proof` array. for (uint256 i = 0; i < totalHashes; i++) { bytes32 a = leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]; bytes32 b = proofFlags[i] ? (leafPos < leavesLen ? leaves[leafPos++] : hashes[hashPos++]) : proof[proofPos++]; hashes[i] = _hashPair(a, b); } if (totalHashes > 0) { require(proofPos == proofLen, "MerkleProof: invalid multiproof"); unchecked { return hashes[totalHashes - 1]; } } else if (leavesLen > 0) { return leaves[0]; } else { return proof[0]; } } function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) { return a < b ? _efficientHash(a, b) : _efficientHash(b, a); } function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) { /// @solidity memory-safe-assembly assembly { mstore(0x00, a) mstore(0x20, b) value := keccak256(0x00, 0x40) } } } // OpenZeppelin Contracts (last updated v4.9.3) (token/ERC20/utils/SafeERC20.sol) // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol) /** * @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); } // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/extensions/IERC20Permit.sol) /** * @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); } // OpenZeppelin Contracts (last updated v4.9.0) (utils/Address.sol) /** * @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); } } } /** * @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)); } } // OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol) /** * @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); } } } // OpenZeppelin Contracts (last updated v4.9.0) (utils/structs/BitMaps.sol) /** * @dev Library for managing uint256 to bool mapping in a compact and efficient way, providing the keys are sequential. * Largely inspired by Uniswap's https://github.com/Uniswap/merkle-distributor/blob/master/contracts/MerkleDistributor.sol[merkle-distributor]. */ library BitMaps { struct BitMap { mapping(uint256 => uint256) _data; } /** * @dev Returns whether the bit at `index` is set. */ function get(BitMap storage bitmap, uint256 index) internal view returns (bool) { uint256 bucket = index >> 8; uint256 mask = 1 << (index & 0xff); return bitmap._data[bucket] & mask != 0; } /** * @dev Sets the bit at `index` to the boolean `value`. */ function setTo(BitMap storage bitmap, uint256 index, bool value) internal { if (value) { set(bitmap, index); } else { unset(bitmap, index); } } /** * @dev Sets the bit at `index`. */ function set(BitMap storage bitmap, uint256 index) internal { uint256 bucket = index >> 8; uint256 mask = 1 << (index & 0xff); bitmap._data[bucket] |= mask; } /** * @dev Unsets the bit at `index`. */ function unset(BitMap storage bitmap, uint256 index) internal { uint256 bucket = index >> 8; uint256 mask = 1 << (index & 0xff); bitmap._data[bucket] &= ~mask; } } contract Vesting { using BitMaps for BitMaps.BitMap; using SafeERC20 for IERC20; address public immutable token; bytes32 public immutable merkleRoot; uint256 public constant MAX_PERCENTAGE = 1e4; address public owner; mapping(uint256 => uint256) public claimed; BitMaps.BitMap private _revokedBitmap; error InvalidProof(); error NothingToClaim(); error InvalidDates(); error EmptyMerkleRoot(); error OnlyOwner(); error AlreadyRevoked(); error ZeroAddress(); error CantRevokeEndedVesting(); error UnrevocableVesting(); error ClaimAmountGtClaimable(); error Revoked(); event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); event Claim(address indexed account, uint256 amount); event VestingRevoked(address indexed account, uint256 amountUnvested); constructor( address _token, bytes32 _merkleRoot, address _owner ) { if (_merkleRoot == "") revert EmptyMerkleRoot(); token = _token; merkleRoot = _merkleRoot; owner = _owner; } modifier onlyOwner() { if (msg.sender != owner) revert OnlyOwner(); _; } function claim( uint256 index, address account, uint256 amount, bool revocable, uint256 start, uint256 end, uint256 cadence, uint256 percentageOnStart, bytes32[] calldata merkleProof, uint256 claimAmount ) public { bytes32 node = keccak256( abi.encodePacked(index, account, amount, revocable, start, end, cadence, percentageOnStart) ); if (!MerkleProof.verify(merkleProof, merkleRoot, node)) revert InvalidProof(); if (getRevoked(index)) revert Revoked(); uint256 claimable = getClaimable(index, amount, start, end, cadence, percentageOnStart); if (claimable == 0) revert NothingToClaim(); if (claimAmount > claimable) revert ClaimAmountGtClaimable(); claimed[index] += claimAmount; IERC20(token).safeTransfer(account, claimAmount); emit Claim(account, claimAmount); } function stopVesting( uint256 index, address account, uint256 amount, bool revocable, uint256 start, uint256 end, uint256 cadence, uint256 percentageOnStart, bytes32[] calldata merkleProof ) external onlyOwner { bytes32 node = keccak256( abi.encodePacked(index, account, amount, revocable, start, end, cadence, percentageOnStart) ); if (!MerkleProof.verify(merkleProof, merkleRoot, node)) revert InvalidProof(); if (!revocable) revert UnrevocableVesting(); if (getRevoked(index)) revert AlreadyRevoked(); if (block.timestamp >= end) revert CantRevokeEndedVesting(); uint256 claimable = getClaimable(index, amount, start, end, cadence, percentageOnStart); setRevoked(index); if (claimable != 0) { IERC20(token).safeTransfer(account, claimable); emit Claim(account, claimable); } uint256 rest = amount - (claimable + claimed[index]); IERC20(token).safeTransfer(owner, rest); emit VestingRevoked(account, rest); } function getClaimable( uint256 index, uint256 amount, uint256 start, uint256 end, uint256 cadence, uint256 percentageOnStart ) public view returns (uint256) { if (block.timestamp < start) return 0; if (block.timestamp > end) return amount - claimed[index]; uint256 elapsed = ((block.timestamp - start) / cadence) * cadence; if (percentageOnStart != 0) { uint256 claimableOnStart = (percentageOnStart * amount) / MAX_PERCENTAGE; uint256 claimableRest = (elapsed * (amount - claimableOnStart)) / (end - start); return claimableRest + claimableOnStart - claimed[index]; } return (elapsed * amount) / (end - start) - claimed[index]; } function transferOwnership(address newOwner) public virtual onlyOwner { if (newOwner == address(0)) revert ZeroAddress(); owner = newOwner; } function getRevoked(uint256 index) public view returns (bool) { return _revokedBitmap.get(index); } function setRevoked(uint256 index) internal { _revokedBitmap.set(index); } }
[{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"bytes32","name":"_merkleRoot","type":"bytes32"},{"internalType":"address","name":"_owner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AlreadyRevoked","type":"error"},{"inputs":[],"name":"CantRevokeEndedVesting","type":"error"},{"inputs":[],"name":"ClaimAmountGtClaimable","type":"error"},{"inputs":[],"name":"EmptyMerkleRoot","type":"error"},{"inputs":[],"name":"InvalidDates","type":"error"},{"inputs":[],"name":"InvalidProof","type":"error"},{"inputs":[],"name":"NothingToClaim","type":"error"},{"inputs":[],"name":"OnlyOwner","type":"error"},{"inputs":[],"name":"Revoked","type":"error"},{"inputs":[],"name":"UnrevocableVesting","type":"error"},{"inputs":[],"name":"ZeroAddress","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Claim","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":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountUnvested","type":"uint256"}],"name":"VestingRevoked","type":"event"},{"inputs":[],"name":"MAX_PERCENTAGE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bool","name":"revocable","type":"bool"},{"internalType":"uint256","name":"start","type":"uint256"},{"internalType":"uint256","name":"end","type":"uint256"},{"internalType":"uint256","name":"cadence","type":"uint256"},{"internalType":"uint256","name":"percentageOnStart","type":"uint256"},{"internalType":"bytes32[]","name":"merkleProof","type":"bytes32[]"},{"internalType":"uint256","name":"claimAmount","type":"uint256"}],"name":"claim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"claimed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"start","type":"uint256"},{"internalType":"uint256","name":"end","type":"uint256"},{"internalType":"uint256","name":"cadence","type":"uint256"},{"internalType":"uint256","name":"percentageOnStart","type":"uint256"}],"name":"getClaimable","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRevoked","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"merkleRoot","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bool","name":"revocable","type":"bool"},{"internalType":"uint256","name":"start","type":"uint256"},{"internalType":"uint256","name":"end","type":"uint256"},{"internalType":"uint256","name":"cadence","type":"uint256"},{"internalType":"uint256","name":"percentageOnStart","type":"uint256"},{"internalType":"bytes32[]","name":"merkleProof","type":"bytes32[]"}],"name":"stopVesting","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"token","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60c060405234801561001057600080fd5b5060405161141c38038061141c83398101604081905261002f9161009a565b81600003610050576040516385ac2b9960e01b815260040160405180910390fd5b6001600160a01b0392831660805260a091909152600080546001600160a01b031916919092161790556100d6565b80516001600160a01b038116811461009557600080fd5b919050565b6000806000606084860312156100af57600080fd5b6100b88461007e565b9250602084015191506100cd6040850161007e565b90509250925092565b60805160a0516112ff61011d6000396000818160c80152818161040001526107db0152600081816101e101528181610565015281816109440152610a0001526112ff6000f3fe608060405234801561001057600080fd5b50600436106100be5760003560e01c8063dbe7e3bd11610076578063f2fde38b1161005b578063f2fde38b146101b6578063fa9f0a80146101c9578063fc0c546a146101dc57600080fd5b8063dbe7e3bd14610181578063e0e716c4146101a157600080fd5b80634c255c97116100a75780634c255c97146101205780638da5cb5b14610129578063c8b126901461016e57600080fd5b80632eb4a7ab146100c35780634252475c146100fd575b600080fd5b6100ea7f000000000000000000000000000000000000000000000000000000000000000081565b6040519081526020015b60405180910390f35b61011061010b366004610ebe565b610203565b60405190151581526020016100f4565b6100ea61271081565b6000546101499073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100f4565b6100ea61017c366004610ed7565b610228565b6100ea61018f366004610ebe565b60016020526000908152604090205481565b6101b46101af366004610f9d565b610346565b005b6101b46101c436600461104d565b6105eb565b6101b46101d7366004611068565b6106d0565b6101497f000000000000000000000000000000000000000000000000000000000000000081565b600881901c600090815260026020526040812054600160ff84161b1615155b92915050565b60008442101561023a5750600061033c565b834211156102625760008781526001602052604090205461025b908761113c565b905061033c565b60008380610270884261113c565b61027a919061114f565b610284919061118a565b9050821561030157600061271061029b898661118a565b6102a5919061114f565b905060006102b3888861113c565b6102bd838b61113c565b6102c7908561118a565b6102d1919061114f565b60008b8152600160205260409020549091506102ed83836111a1565b6102f7919061113c565b935050505061033c565b60008881526001602052604090205461031a878761113c565b610324898461118a565b61032e919061114f565b610338919061113c565b9150505b9695505050505050565b60408051602081018d90527fffffffffffffffffffffffffffffffffffffffff00000000000000000000000060608d901b1691810191909152605481018a905288151560f81b6074820152607581018890526095810187905260b5810186905260d5810185905260009060f50160405160208183030381529060405280519060200120905061042b8484808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152507f00000000000000000000000000000000000000000000000000000000000000009250859150610a719050565b610461576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61046a8c610203565b156104a1576040517f44825a4b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006104b18d8c8b8b8b8b610228565b9050806000036104ed576040517f969bf72800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80831115610527576040517f1d942e9700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008d815260016020526040812080548592906105459084906111a1565b9091555061058c905073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168d85610a87565b8b73ffffffffffffffffffffffffffffffffffffffff167f47cee97cb7acd717b3c0aa1435d004cd5b3c8c57d70dbceb4e4458bbd60e39d4846040516105d491815260200190565b60405180910390a250505050505050505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff16331461063c576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8116610689576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60005473ffffffffffffffffffffffffffffffffffffffff163314610721576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408051602081018c90527fffffffffffffffffffffffffffffffffffffffff00000000000000000000000060608c901b16918101919091526054810189905287151560f81b6074820152607581018790526095810186905260b5810185905260d5810184905260009060f5016040516020818303038152906040528051906020012090506108068383808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152507f00000000000000000000000000000000000000000000000000000000000000009250859150610a719050565b61083c576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b87610873576040517f4f57eebe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61087c8b610203565b156108b3576040517f905e710700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8542106108ec576040517ff1e17af300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006108fc8c8b8a8a8a8a610228565b90506109248c600881901c60009081526002602052604090208054600160ff84161b17905550565b80156109bc5761096b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168c83610a87565b8a73ffffffffffffffffffffffffffffffffffffffff167f47cee97cb7acd717b3c0aa1435d004cd5b3c8c57d70dbceb4e4458bbd60e39d4826040516109b391815260200190565b60405180910390a25b60008c8152600160205260408120546109d590836111a1565b6109df908c61113c565b600054909150610a299073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000008116911683610a87565b8b73ffffffffffffffffffffffffffffffffffffffff167f57c76f5e278bfbd4eeb5207d287aa5a1a9e1113c65f7eefa540e379a2774d13b826040516105d491815260200190565b600082610a7e8584610b1c565b14949350505050565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052610b14908490610b69565b505050565b50565b600081815b8451811015610b6157610b4d82868381518110610b4057610b406111b4565b6020026020010151610c7d565b915080610b59816111e3565b915050610b21565b509392505050565b6000610bcb826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16610caf9092919063ffffffff16565b9050805160001480610bec575080806020019051810190610bec919061121b565b610b14576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6000818310610c99576000828152602084905260409020610ca8565b60008381526020839052604090205b9392505050565b6060610cbe8484600085610cc6565b949350505050565b606082471015610d58576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610c74565b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051610d81919061125c565b60006040518083038185875af1925050503d8060008114610dbe576040519150601f19603f3d011682016040523d82523d6000602084013e610dc3565b606091505b5091509150610dd487838387610ddf565b979650505050505050565b60608315610e75578251600003610e6e5773ffffffffffffffffffffffffffffffffffffffff85163b610e6e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610c74565b5081610cbe565b610cbe8383815115610e8a5781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c749190611278565b600060208284031215610ed057600080fd5b5035919050565b60008060008060008060c08789031215610ef057600080fd5b505084359660208601359650604086013595606081013595506080810135945060a0013592509050565b803573ffffffffffffffffffffffffffffffffffffffff81168114610f3e57600080fd5b919050565b8015158114610b1957600080fd5b60008083601f840112610f6357600080fd5b50813567ffffffffffffffff811115610f7b57600080fd5b6020830191508360208260051b8501011115610f9657600080fd5b9250929050565b60008060008060008060008060008060006101408c8e031215610fbf57600080fd5b8b359a50610fcf60208d01610f1a565b995060408c0135985060608c0135610fe681610f43565b975060808c0135965060a08c0135955060c08c0135945060e08c013593506101008c013567ffffffffffffffff81111561101f57600080fd5b61102b8e828f01610f51565b915080945050809250506101208c013590509295989b509295989b9093969950565b60006020828403121561105f57600080fd5b610ca882610f1a565b6000806000806000806000806000806101208b8d03121561108857600080fd5b8a35995061109860208c01610f1a565b985060408b0135975060608b01356110af81610f43565b965060808b0135955060a08b0135945060c08b0135935060e08b013592506101008b013567ffffffffffffffff8111156110e857600080fd5b6110f48d828e01610f51565b915080935050809150509295989b9194979a5092959850565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b818103818111156102225761022261110d565b600082611185577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b80820281158282048414176102225761022261110d565b808201808211156102225761022261110d565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036112145761121461110d565b5060010190565b60006020828403121561122d57600080fd5b8151610ca881610f43565b60005b8381101561125357818101518382015260200161123b565b50506000910152565b6000825161126e818460208701611238565b9190910192915050565b6020815260008251806020840152611297816040850160208701611238565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fea26469706673582212207b8106584e71fae3733f31650cc58dd660742e4788036206b246fe94739a9e1c64736f6c634300081100330000000000000000000000001b262e37935a707a3cc5a7373411a99c566a7cc3182bab77690f6e9c84dbbf192a01e9067624b88960783c8dcd3f8077facc5901000000000000000000000000ee061c47e1f2d946c5aa157162149feb06670dbd
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106100be5760003560e01c8063dbe7e3bd11610076578063f2fde38b1161005b578063f2fde38b146101b6578063fa9f0a80146101c9578063fc0c546a146101dc57600080fd5b8063dbe7e3bd14610181578063e0e716c4146101a157600080fd5b80634c255c97116100a75780634c255c97146101205780638da5cb5b14610129578063c8b126901461016e57600080fd5b80632eb4a7ab146100c35780634252475c146100fd575b600080fd5b6100ea7f182bab77690f6e9c84dbbf192a01e9067624b88960783c8dcd3f8077facc590181565b6040519081526020015b60405180910390f35b61011061010b366004610ebe565b610203565b60405190151581526020016100f4565b6100ea61271081565b6000546101499073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016100f4565b6100ea61017c366004610ed7565b610228565b6100ea61018f366004610ebe565b60016020526000908152604090205481565b6101b46101af366004610f9d565b610346565b005b6101b46101c436600461104d565b6105eb565b6101b46101d7366004611068565b6106d0565b6101497f0000000000000000000000001b262e37935a707a3cc5a7373411a99c566a7cc381565b600881901c600090815260026020526040812054600160ff84161b1615155b92915050565b60008442101561023a5750600061033c565b834211156102625760008781526001602052604090205461025b908761113c565b905061033c565b60008380610270884261113c565b61027a919061114f565b610284919061118a565b9050821561030157600061271061029b898661118a565b6102a5919061114f565b905060006102b3888861113c565b6102bd838b61113c565b6102c7908561118a565b6102d1919061114f565b60008b8152600160205260409020549091506102ed83836111a1565b6102f7919061113c565b935050505061033c565b60008881526001602052604090205461031a878761113c565b610324898461118a565b61032e919061114f565b610338919061113c565b9150505b9695505050505050565b60408051602081018d90527fffffffffffffffffffffffffffffffffffffffff00000000000000000000000060608d901b1691810191909152605481018a905288151560f81b6074820152607581018890526095810187905260b5810186905260d5810185905260009060f50160405160208183030381529060405280519060200120905061042b8484808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152507f182bab77690f6e9c84dbbf192a01e9067624b88960783c8dcd3f8077facc59019250859150610a719050565b610461576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61046a8c610203565b156104a1576040517f44825a4b00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006104b18d8c8b8b8b8b610228565b9050806000036104ed576040517f969bf72800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80831115610527576040517f1d942e9700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008d815260016020526040812080548592906105459084906111a1565b9091555061058c905073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000001b262e37935a707a3cc5a7373411a99c566a7cc3168d85610a87565b8b73ffffffffffffffffffffffffffffffffffffffff167f47cee97cb7acd717b3c0aa1435d004cd5b3c8c57d70dbceb4e4458bbd60e39d4846040516105d491815260200190565b60405180910390a250505050505050505050505050565b60005473ffffffffffffffffffffffffffffffffffffffff16331461063c576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8116610689576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60005473ffffffffffffffffffffffffffffffffffffffff163314610721576040517f5fc483c500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60408051602081018c90527fffffffffffffffffffffffffffffffffffffffff00000000000000000000000060608c901b16918101919091526054810189905287151560f81b6074820152607581018790526095810186905260b5810185905260d5810184905260009060f5016040516020818303038152906040528051906020012090506108068383808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152507f182bab77690f6e9c84dbbf192a01e9067624b88960783c8dcd3f8077facc59019250859150610a719050565b61083c576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b87610873576040517f4f57eebe00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61087c8b610203565b156108b3576040517f905e710700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8542106108ec576040517ff1e17af300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006108fc8c8b8a8a8a8a610228565b90506109248c600881901c60009081526002602052604090208054600160ff84161b17905550565b80156109bc5761096b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000001b262e37935a707a3cc5a7373411a99c566a7cc3168c83610a87565b8a73ffffffffffffffffffffffffffffffffffffffff167f47cee97cb7acd717b3c0aa1435d004cd5b3c8c57d70dbceb4e4458bbd60e39d4826040516109b391815260200190565b60405180910390a25b60008c8152600160205260408120546109d590836111a1565b6109df908c61113c565b600054909150610a299073ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000001b262e37935a707a3cc5a7373411a99c566a7cc38116911683610a87565b8b73ffffffffffffffffffffffffffffffffffffffff167f57c76f5e278bfbd4eeb5207d287aa5a1a9e1113c65f7eefa540e379a2774d13b826040516105d491815260200190565b600082610a7e8584610b1c565b14949350505050565b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052610b14908490610b69565b505050565b50565b600081815b8451811015610b6157610b4d82868381518110610b4057610b406111b4565b6020026020010151610c7d565b915080610b59816111e3565b915050610b21565b509392505050565b6000610bcb826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff16610caf9092919063ffffffff16565b9050805160001480610bec575080806020019051810190610bec919061121b565b610b14576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6000818310610c99576000828152602084905260409020610ca8565b60008381526020839052604090205b9392505050565b6060610cbe8484600085610cc6565b949350505050565b606082471015610d58576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c00000000000000000000000000000000000000000000000000006064820152608401610c74565b6000808673ffffffffffffffffffffffffffffffffffffffff168587604051610d81919061125c565b60006040518083038185875af1925050503d8060008114610dbe576040519150601f19603f3d011682016040523d82523d6000602084013e610dc3565b606091505b5091509150610dd487838387610ddf565b979650505050505050565b60608315610e75578251600003610e6e5773ffffffffffffffffffffffffffffffffffffffff85163b610e6e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401610c74565b5081610cbe565b610cbe8383815115610e8a5781518083602001fd5b806040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c749190611278565b600060208284031215610ed057600080fd5b5035919050565b60008060008060008060c08789031215610ef057600080fd5b505084359660208601359650604086013595606081013595506080810135945060a0013592509050565b803573ffffffffffffffffffffffffffffffffffffffff81168114610f3e57600080fd5b919050565b8015158114610b1957600080fd5b60008083601f840112610f6357600080fd5b50813567ffffffffffffffff811115610f7b57600080fd5b6020830191508360208260051b8501011115610f9657600080fd5b9250929050565b60008060008060008060008060008060006101408c8e031215610fbf57600080fd5b8b359a50610fcf60208d01610f1a565b995060408c0135985060608c0135610fe681610f43565b975060808c0135965060a08c0135955060c08c0135945060e08c013593506101008c013567ffffffffffffffff81111561101f57600080fd5b61102b8e828f01610f51565b915080945050809250506101208c013590509295989b509295989b9093969950565b60006020828403121561105f57600080fd5b610ca882610f1a565b6000806000806000806000806000806101208b8d03121561108857600080fd5b8a35995061109860208c01610f1a565b985060408b0135975060608b01356110af81610f43565b965060808b0135955060a08b0135945060c08b0135935060e08b013592506101008b013567ffffffffffffffff8111156110e857600080fd5b6110f48d828e01610f51565b915080935050809150509295989b9194979a5092959850565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b818103818111156102225761022261110d565b600082611185577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b80820281158282048414176102225761022261110d565b808201808211156102225761022261110d565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036112145761121461110d565b5060010190565b60006020828403121561122d57600080fd5b8151610ca881610f43565b60005b8381101561125357818101518382015260200161123b565b50506000910152565b6000825161126e818460208701611238565b9190910192915050565b6020815260008251806020840152611297816040850160208701611238565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016919091016040019291505056fea26469706673582212207b8106584e71fae3733f31650cc58dd660742e4788036206b246fe94739a9e1c64736f6c63430008110033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000001b262e37935a707a3cc5a7373411a99c566a7cc3182bab77690f6e9c84dbbf192a01e9067624b88960783c8dcd3f8077facc5901000000000000000000000000ee061c47e1f2d946c5aa157162149feb06670dbd
-----Decoded View---------------
Arg [0] : _token (address): 0x1b262e37935a707A3Cc5a7373411a99c566a7CC3
Arg [1] : _merkleRoot (bytes32): 0x182bab77690f6e9c84dbbf192a01e9067624b88960783c8dcd3f8077facc5901
Arg [2] : _owner (address): 0xee061C47e1F2d946c5Aa157162149Feb06670dbd
-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 0000000000000000000000001b262e37935a707a3cc5a7373411a99c566a7cc3
Arg [1] : 182bab77690f6e9c84dbbf192a01e9067624b88960783c8dcd3f8077facc5901
Arg [2] : 000000000000000000000000ee061c47e1f2d946c5aa157162149feb06670dbd
Deployed Bytecode Sourcemap
45963:4630:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;46098:35;;;;;;;;160:25:1;;;148:2;133:18;46098:35:0;;;;;;;;50381:113;;;;;;:::i;:::-;;:::i;:::-;;;546:14:1;;539:22;521:41;;509:2;494:18;50381:113:0;381:187:1;46140:44:0;;46181:3;46140:44;;46193:20;;;;;;;;;;;;931:42:1;919:55;;;901:74;;889:2;874:18;46193:20:0;755:226:1;49406:795:0;;;;;;:::i;:::-;;:::i;46222:42::-;;;;;;:::i;:::-;;;;;;;;;;;;;;47232:983;;;;;;:::i;:::-;;:::i;:::-;;50209:164;;;;;;:::i;:::-;;:::i;48223:1175::-;;;;;;:::i;:::-;;:::i;46061:30::-;;;;;50381:113;45051:1;45042:10;;;50437:4;45115:20;;;50461:14;45115:20;;;;;;45078:1;45092:4;45084:12;;45078:19;45115:27;:32;;50461:25;50454:32;50381:113;-1:-1:-1;;50381:113:0:o;49406:795::-;49613:7;49655:5;49637:15;:23;49633:37;;;-1:-1:-1;49669:1:0;49662:8;;49633:37;49703:3;49685:15;:21;49681:57;;;49724:14;;;;:7;:14;;;;;;49715:23;;:6;:23;:::i;:::-;49708:30;;;;49681:57;49751:15;49809:7;;49771:23;49789:5;49771:15;:23;:::i;:::-;49770:35;;;;:::i;:::-;49769:47;;;;:::i;:::-;49751:65;-1:-1:-1;49833:22:0;;49829:294;;49872:24;46181:3;49900:26;49920:6;49900:17;:26;:::i;:::-;49899:45;;;;:::i;:::-;49872:72;-1:-1:-1;49959:21:0;50026:11;50032:5;50026:3;:11;:::i;:::-;49995:25;50004:16;49995:6;:25;:::i;:::-;49984:37;;:7;:37;:::i;:::-;49983:55;;;;:::i;:::-;50097:14;;;;:7;:14;;;;;;49959:79;;-1:-1:-1;50062:32:0;50078:16;49959:79;50062:32;:::i;:::-;:49;;;;:::i;:::-;50055:56;;;;;;;49829:294;50179:14;;;;:7;:14;;;;;;50164:11;50170:5;50164:3;:11;:::i;:::-;50143:16;50153:6;50143:7;:16;:::i;:::-;50142:34;;;;:::i;:::-;:51;;;;:::i;:::-;50135:58;;;49406:795;;;;;;;;;:::o;47232:983::-;47590:91;;;;;;5813:19:1;;;5883:66;5870:2;5866:15;;;5862:88;5848:12;;;5841:110;;;;5967:12;;;5960:28;;;6034:14;;6027:22;6022:3;6018:32;6004:12;;;5997:54;6067:12;;;6060:28;;;6104:13;;;6097:29;;;6142:13;;;6135:29;;;6180:13;;;6173:29;;;47551:12:0;;6218:13:1;;47590:91:0;;;;;;;;;;;;47566:126;;;;;;47551:141;;47708:49;47727:11;;47708:49;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;47740:10:0;;-1:-1:-1;47752:4:0;;-1:-1:-1;47708:18:0;;-1:-1:-1;47708:49:0:i;:::-;47703:77;;47766:14;;;;;;;;;;;;;;47703:77;47797:17;47808:5;47797:10;:17::i;:::-;47793:39;;;47823:9;;;;;;;;;;;;;;47793:39;47845:17;47865:67;47878:5;47885:6;47893:5;47900:3;47905:7;47914:17;47865:12;:67::i;:::-;47845:87;;47949:9;47962:1;47949:14;47945:43;;47972:16;;;;;;;;;;;;;;47945:43;48017:9;48003:11;:23;47999:60;;;48035:24;;;;;;;;;;;;;;47999:60;48072:14;;;;:7;:14;;;;;:29;;48090:11;;48072:14;:29;;48090:11;;48072:29;:::i;:::-;;;;-1:-1:-1;48114:48:0;;-1:-1:-1;48114:26:0;48121:5;48114:26;48141:7;48150:11;48114:26;:48::i;:::-;48186:7;48180:27;;;48195:11;48180:27;;;;160:25:1;;148:2;133:18;;14:177;48180:27:0;;;;;;;;47540:675;;47232:983;;;;;;;;;;;:::o;50209:164::-;47179:5;;;;47165:10;:19;47161:43;;47193:11;;;;;;;;;;;;;;47161:43;50294:22:::1;::::0;::::1;50290:48;;50325:13;;;;;;;;;;;;;;50290:48;50349:5;:16:::0;;;::::1;;::::0;;;::::1;::::0;;;::::1;::::0;;50209:164::o;48223:1175::-;47179:5;;;;47165:10;:19;47161:43;;47193:11;;;;;;;;;;;;;;47161:43;48569:91:::1;::::0;;::::1;::::0;::::1;5813:19:1::0;;;5883:66;5870:2;5866:15;;;5862:88;5848:12;;;5841:110;;;;5967:12;;;5960:28;;;6034:14;;6027:22;6022:3;6018:32;6004:12;;;5997:54;6067:12;;;6060:28;;;6104:13;;;6097:29;;;6142:13;;;6135:29;;;6180:13;;;6173:29;;;48530:12:0::1;::::0;6218:13:1;;48569:91:0::1;;;;;;;;;;;;48545:126;;;;;;48530:141;;48687:49;48706:11;;48687:49;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;::::0;::::1;::::0;;;;-1:-1:-1;48719:10:0::1;::::0;-1:-1:-1;48731:4:0;;-1:-1:-1;48687:18:0::1;::::0;-1:-1:-1;48687:49:0:i:1;:::-;48682:77;;48745:14;;;;;;;;;;;;;;48682:77;48777:9;48772:43;;48795:20;;;;;;;;;;;;;;48772:43;48832:17;48843:5;48832:10;:17::i;:::-;48828:46;;;48858:16;;;;;;;;;;;;;;48828:46;48910:3;48891:15;:22;48887:59;;48922:24;;;;;;;;;;;;;;48887:59;48959:17;48979:67;48992:5;48999:6;49007:5;49014:3;49019:7;49028:17;48979:12;:67::i;:::-;48959:87;;49059:17;49070:5;45604:1:::0;45595:10;;;45578:14;45661:20;;;50557:14;45661:20;;;;;:28;;45631:1;45645:4;45637:12;;45631:19;45661:28;;;50502:88;;49059:17:::1;49093:14:::0;;49089:138:::1;;49124:46;:26;49131:5;49124:26;49151:7:::0;49160:9;49124:26:::1;:46::i;:::-;49196:7;49190:25;;;49205:9;49190:25;;;;160::1::0;;148:2;133:18;;14:177;49190:25:0::1;;;;;;;;49089:138;49239:12;49276:14:::0;;;:7:::1;:14;::::0;;;;;49264:26:::1;::::0;:9;:26:::1;:::i;:::-;49254:37;::::0;:6;:37:::1;:::i;:::-;49331:5;::::0;49239:52;;-1:-1:-1;49304:39:0::1;::::0;49331:5:::1;49311;49304:26:::0;::::1;::::0;49331:5:::1;49239:52:::0;49304:26:::1;:39::i;:::-;49376:7;49361:29;;;49385:4;49361:29;;;;160:25:1::0;;148:2;133:18;;14:177;1189:156:0;1280:4;1333;1304:25;1317:5;1324:4;1304:12;:25::i;:::-;:33;;1189:156;-1:-1:-1;;;;1189:156:0:o;25227:177::-;25337:58;;;6446:42:1;6434:55;;25337:58:0;;;6416:74:1;6506:18;;;;6499:34;;;25337:58:0;;;;;;;;;;6389:18:1;;;;25337:58:0;;;;;;;;;;25360:23;25337:58;;;25310:86;;25330:5;;25310:19;:86::i;:::-;25227:177;;;:::o;50557:25::-;50502:88;:::o;1988:296::-;2071:7;2114:4;2071:7;2129:118;2153:5;:12;2149:1;:16;2129:118;;;2202:33;2212:12;2226:5;2232:1;2226:8;;;;;;;;:::i;:::-;;;;;;;2202:9;:33::i;:::-;2187:48;-1:-1:-1;2167:3:0;;;;:::i;:::-;;;;2129:118;;;-1:-1:-1;2264:12:0;1988:296;-1:-1:-1;;;1988:296:0:o;29573:649::-;29997:23;30023:69;30051:4;30023:69;;;;;;;;;;;;;;;;;30031:5;30023:27;;;;:69;;;;;:::i;:::-;29997:95;;30111:10;:17;30132:1;30111:22;:56;;;;30148:10;30137:30;;;;;;;;;;;;:::i;:::-;30103:111;;;;;;;7385:2:1;30103:111:0;;;7367:21:1;7424:2;7404:18;;;7397:30;7463:34;7443:18;;;7436:62;7534:12;7514:18;;;7507:40;7564:19;;30103:111:0;;;;;;;;9426:149;9489:7;9520:1;9516;:5;:51;;9651:13;9745:15;;;9781:4;9774:15;;;9828:4;9812:21;;9516:51;;;9651:13;9745:15;;;9781:4;9774:15;;;9828:4;9812:21;;9524:20;9509:58;9426:149;-1:-1:-1;;;9426:149:0:o;19109:229::-;19246:12;19278:52;19300:6;19308:4;19314:1;19317:12;19278:21;:52::i;:::-;19271:59;19109:229;-1:-1:-1;;;;19109:229:0:o;20195:455::-;20365:12;20423:5;20398:21;:30;;20390:81;;;;;;;7796:2:1;20390:81:0;;;7778:21:1;7835:2;7815:18;;;7808:30;7874:34;7854:18;;;7847:62;7945:8;7925:18;;;7918:36;7971:19;;20390:81:0;7594:402:1;20390:81:0;20483:12;20497:23;20524:6;:11;;20543:5;20550:4;20524:31;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;20482:73;;;;20573:69;20600:6;20608:7;20617:10;20629:12;20573:26;:69::i;:::-;20566:76;20195:455;-1:-1:-1;;;;;;;20195:455:0:o;22768:644::-;22953:12;22982:7;22978:427;;;23010:10;:17;23031:1;23010:22;23006:290;;16649:19;;;;23220:60;;;;;;;8750:2:1;23220:60:0;;;8732:21:1;8789:2;8769:18;;;8762:30;8828:31;8808:18;;;8801:59;8877:18;;23220:60:0;8548:353:1;23220:60:0;-1:-1:-1;23317:10:0;23310:17;;22978:427;23360:33;23368:10;23380:12;24115:17;;:21;24111:388;;24347:10;24341:17;24404:15;24391:10;24387:2;24383:19;24376:44;24111:388;24474:12;24467:20;;;;;;;;;;;:::i;196:180:1:-;255:6;308:2;296:9;287:7;283:23;279:32;276:52;;;324:1;321;314:12;276:52;-1:-1:-1;347:23:1;;196:180;-1:-1:-1;196:180:1:o;986:523::-;1090:6;1098;1106;1114;1122;1130;1183:3;1171:9;1162:7;1158:23;1154:33;1151:53;;;1200:1;1197;1190:12;1151:53;-1:-1:-1;;1223:23:1;;;1293:2;1278:18;;1265:32;;-1:-1:-1;1344:2:1;1329:18;;1316:32;;1395:2;1380:18;;1367:32;;-1:-1:-1;1446:3:1;1431:19;;1418:33;;-1:-1:-1;1498:3:1;1483:19;1470:33;;-1:-1:-1;986:523:1;-1:-1:-1;986:523:1:o;1514:196::-;1582:20;;1642:42;1631:54;;1621:65;;1611:93;;1700:1;1697;1690:12;1611:93;1514:196;;;:::o;1715:118::-;1801:5;1794:13;1787:21;1780:5;1777:32;1767:60;;1823:1;1820;1813:12;1838:367;1901:8;1911:6;1965:3;1958:4;1950:6;1946:17;1942:27;1932:55;;1983:1;1980;1973:12;1932:55;-1:-1:-1;2006:20:1;;2049:18;2038:30;;2035:50;;;2081:1;2078;2071:12;2035:50;2118:4;2110:6;2106:17;2094:29;;2178:3;2171:4;2161:6;2158:1;2154:14;2146:6;2142:27;2138:38;2135:47;2132:67;;;2195:1;2192;2185:12;2132:67;1838:367;;;;;:::o;2210:1125::-;2374:6;2382;2390;2398;2406;2414;2422;2430;2438;2446;2454:7;2508:3;2496:9;2487:7;2483:23;2479:33;2476:53;;;2525:1;2522;2515:12;2476:53;2561:9;2548:23;2538:33;;2590:38;2624:2;2613:9;2609:18;2590:38;:::i;:::-;2580:48;;2675:2;2664:9;2660:18;2647:32;2637:42;;2729:2;2718:9;2714:18;2701:32;2742:28;2764:5;2742:28;:::i;:::-;2789:5;-1:-1:-1;2841:3:1;2826:19;;2813:33;;-1:-1:-1;2893:3:1;2878:19;;2865:33;;-1:-1:-1;2945:3:1;2930:19;;2917:33;;-1:-1:-1;2997:3:1;2982:19;;2969:33;;-1:-1:-1;3053:3:1;3038:19;;3025:33;3081:18;3070:30;;3067:50;;;3113:1;3110;3103:12;3067:50;3152:70;3214:7;3205:6;3194:9;3190:22;3152:70;:::i;:::-;3126:96;;3241:8;3231:18;;;3268:8;3258:18;;;3324:3;3313:9;3309:19;3296:33;3285:44;;2210:1125;;;;;;;;;;;;;;:::o;3340:186::-;3399:6;3452:2;3440:9;3431:7;3427:23;3423:32;3420:52;;;3468:1;3465;3458:12;3420:52;3491:29;3510:9;3491:29;:::i;3531:1054::-;3686:6;3694;3702;3710;3718;3726;3734;3742;3750;3758;3811:3;3799:9;3790:7;3786:23;3782:33;3779:53;;;3828:1;3825;3818:12;3779:53;3864:9;3851:23;3841:33;;3893:38;3927:2;3916:9;3912:18;3893:38;:::i;:::-;3883:48;;3978:2;3967:9;3963:18;3950:32;3940:42;;4032:2;4021:9;4017:18;4004:32;4045:28;4067:5;4045:28;:::i;:::-;4092:5;-1:-1:-1;4144:3:1;4129:19;;4116:33;;-1:-1:-1;4196:3:1;4181:19;;4168:33;;-1:-1:-1;4248:3:1;4233:19;;4220:33;;-1:-1:-1;4300:3:1;4285:19;;4272:33;;-1:-1:-1;4356:3:1;4341:19;;4328:33;4384:18;4373:30;;4370:50;;;4416:1;4413;4406:12;4370:50;4455:70;4517:7;4508:6;4497:9;4493:22;4455:70;:::i;:::-;4429:96;;4544:8;4534:18;;;4571:8;4561:18;;;3531:1054;;;;;;;;;;;;;:::o;4590:184::-;4642:77;4639:1;4632:88;4739:4;4736:1;4729:15;4763:4;4760:1;4753:15;4779:128;4846:9;;;4867:11;;;4864:37;;;4881:18;;:::i;4912:274::-;4952:1;4978;4968:189;;5013:77;5010:1;5003:88;5114:4;5111:1;5104:15;5142:4;5139:1;5132:15;4968:189;-1:-1:-1;5171:9:1;;4912:274::o;5191:168::-;5264:9;;;5295;;5312:15;;;5306:22;;5292:37;5282:71;;5333:18;;:::i;5364:125::-;5429:9;;;5450:10;;;5447:36;;;5463:18;;:::i;6544:184::-;6596:77;6593:1;6586:88;6693:4;6690:1;6683:15;6717:4;6714:1;6707:15;6733:195;6772:3;6803:66;6796:5;6793:77;6790:103;;6873:18;;:::i;:::-;-1:-1:-1;6920:1:1;6909:13;;6733:195::o;6933:245::-;7000:6;7053:2;7041:9;7032:7;7028:23;7024:32;7021:52;;;7069:1;7066;7059:12;7021:52;7101:9;7095:16;7120:28;7142:5;7120:28;:::i;8001:250::-;8086:1;8096:113;8110:6;8107:1;8104:13;8096:113;;;8186:11;;;8180:18;8167:11;;;8160:39;8132:2;8125:10;8096:113;;;-1:-1:-1;;8243:1:1;8225:16;;8218:27;8001:250::o;8256:287::-;8385:3;8423:6;8417:13;8439:66;8498:6;8493:3;8486:4;8478:6;8474:17;8439:66;:::i;:::-;8521:16;;;;;8256:287;-1:-1:-1;;8256:287:1:o;8906:455::-;9055:2;9044:9;9037:21;9018:4;9087:6;9081:13;9130:6;9125:2;9114:9;9110:18;9103:34;9146:79;9218:6;9213:2;9202:9;9198:18;9193:2;9185:6;9181:15;9146:79;:::i;:::-;9277:2;9265:15;9282:66;9261:88;9246:104;;;;9352:2;9242:113;;8906:455;-1:-1:-1;;8906:455:1:o
Swarm Source
ipfs://7b8106584e71fae3733f31650cc58dd660742e4788036206b246fe94739a9e1c
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.