Feature Tip: Add private address tag to any address under My Name Tag !
More Info
Private Name Tags
ContractCreator
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
Claim
Compiler Version
v0.8.25+commit.b61c2a91
Optimization Enabled:
Yes with 999999 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: ISC pragma solidity 0.8.25; import "@openzeppelin/contracts/access/Ownable2Step.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol"; import "./IClaimable.sol"; /** * @notice Contract that supports one-time issuance of a configurable amount of tokens to a configurable number of * addresses over a configurable vesting schedule. Instead of tracking token balances at construction-/initialization * time, a merkle root is posted to this contract, allowing accounts to prove their balances if they so choose. * * Note: only the associated token contract is able to call `proveInitialBalance(...)`, so this contract is very tightly- * coupled to tokens that resemble the Anvil token, that is to say governance tokens that permit accounts with balances * in this Claim contract to be delegated and used in voting. * * @custom:security-contact [email protected] */ contract Claim is IClaimable, Ownable2Step { /*************** * ERROR TYPES * ***************/ error Unauthorized(); error AlreadyInitialized(); error ClaimAmountTooBig(uint256 _requested, uint256 _availableForClaim); error InvalidProof(); error NoClaimableTokens(); error OwnerRescueTooSoon(); error RescueDestinationHasInitialBalance(); error VestingPeriodNotStarted(); error InvalidInitialization(); /*********** * STRUCTS * ***********/ // NB: Total issuance is 100_000_000_000e18, so uint128 is plenty struct Balance { uint128 initial; uint128 claimed; } /********** * EVENTS * **********/ event TokensClaimed(address indexed byAccount, uint256 amount); event InitialBalanceProven(address indexed account, uint256 initialBalance); event FundsRescued(address indexed to, uint256 amount); /****************** * CONTRACT STATE * ******************/ /// The merkle root of initial user balances that will be subject to this contract's vesting / claim functionality. /// NB: leaves in this tree are of the format `abi.encode(address _address, uint256 _balance)`. bytes32 public balanceRoot; /// The timestamp at which vesting begins. No tokens will be claimable prior to this date. uint32 public vestingStartTimestamp; /// The number of seconds after `vestingStartTimestamp` at which point all tokens will be vested. uint32 public vestingPeriodSeconds; /// The timestamp after which unproven balances may be withdrawn by the owner. See documentation for ownerRescueTokens(...). uint32 public ownerRescueTimestamp; /// The total amount that has been proven but not claimed. This reduces the amount eligible for rescue after `ownerRescueTimestamp`. uint128 public totalProvenUnclaimed; /// The token for which this contract manages claims IERC20 public token; /// account address => Balance (see struct above). Note: this struct is 0 until `proveInitialBalance()` is called. mapping(address => Balance) public provenBalances; /**************** * PUBLIC VIEWS * ****************/ /** * @notice Returns the proven unclaimed balance for the provided account. * @param _forAccount The account for which the proven unclaimed balance will be returned. * @return The proven unclaimed balance. */ function getProvenUnclaimedBalance(address _forAccount) public view returns (uint256) { Balance storage provenBalanceStorage = provenBalances[_forAccount]; return uint256(provenBalanceStorage.initial - provenBalanceStorage.claimed); } /***************************** * STATE-MODIFYING FUNCTIONS * *****************************/ /// Note: this contract is mostly useless until it is initialized via `initialize(...)` below. constructor() Ownable(msg.sender) {} /** * @notice Initializes this claim contract, indicating the token that may be claimed, the root of the balances * merkle tree and vesting parameters. * * @dev Leaves of the merkle tree for which the root is provided are of the format `abi.encode(address, uint256)`, * where the address is the address of the account and the uint256 is the initial balance of that account. * * Note: It is assumed, not enforced, that this contract will receive the amount of _token that constitutes the sum * of all leaves in the merkle tree for which _balanceRoot is the root. On-chain observers will have no way of * knowing that, but off-chain proofs can be made publicly available to provide this assurance. * @param _token The ERC-20 token on which this contract operates. * @param _balanceRoot The merkle root of the balances. * @param _vestingStartDelaySeconds The number of seconds after which claim vesting will start. * @param _vestingPeriodSeconds The period over which token vesting will complete. * @param _ownerRescueDelaySeconds The number of seconds after initialization when the owner may withdraw all unproven tokens. */ function initialize( IERC20 _token, bytes32 _balanceRoot, uint256 _vestingStartDelaySeconds, uint256 _vestingPeriodSeconds, uint256 _ownerRescueDelaySeconds ) external onlyOwner { if (address(token) != address(0)) revert AlreadyInitialized(); if (address(_token) == address(0)) revert InvalidInitialization(); if (_balanceRoot == bytes32(0)) revert InvalidInitialization(); if (_vestingPeriodSeconds == 0) revert InvalidInitialization(); token = _token; balanceRoot = _balanceRoot; vestingStartTimestamp = uint32(block.timestamp + _vestingStartDelaySeconds); vestingPeriodSeconds = uint32(_vestingPeriodSeconds); ownerRescueTimestamp = uint32(block.timestamp + _ownerRescueDelaySeconds); } /** * @notice Claims the provided amount to the sender, assuming that address has a sufficient proven claimable amount. * @param _amount The amount to claim.this */ function claim(uint256 _amount) external { uint256 vestingStart = vestingStartTimestamp; if (block.timestamp <= vestingStart) revert VestingPeriodNotStarted(); uint256 vestedSeconds = block.timestamp - vestingStartTimestamp; uint256 periodSeconds = vestingPeriodSeconds; Balance storage provenBalanceStorage = provenBalances[msg.sender]; uint256 vested = vestedSeconds >= periodSeconds ? uint256(provenBalanceStorage.initial) : (vestedSeconds * uint256(provenBalanceStorage.initial)) / periodSeconds; uint256 claimed = uint256(provenBalanceStorage.claimed); uint256 claimableBalance = vested - claimed; if (claimableBalance == 0) revert NoClaimableTokens(); if (_amount > claimableBalance) revert ClaimAmountTooBig(_amount, claimableBalance); if (_amount == 0) { _amount = claimableBalance; } provenBalanceStorage.claimed = uint128(claimed + _amount); totalProvenUnclaimed -= uint128(_amount); // NB: Return value not checked because this was developed for Anvil, and that reverts on failure. // If repurposing this contract, update to suit your needs. token.transfer(msg.sender, _amount); emit TokensClaimed(msg.sender, _amount); } /** * @notice Allows tokens locked in this contract to be rescued by the owner after a sufficiently long period of time * allowing intended owners to prove their balances. The idea is that if the intended owner hasn't taken action, * they have lost access or do not care to claim. * @dev This disables all future proofs and rescues. * @param _destination The address to which tokens will be transferred. */ function ownerRescueTokens(address _destination) external onlyOwner { if (block.timestamp < ownerRescueTimestamp) revert OwnerRescueTooSoon(); if (getProvenUnclaimedBalance(_destination) > 0) revert RescueDestinationHasInitialBalance(); delete balanceRoot; uint256 amount = token.balanceOf(address(this)) - totalProvenUnclaimed; if (amount == 0) return; // NB: Return value not checked because this was developed for Anvil, and that reverts on failure. // If repurposing this contract, update to suit your needs. token.transfer(_destination, amount); emit FundsRescued(_destination, amount); } /** * @inheritdoc IClaimable */ function proveInitialBalance( address _address, uint256 _initialBalance, bytes32[] calldata _proof ) external returns (uint256) { if (msg.sender != address(token)) revert Unauthorized(); Balance storage provenBalanceStorage = provenBalances[_address]; if (provenBalanceStorage.initial != 0) return 0; _verifyInitialBalanceOrRevert(_address, _initialBalance, _proof); totalProvenUnclaimed += uint128(_initialBalance); provenBalanceStorage.initial = uint128(_initialBalance); emit InitialBalanceProven(_address, _initialBalance); return _initialBalance; } /** * Note: this is overridden to disable it. * * @inheritdoc Ownable */ function renounceOwnership() public override onlyOwner { // Disallow accidental and intentional ownership renunciation. revert(); } /******************************** * PRIVATE / INTERNAL FUNCTIONS * ********************************/ /** * @notice Verifies the provided address has the provided initial balance according to the provided merkle proof, * reverting if it does not. * @param _address The address in question. * @param _initialBalance The initial balance being proven. * @param _proof The merkle proof that the address has the balance. */ function _verifyInitialBalanceOrRevert( address _address, uint256 _initialBalance, bytes32[] calldata _proof ) private view { if ( !MerkleProof.verifyCalldata( _proof, balanceRoot, keccak256(abi.encodePacked(keccak256(abi.encode(_address, _initialBalance)))) ) ) { revert InvalidProof(); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol) pragma solidity ^0.8.20; import {Context} from "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * The initial owner is set to the address provided by the deployer. This can * later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; /** * @dev The caller account is not authorized to perform an operation. */ error OwnableUnauthorizedAccount(address account); /** * @dev The owner is not a valid owner account. (eg. `address(0)`) */ error OwnableInvalidOwner(address owner); event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the address provided by the deployer as the initial owner. */ constructor(address initialOwner) { if (initialOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(initialOwner); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { if (owner() != _msgSender()) { revert OwnableUnauthorizedAccount(_msgSender()); } } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { if (newOwner == address(0)) { revert OwnableInvalidOwner(address(0)); } _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable2Step.sol) pragma solidity ^0.8.20; import {Ownable} from "./Ownable.sol"; /** * @dev Contract module which provides access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * The initial owner is specified at deployment time in the constructor for `Ownable`. This * can later be changed with {transferOwnership} and {acceptOwnership}. * * This module is used through inheritance. It will make available all functions * from parent (Ownable). */ abstract contract Ownable2Step is Ownable { address private _pendingOwner; event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner); /** * @dev Returns the address of the pending owner. */ function pendingOwner() public view virtual returns (address) { return _pendingOwner; } /** * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one. * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual override onlyOwner { _pendingOwner = newOwner; emit OwnershipTransferStarted(owner(), newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner. * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual override { delete _pendingOwner; super._transferOwnership(newOwner); } /** * @dev The new owner accepts the ownership transfer. */ function acceptOwnership() public virtual { address sender = _msgSender(); if (pendingOwner() != sender) { revert OwnableUnauthorizedAccount(sender); } _transferOwnership(sender); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the value of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the value of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves a `value` amount of tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 value) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets a `value` amount of tokens as the allowance of `spender` over the * caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 value) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the * allowance mechanism. `value` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 value) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol) pragma solidity ^0.8.20; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/MerkleProof.sol) pragma solidity ^0.8.20; /** * @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 The multiproof provided is not valid. */ error MerkleProofInvalidMultiproof(); /** * @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} */ 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. */ 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} */ 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. */ 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. */ 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). */ 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. if (leavesLen + proofLen != totalHashes + 1) { revert MerkleProofInvalidMultiproof(); } // 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) { if (proofPos != proofLen) { revert MerkleProofInvalidMultiproof(); } 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. */ 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. if (leavesLen + proofLen != totalHashes + 1) { revert MerkleProofInvalidMultiproof(); } // 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) { if (proofPos != proofLen) { revert MerkleProofInvalidMultiproof(); } unchecked { return hashes[totalHashes - 1]; } } else if (leavesLen > 0) { return leaves[0]; } else { return proof[0]; } } /** * @dev Sorts the pair (a, b) and hashes the result. */ function _hashPair(bytes32 a, bytes32 b) private pure returns (bytes32) { return a < b ? _efficientHash(a, b) : _efficientHash(b, a); } /** * @dev Implementation of keccak256(abi.encode(a, b)) that doesn't allocate or expand memory. */ 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) } } }
// SPDX-License-Identifier: ISC pragma solidity 0.8.25; interface IClaimable { /** * @notice Proves that the provided address has the provided initial balance, enabling claim and voting. * @dev The merkle proof is for a merkle tree for which leaves take the form * `abi.encode(address _address, uint256 _balance)`. * * This function will revert if the provided merkle proof is not valid UNLESS a balance for the account had previously * been proven via a successful invocation of this function, in which case this is a no-op that always returns 0. * @param _address The address of the account for which the initial balance is being proven. * @param _initialBalance The initial balance of the address, as proven by the provided merkle proof. * @param _proof The merkle proof that proves the initial balance for the address. * @return The amount that has been proven that was not previously proven (will be 0 after initial call for an address). */ function proveInitialBalance( address _address, uint256 _initialBalance, bytes32[] calldata _proof ) external returns (uint256); }
{ "optimizer": { "enabled": true, "runs": 999999 }, "evmVersion": "paris", "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AlreadyInitialized","type":"error"},{"inputs":[{"internalType":"uint256","name":"_requested","type":"uint256"},{"internalType":"uint256","name":"_availableForClaim","type":"uint256"}],"name":"ClaimAmountTooBig","type":"error"},{"inputs":[],"name":"InvalidInitialization","type":"error"},{"inputs":[],"name":"InvalidProof","type":"error"},{"inputs":[],"name":"NoClaimableTokens","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[],"name":"OwnerRescueTooSoon","type":"error"},{"inputs":[],"name":"RescueDestinationHasInitialBalance","type":"error"},{"inputs":[],"name":"Unauthorized","type":"error"},{"inputs":[],"name":"VestingPeriodNotStarted","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"FundsRescued","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"initialBalance","type":"uint256"}],"name":"InitialBalanceProven","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"byAccount","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"TokensClaimed","type":"event"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"balanceRoot","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"claim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_forAccount","type":"address"}],"name":"getProvenUnclaimedBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"_token","type":"address"},{"internalType":"bytes32","name":"_balanceRoot","type":"bytes32"},{"internalType":"uint256","name":"_vestingStartDelaySeconds","type":"uint256"},{"internalType":"uint256","name":"_vestingPeriodSeconds","type":"uint256"},{"internalType":"uint256","name":"_ownerRescueDelaySeconds","type":"uint256"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ownerRescueTimestamp","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_destination","type":"address"}],"name":"ownerRescueTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"},{"internalType":"uint256","name":"_initialBalance","type":"uint256"},{"internalType":"bytes32[]","name":"_proof","type":"bytes32[]"}],"name":"proveInitialBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"provenBalances","outputs":[{"internalType":"uint128","name":"initial","type":"uint128"},{"internalType":"uint128","name":"claimed","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"token","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalProvenUnclaimed","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"vestingPeriodSeconds","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"vestingStartTimestamp","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"}]
Contract Creation Code
6080604052348015600f57600080fd5b503380603557604051631e4fbdf760e01b81526000600482015260240160405180910390fd5b603c816041565b5060ab565b600180546001600160a01b0319169055605881605b565b50565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6112ce806100ba6000396000f3fe608060405234801561001057600080fd5b506004361061011b5760003560e01c8063b2df19da116100b2578063e1f5bbcd11610081578063e65d1da311610066578063e65d1da3146102b0578063f2fde38b14610323578063fc0c546a1461033657600080fd5b8063e1f5bbcd14610276578063e30c39781461029257600080fd5b8063b2df19da146101fd578063bb769f1a14610206578063d03dd46714610253578063d6ddd21b1461026657600080fd5b806379ba5097116100ee57806379ba5097146101825780638da5cb5b1461018a5780639b03b23f146101c9578063a55ac88d146101ea57600080fd5b80630a4d9c2914610120578063379607f51461013557806354f7715414610148578063715018a61461017a575b600080fd5b61013361012e366004611021565b610356565b005b610133610143366004611065565b61052f565b60035461016090640100000000900463ffffffff1681565b60405163ffffffff90911681526020015b60405180910390f35b610133610827565b61013361082f565b60005473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610171565b6101dc6101d736600461107e565b6108a6565b604051908152602001610171565b6101336101f836600461107e565b610918565b6101dc60025481565b600354610232906c0100000000000000000000000090046fffffffffffffffffffffffffffffffff1681565b6040516fffffffffffffffffffffffffffffffff9091168152602001610171565b6101dc6102613660046110a2565b610b7e565b6003546101609063ffffffff1681565b6003546101609068010000000000000000900463ffffffff1681565b60015473ffffffffffffffffffffffffffffffffffffffff166101a4565b6102fa6102be36600461107e565b6005602052600090815260409020546fffffffffffffffffffffffffffffffff8082169170010000000000000000000000000000000090041682565b604080516fffffffffffffffffffffffffffffffff938416815292909116602083015201610171565b61013361033136600461107e565b610cff565b6004546101a49073ffffffffffffffffffffffffffffffffffffffff1681565b61035e610daf565b60045473ffffffffffffffffffffffffffffffffffffffff16156103ae576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff85166103fb576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83610432576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8160000361046c576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600480547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff871617905560028490556104bb834261115d565b6003805463ffffffff858116640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000909216931692909217919091179055610508814261115d565b600360086101000a81548163ffffffff021916908363ffffffff1602179055505050505050565b60035463ffffffff16428110610571576040517f4ae2bef800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6003546000906105879063ffffffff1642611170565b60035433600090815260056020526040812092935064010000000090910463ffffffff169190828410156105e457815483906105d5906fffffffffffffffffffffffffffffffff1686611183565b6105df919061119a565b6105f9565b81546fffffffffffffffffffffffffffffffff165b825490915070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff1660006106308284611170565b90508060000361066c576040517fb8d485a500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b808811156106b5576040517f66cb8b1400000000000000000000000000000000000000000000000000000000815260048101899052602481018290526044015b60405180910390fd5b876000036106c1578097505b6106cb888361115d565b84546fffffffffffffffffffffffffffffffff91821670010000000000000000000000000000000002908216178555600380548a92600c9161071f9185916c010000000000000000000000009004166111d5565b82546fffffffffffffffffffffffffffffffff9182166101009390930a928302919092021990911617905550600480546040517fa9059cbb0000000000000000000000000000000000000000000000000000000081523392810192909252602482018a905273ffffffffffffffffffffffffffffffffffffffff169063a9059cbb906044016020604051808303816000875af11580156107c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107e79190611205565b5060405188815233907f896e034966eaaf1adc54acc0f257056febbd300c9e47182cf761982cf1f5e4309060200160405180910390a25050505050505050565b61011b610daf565b600154339073ffffffffffffffffffffffffffffffffffffffff16811461089a576040517f118cdaa700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff821660048201526024016106ac565b6108a381610e04565b50565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260056020526040812080546108ff906fffffffffffffffffffffffffffffffff7001000000000000000000000000000000008204811691166111d5565b6fffffffffffffffffffffffffffffffff169392505050565b610920610daf565b60035468010000000000000000900463ffffffff1642101561096e576040517fc89f235300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610979826108a6565b11156109b1576040517f6599af9300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006002819055600354600480546040517f70a0823100000000000000000000000000000000000000000000000000000000815230928101929092526c010000000000000000000000009092046fffffffffffffffffffffffffffffffff169173ffffffffffffffffffffffffffffffffffffffff16906370a0823190602401602060405180830381865afa158015610a4e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a729190611227565b610a7c9190611170565b905080600003610a8a575050565b600480546040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116938201939093526024810184905291169063a9059cbb906044016020604051808303816000875af1158015610b05573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b299190611205565b508173ffffffffffffffffffffffffffffffffffffffff167fc4474c2790e13695f6d2b6f1d8e164290b55370f87a542fd7711abe0a1bf40ac82604051610b7291815260200190565b60405180910390a25050565b60045460009073ffffffffffffffffffffffffffffffffffffffff163314610bd2576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8516600090815260056020526040902080546fffffffffffffffffffffffffffffffff1615610c1a576000915050610cf7565b610c2686868686610e35565b846003600c8282829054906101000a90046fffffffffffffffffffffffffffffffff16610c539190611240565b82546101009290920a6fffffffffffffffffffffffffffffffff81810219909316918316021790915582547fffffffffffffffffffffffffffffffff00000000000000000000000000000000169087161782555060405185815273ffffffffffffffffffffffffffffffffffffffff8716907f5ff5d84c0b3a7ba5ab8dba747b231618988c477c8af68fefeb8ddb8ddaf041879060200160405180910390a2849150505b949350505050565b610d07610daf565b6001805473ffffffffffffffffffffffffffffffffffffffff83167fffffffffffffffffffffffff00000000000000000000000000000000000000009091168117909155610d6a60005473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b60005473ffffffffffffffffffffffffffffffffffffffff163314610e02576040517f118cdaa70000000000000000000000000000000000000000000000000000000081523360048201526024016106ac565b565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001690556108a381610efc565b6002546040805173ffffffffffffffffffffffffffffffffffffffff87166020820152908101859052610ec0918491849190606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120908301520160405160208183030381529060405280519060200120610f71565b610ef6576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50505050565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600082610f7f868685610f89565b1495945050505050565b600081815b84811015610fc257610fb882878784818110610fac57610fac611269565b90506020020135610fcb565b9150600101610f8e565b50949350505050565b6000818310610fe7576000828152602084905260409020610ff6565b60008381526020839052604090205b90505b92915050565b73ffffffffffffffffffffffffffffffffffffffff811681146108a357600080fd5b600080600080600060a0868803121561103957600080fd5b853561104481610fff565b97602087013597506040870135966060810135965060800135945092505050565b60006020828403121561107757600080fd5b5035919050565b60006020828403121561109057600080fd5b813561109b81610fff565b9392505050565b600080600080606085870312156110b857600080fd5b84356110c381610fff565b935060208501359250604085013567ffffffffffffffff808211156110e757600080fd5b818701915087601f8301126110fb57600080fd5b81358181111561110a57600080fd5b8860208260051b850101111561111f57600080fd5b95989497505060200194505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b80820180821115610ff957610ff961112e565b81810381811115610ff957610ff961112e565b8082028115828204841417610ff957610ff961112e565b6000826111d0577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b6fffffffffffffffffffffffffffffffff8281168282160390808211156111fe576111fe61112e565b5092915050565b60006020828403121561121757600080fd5b8151801515811461109b57600080fd5b60006020828403121561123957600080fd5b5051919050565b6fffffffffffffffffffffffffffffffff8181168382160190808211156111fe576111fe61112e565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfea264697066735822122089263d80df1b899c04a827071bf5f996725eec072b770b2a3e66382d00f8e94664736f6c63430008190033
Deployed Bytecode
0x608060405234801561001057600080fd5b506004361061011b5760003560e01c8063b2df19da116100b2578063e1f5bbcd11610081578063e65d1da311610066578063e65d1da3146102b0578063f2fde38b14610323578063fc0c546a1461033657600080fd5b8063e1f5bbcd14610276578063e30c39781461029257600080fd5b8063b2df19da146101fd578063bb769f1a14610206578063d03dd46714610253578063d6ddd21b1461026657600080fd5b806379ba5097116100ee57806379ba5097146101825780638da5cb5b1461018a5780639b03b23f146101c9578063a55ac88d146101ea57600080fd5b80630a4d9c2914610120578063379607f51461013557806354f7715414610148578063715018a61461017a575b600080fd5b61013361012e366004611021565b610356565b005b610133610143366004611065565b61052f565b60035461016090640100000000900463ffffffff1681565b60405163ffffffff90911681526020015b60405180910390f35b610133610827565b61013361082f565b60005473ffffffffffffffffffffffffffffffffffffffff165b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610171565b6101dc6101d736600461107e565b6108a6565b604051908152602001610171565b6101336101f836600461107e565b610918565b6101dc60025481565b600354610232906c0100000000000000000000000090046fffffffffffffffffffffffffffffffff1681565b6040516fffffffffffffffffffffffffffffffff9091168152602001610171565b6101dc6102613660046110a2565b610b7e565b6003546101609063ffffffff1681565b6003546101609068010000000000000000900463ffffffff1681565b60015473ffffffffffffffffffffffffffffffffffffffff166101a4565b6102fa6102be36600461107e565b6005602052600090815260409020546fffffffffffffffffffffffffffffffff8082169170010000000000000000000000000000000090041682565b604080516fffffffffffffffffffffffffffffffff938416815292909116602083015201610171565b61013361033136600461107e565b610cff565b6004546101a49073ffffffffffffffffffffffffffffffffffffffff1681565b61035e610daf565b60045473ffffffffffffffffffffffffffffffffffffffff16156103ae576040517f0dc149f000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff85166103fb576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b83610432576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8160000361046c576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600480547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff871617905560028490556104bb834261115d565b6003805463ffffffff858116640100000000027fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000909216931692909217919091179055610508814261115d565b600360086101000a81548163ffffffff021916908363ffffffff1602179055505050505050565b60035463ffffffff16428110610571576040517f4ae2bef800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6003546000906105879063ffffffff1642611170565b60035433600090815260056020526040812092935064010000000090910463ffffffff169190828410156105e457815483906105d5906fffffffffffffffffffffffffffffffff1686611183565b6105df919061119a565b6105f9565b81546fffffffffffffffffffffffffffffffff165b825490915070010000000000000000000000000000000090046fffffffffffffffffffffffffffffffff1660006106308284611170565b90508060000361066c576040517fb8d485a500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b808811156106b5576040517f66cb8b1400000000000000000000000000000000000000000000000000000000815260048101899052602481018290526044015b60405180910390fd5b876000036106c1578097505b6106cb888361115d565b84546fffffffffffffffffffffffffffffffff91821670010000000000000000000000000000000002908216178555600380548a92600c9161071f9185916c010000000000000000000000009004166111d5565b82546fffffffffffffffffffffffffffffffff9182166101009390930a928302919092021990911617905550600480546040517fa9059cbb0000000000000000000000000000000000000000000000000000000081523392810192909252602482018a905273ffffffffffffffffffffffffffffffffffffffff169063a9059cbb906044016020604051808303816000875af11580156107c3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107e79190611205565b5060405188815233907f896e034966eaaf1adc54acc0f257056febbd300c9e47182cf761982cf1f5e4309060200160405180910390a25050505050505050565b61011b610daf565b600154339073ffffffffffffffffffffffffffffffffffffffff16811461089a576040517f118cdaa700000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff821660048201526024016106ac565b6108a381610e04565b50565b73ffffffffffffffffffffffffffffffffffffffff8116600090815260056020526040812080546108ff906fffffffffffffffffffffffffffffffff7001000000000000000000000000000000008204811691166111d5565b6fffffffffffffffffffffffffffffffff169392505050565b610920610daf565b60035468010000000000000000900463ffffffff1642101561096e576040517fc89f235300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610979826108a6565b11156109b1576040517f6599af9300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006002819055600354600480546040517f70a0823100000000000000000000000000000000000000000000000000000000815230928101929092526c010000000000000000000000009092046fffffffffffffffffffffffffffffffff169173ffffffffffffffffffffffffffffffffffffffff16906370a0823190602401602060405180830381865afa158015610a4e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a729190611227565b610a7c9190611170565b905080600003610a8a575050565b600480546040517fa9059cbb00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff858116938201939093526024810184905291169063a9059cbb906044016020604051808303816000875af1158015610b05573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b299190611205565b508173ffffffffffffffffffffffffffffffffffffffff167fc4474c2790e13695f6d2b6f1d8e164290b55370f87a542fd7711abe0a1bf40ac82604051610b7291815260200190565b60405180910390a25050565b60045460009073ffffffffffffffffffffffffffffffffffffffff163314610bd2576040517f82b4290000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff8516600090815260056020526040902080546fffffffffffffffffffffffffffffffff1615610c1a576000915050610cf7565b610c2686868686610e35565b846003600c8282829054906101000a90046fffffffffffffffffffffffffffffffff16610c539190611240565b82546101009290920a6fffffffffffffffffffffffffffffffff81810219909316918316021790915582547fffffffffffffffffffffffffffffffff00000000000000000000000000000000169087161782555060405185815273ffffffffffffffffffffffffffffffffffffffff8716907f5ff5d84c0b3a7ba5ab8dba747b231618988c477c8af68fefeb8ddb8ddaf041879060200160405180910390a2849150505b949350505050565b610d07610daf565b6001805473ffffffffffffffffffffffffffffffffffffffff83167fffffffffffffffffffffffff00000000000000000000000000000000000000009091168117909155610d6a60005473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b60005473ffffffffffffffffffffffffffffffffffffffff163314610e02576040517f118cdaa70000000000000000000000000000000000000000000000000000000081523360048201526024016106ac565b565b600180547fffffffffffffffffffffffff00000000000000000000000000000000000000001690556108a381610efc565b6002546040805173ffffffffffffffffffffffffffffffffffffffff87166020820152908101859052610ec0918491849190606001604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181528282528051602091820120908301520160405160208183030381529060405280519060200120610f71565b610ef6576040517f09bde33900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b50505050565b6000805473ffffffffffffffffffffffffffffffffffffffff8381167fffffffffffffffffffffffff0000000000000000000000000000000000000000831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600082610f7f868685610f89565b1495945050505050565b600081815b84811015610fc257610fb882878784818110610fac57610fac611269565b90506020020135610fcb565b9150600101610f8e565b50949350505050565b6000818310610fe7576000828152602084905260409020610ff6565b60008381526020839052604090205b90505b92915050565b73ffffffffffffffffffffffffffffffffffffffff811681146108a357600080fd5b600080600080600060a0868803121561103957600080fd5b853561104481610fff565b97602087013597506040870135966060810135965060800135945092505050565b60006020828403121561107757600080fd5b5035919050565b60006020828403121561109057600080fd5b813561109b81610fff565b9392505050565b600080600080606085870312156110b857600080fd5b84356110c381610fff565b935060208501359250604085013567ffffffffffffffff808211156110e757600080fd5b818701915087601f8301126110fb57600080fd5b81358181111561110a57600080fd5b8860208260051b850101111561111f57600080fd5b95989497505060200194505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b80820180821115610ff957610ff961112e565b81810381811115610ff957610ff961112e565b8082028115828204841417610ff957610ff961112e565b6000826111d0577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500490565b6fffffffffffffffffffffffffffffffff8281168282160390808211156111fe576111fe61112e565b5092915050565b60006020828403121561121757600080fd5b8151801515811461109b57600080fd5b60006020828403121561123957600080fd5b5051919050565b6fffffffffffffffffffffffffffffffff8181168382160190808211156111fe576111fe61112e565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fdfea264697066735822122089263d80df1b899c04a827071bf5f996725eec072b770b2a3e66382d00f8e94664736f6c63430008190033
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.