More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 7,482 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Claim Tokens | 21469859 | 1 hr ago | IN | 0 ETH | 0.00052272 | ||||
Claim Tokens | 21469855 | 1 hr ago | IN | 0 ETH | 0.00063352 | ||||
Claim Tokens | 21469847 | 1 hr ago | IN | 0 ETH | 0.00052219 | ||||
Claim Tokens | 21469838 | 1 hr ago | IN | 0 ETH | 0.00054031 | ||||
Claim Tokens | 21469737 | 2 hrs ago | IN | 0 ETH | 0.00034281 | ||||
Claim Tokens | 21469724 | 2 hrs ago | IN | 0 ETH | 0.00042549 | ||||
Claim Tokens | 21468856 | 5 hrs ago | IN | 0 ETH | 0.00074308 | ||||
Claim Tokens | 21468583 | 5 hrs ago | IN | 0 ETH | 0.00058909 | ||||
Claim Tokens | 21468027 | 7 hrs ago | IN | 0 ETH | 0.00095848 | ||||
Claim Tokens | 21467576 | 9 hrs ago | IN | 0 ETH | 0.00088316 | ||||
Claim Tokens | 21466951 | 11 hrs ago | IN | 0 ETH | 0.00084152 | ||||
Claim Tokens | 21466682 | 12 hrs ago | IN | 0 ETH | 0.00116806 | ||||
Claim Tokens | 21466340 | 13 hrs ago | IN | 0 ETH | 0.00138585 | ||||
Claim Tokens | 21466195 | 14 hrs ago | IN | 0 ETH | 0.0014903 | ||||
Claim Tokens | 21465801 | 15 hrs ago | IN | 0 ETH | 0.0026039 | ||||
Claim Tokens | 21465510 | 16 hrs ago | IN | 0 ETH | 0.00066233 | ||||
Claim Tokens | 21465486 | 16 hrs ago | IN | 0 ETH | 0.00094164 | ||||
Claim Tokens | 21465484 | 16 hrs ago | IN | 0 ETH | 0.00052991 | ||||
Claim Tokens | 21465424 | 16 hrs ago | IN | 0 ETH | 0.00048411 | ||||
Claim Tokens | 21465382 | 16 hrs ago | IN | 0 ETH | 0.00049906 | ||||
Lock Tokens | 21465252 | 17 hrs ago | IN | 0 ETH | 0.00117362 | ||||
Invalidate Distr... | 21465246 | 17 hrs ago | IN | 0 ETH | 0.00023387 | ||||
Claim Tokens | 21465091 | 17 hrs ago | IN | 0 ETH | 0.00053152 | ||||
Claim Tokens | 21465010 | 17 hrs ago | IN | 0 ETH | 0.00061953 | ||||
Claim Tokens | 21464905 | 18 hrs ago | IN | 0 ETH | 0.00056631 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
PresailDeck
Compiler Version
v0.8.24+commit.e11b9ed9
Optimization Enabled:
No with 200 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity ^0.8.22; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol"; import "@openzeppelin/contracts/utils/structs/BitMaps.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; /** * @title PresailDeck * @dev Contract for distributing tokens using a Merkle tree. */ contract PresailDeck { using SafeERC20 for IERC20; struct Distribution { bytes32 merkleRoot; uint256 lockedTokens; uint256 claimedTokens; address token; bool invalidated; address owner; bool markedForReplacement; bool replaced; } mapping(uint256 => Distribution) public distributions; mapping(uint256 => BitMaps.BitMap) private claimedBitmaps; uint256 public distributionsCount; event TokensLocked(uint256 indexed distributionId, address indexed owner, bytes32 indexed merkleRoot, uint256 lockedTokens, address token, bool forceExactAmountTransfer); event TokensClaimed(uint256 indexed distributionId, address indexed recipient, uint256 amount, address token, address indexed transferRecipient); event TokensReclaimed(uint256 indexed distributionId, uint256 reclaimedTokens, address token); event TokensDeposited(uint256 indexed distributionId, uint256 lockedTokens, uint256 depositedTokens, address token, bool forceExactAmountTransfer); event DistributionSetInvalidated(uint256 indexed distributionId, bool invalidated); event DistributionReplaced(uint256 indexed distributionReplacedId, uint256 indexed distributionId, address indexed owner); error UnauthorizedAccess(address caller, address owner); error DistributionInvalidated(uint256 distributionId); error DistributionNotInvalidated(uint256 distributionId); error TokensAlreadyClaimed(address recipient); error ClaimedTokensExceedLockedAmount(uint256 claimedTokens, uint256 lockedTokens); error InvalidMerkleProof(); error ArraysLengthMismatch(); error TokenMismatch(); error DistributionMarkedForReplacement(uint256 distributionId); error DistributionNotMarkedForReplacement(uint256 distributionId); error DistributionAlreadyReplaced(uint256 distributionId); error NonExactAmountTransfer(); modifier onlyOwner(uint256 _distributionId) { if (distributions[_distributionId].owner != msg.sender) revert UnauthorizedAccess(msg.sender, distributions[_distributionId].owner); _; } /** * @dev Locks tokens in the contract for distribution. * @param _token The address of the token contract. * @param _totalTokens The total number of tokens to be distributed. * @param _merkleRoot The Merkle root of the Merkle tree containing the token distribution. * @param _replacesDistribution If this new distribution replaces an existing one * @param _distributionToReplace If _replacesDistribution is true, this is the index of the distribution to replace */ function lockTokens( address _token, uint256 _totalTokens, bytes32 _merkleRoot, bool _replacesDistribution, uint256 _distributionToReplace, bool _forceExactAmountTransfer ) external { uint256 currentDistributionId = distributionsCount; uint256 distributionExistingBalance = 0; if (_replacesDistribution) { Distribution storage distributionToReplace = distributions[_distributionToReplace]; if (distributionToReplace.replaced) revert DistributionAlreadyReplaced(_distributionToReplace); if (!distributionToReplace.markedForReplacement) revert DistributionNotMarkedForReplacement(_distributionToReplace); if (distributionToReplace.owner != msg.sender) revert UnauthorizedAccess(msg.sender, distributionToReplace.owner); if (distributionToReplace.token != _token) revert TokenMismatch(); distributionToReplace.replaced = true; distributionExistingBalance = distributionToReplace.lockedTokens - distributionToReplace.claimedTokens; emit DistributionReplaced(_distributionToReplace, currentDistributionId, msg.sender); } distributionsCount++; distributions[currentDistributionId].merkleRoot = _merkleRoot; distributions[currentDistributionId].token = _token; distributions[currentDistributionId].owner = msg.sender; uint256 balanceBefore = IERC20(_token).balanceOf(address(this)); IERC20(_token).safeTransferFrom(msg.sender, address(this), _totalTokens); uint256 balanceAfter = IERC20(_token).balanceOf(address(this)); uint256 netTransferAmount = balanceAfter - balanceBefore; // If we indicated it to force exact amounts, then the total entered and what was actually transferred should be the same. if (_forceExactAmountTransfer && _totalTokens != netTransferAmount) revert NonExactAmountTransfer(); distributions[currentDistributionId].lockedTokens = distributionExistingBalance + netTransferAmount; emit TokensLocked(currentDistributionId, msg.sender, _merkleRoot, netTransferAmount, _token, _forceExactAmountTransfer); } /** * @dev Claims tokens for a recipient based on a Merkle proof. * @param _distributionId The ID of the distribution. * @param _index The index of the leaf in the Merkle tree. * @param _amount The amount of tokens to claim. * @param _proof The Merkle proof for the claimed tokens. */ function claimTokens(uint256 _distributionId, uint256 _index, uint256 _amount, bytes32[] calldata _proof) external { _claim(_distributionId, _index, msg.sender, _amount, _proof, msg.sender); } /** * @notice Claims tokens from multiple distributions in a single call. * @dev This function allows users to claim tokens from multiple distributions simultaneously, providing an array of distribution IDs, accounts, amounts, and proofs. * @param _distributionIds An array of distribution IDs from which tokens will be claimed. * @param _indexes An array of indexes for each distribution. * @param _amounts An array of amounts of tokens to claim for each distribution. * @param _proofs An array of Merkle proofs for each distribution claim. */ function claimMultipleTokens(uint256[] calldata _distributionIds, uint256[] calldata _indexes, uint256[] calldata _amounts, bytes32[][] calldata _proofs) external { if (_distributionIds.length != _indexes.length || _distributionIds.length != _amounts.length || _distributionIds.length != _proofs.length) { revert ArraysLengthMismatch(); } for (uint256 i = 0; i < _distributionIds.length; i++) { _claim(_distributionIds[i], _indexes[i], msg.sender, _amounts[i], _proofs[i], msg.sender); } } /** * @dev Allows the owner to clawback tokens of a recipient based on a Merkle proof. * @param _distributionId The ID of the distribution. * @param _index The index of the leaf in the Merkle tree. * @param _account The recipient's address to clawback from. * @param _amount The amount of tokens to reclaim. * @param _proof The Merkle proof for the reclaimed tokens. */ function clawbackTokens(uint256 _distributionId, uint256 _index, address _account, uint256 _amount, bytes32[] calldata _proof) external onlyOwner(_distributionId) { Distribution storage distribution = distributions[_distributionId]; _claim(_distributionId, _index, _account, _amount, _proof, distribution.owner); } /** * @dev Internal function to handle token claims. * @param _distributionId The ID of the distribution. * @param _index The index of the leaf in the Merkle tree. * @param _recipient The recipient's address. * @param _amount The amount of tokens to claim. * @param _proof The Merkle proof for the claimed tokens. * @param _transferRecipient The address to transfer the claimed tokens to. */ function _claim(uint256 _distributionId, uint256 _index, address _recipient, uint256 _amount, bytes32[] calldata _proof, address _transferRecipient) internal { Distribution storage distribution = distributions[_distributionId]; if (distribution.invalidated) revert DistributionInvalidated(_distributionId); if (isClaimed(_distributionId, _index)) revert TokensAlreadyClaimed(_recipient); if (!MerkleProof.verifyCalldata(_proof, distribution.merkleRoot, _leaf(_index, _recipient, _amount))) revert InvalidMerkleProof(); BitMaps.BitMap storage claimedBitmap = claimedBitmaps[_distributionId]; BitMaps.set(claimedBitmap, _index); distribution.claimedTokens = distribution.claimedTokens + _amount; if (distribution.claimedTokens > distribution.lockedTokens) revert ClaimedTokensExceedLockedAmount(distribution.claimedTokens, distribution.lockedTokens); IERC20(distribution.token).safeTransfer(_transferRecipient, _amount); emit TokensClaimed(_distributionId, _recipient, _amount, distribution.token, _transferRecipient); } /** * @dev Allows the owner to reclaim tokens and invalidates a distribution. * To be used in case of emergency or after some deadline if beneficiaries are not claiming anymore. * @param _distributionId The ID of the distribution. */ function reclaimTokensAndInvalidateDistribution(uint256 _distributionId) external onlyOwner(_distributionId) { Distribution storage distribution = distributions[_distributionId]; if (distribution.invalidated) revert DistributionInvalidated(_distributionId); distribution.invalidated = true; uint256 tokensLeft = distribution.lockedTokens - distribution.claimedTokens; IERC20(distribution.token).safeTransfer(distribution.owner, tokensLeft); emit TokensReclaimed(_distributionId, tokensLeft, distribution.token); emit DistributionSetInvalidated(_distributionId, true); } /** * @dev Allows the owner to invalidate a distribution and mark it for replacement. * To be used for creating a distribution that replaces another distribution. * Leaves the tokens still locked in the contract so they can be "transferred" to a new distribution that replaces this one. * @param _distributionId The ID of the distribution. */ function invalidateDistributionForReplacement(uint256 _distributionId) external onlyOwner(_distributionId) { Distribution storage distribution = distributions[_distributionId]; // Can only invalidate it for replacement if: // - it HAS NOT been invalidated AND // - it HAS NOT been already replaced AND // - it HAS NOT been marked for replacement (using invalidateDistributionForReplacement) if (distribution.invalidated) revert DistributionInvalidated(_distributionId); if (distribution.replaced) revert DistributionAlreadyReplaced(_distributionId); if (distribution.markedForReplacement) revert DistributionMarkedForReplacement(_distributionId); distribution.invalidated = true; distribution.markedForReplacement = true; emit DistributionSetInvalidated(_distributionId, true); } /** * @dev Allows the owner to cancel the invalidation of a distribution that has been marked for replacement. * @param _distributionId The ID of the distribution. */ function cancelInvalidateDistributionForReplacement(uint256 _distributionId) external onlyOwner(_distributionId) { Distribution storage distribution = distributions[_distributionId]; // Can only cancel it if: // - it HAS been invalidated AND // - it HAS NOT been already replaced AND // - it HAS been marked for replacement (using invalidateDistributionForReplacement) if (!distribution.invalidated) revert DistributionNotInvalidated(_distributionId); if (distribution.replaced) revert DistributionAlreadyReplaced(_distributionId); if (!distribution.markedForReplacement) revert DistributionNotMarkedForReplacement(_distributionId); distribution.invalidated = false; distribution.markedForReplacement = false; emit DistributionSetInvalidated(_distributionId, false); } /** * @dev Allows owner to deposit tokens into their distribution. * Only to be used if for some reason they initially locked less tokens than the sum of all amounts in tree. * @param _distributionId The ID of the distribution. * @param _tokenAmount The amount of tokens to deposit. */ function depositTokens(uint256 _distributionId, uint256 _tokenAmount, bool _forceExactAmountTransfer) external onlyOwner(_distributionId) { Distribution storage distribution = distributions[_distributionId]; if (distribution.invalidated) revert DistributionInvalidated(_distributionId); uint256 balanceBefore = IERC20(distribution.token).balanceOf(address(this)); IERC20(distribution.token).safeTransferFrom(msg.sender, address(this), _tokenAmount); uint256 balanceAfter = IERC20(distribution.token).balanceOf(address(this)); uint256 netTransferAmount = balanceAfter - balanceBefore; // If we indicated it to force exact mounts, then the total entered and what was actually transferred should be the same. if (_forceExactAmountTransfer && _tokenAmount != netTransferAmount) revert NonExactAmountTransfer(); distribution.lockedTokens = distribution.lockedTokens + netTransferAmount; emit TokensDeposited(_distributionId, distribution.lockedTokens, netTransferAmount, distribution.token, _forceExactAmountTransfer); } /** * @dev Internal function to compute the leaf hash for a given index, account, and amount. * @param index The index of the leaf in the Merkle tree. * @param account The account address. * @param amount The token amount. * @return The computed leaf hash. */ function _leaf(uint256 index, address account, uint256 amount) internal pure returns (bytes32) { return keccak256(bytes.concat(keccak256(abi.encode(index, account, amount)))); } /** * @dev Checks if a recipient has already claimed tokens. * @param _distributionId The ID of the distribution. * @param _index The index of the leaf in the Merkle tree. * @return A boolean indicating whether the tokens are already claimed. */ function isClaimed(uint256 _distributionId, uint256 _index) public view returns (bool) { return BitMaps.get(claimedBitmaps[_distributionId], _index); } /** * @dev Checks if multiple recipients have already claimed tokens. * @param _distributionId The ID of the distribution. * @param _indexes The index of the leaf in the Merkle tree. * @return An array of booleans indicating whether the tokens are already claimed. */ function areClaimed(uint256 _distributionId, uint256[] calldata _indexes) public view returns (bool[] memory) { bool[] memory results = new bool[](_indexes.length); for (uint256 i = 0; i < _indexes.length; i++) { results[i] = BitMaps.get(claimedBitmaps[_distributionId], _indexes[i]); } return results; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Permit.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612]. * * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't * need to send a transaction, and thus is not required to hold Ether at all. * * ==== Security Considerations * * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be * considered as an intention to spend the allowance in any specific way. The second is that because permits have * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be * generally recommended is: * * ```solidity * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public { * try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {} * doThing(..., value); * } * * function doThing(..., uint256 value) public { * token.safeTransferFrom(msg.sender, address(this), value); * ... * } * ``` * * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also * {SafeERC20-safeTransferFrom}). * * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so * contracts should have entry points that don't rely on permit. */ interface IERC20Permit { /** * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens, * given ``owner``'s signed approval. * * IMPORTANT: The same issues {IERC20-approve} has related to transaction * ordering also apply here. * * Emits an {Approval} event. * * Requirements: * * - `spender` cannot be the zero address. * - `deadline` must be a timestamp in the future. * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner` * over the EIP712-formatted function arguments. * - the signature must use ``owner``'s current nonce (see {nonces}). * * For more information on the signature format, see the * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP * section]. * * CAUTION: See Security Considerations above. */ function permit( address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s ) external; /** * @dev Returns the current nonce for `owner`. This value must be * included whenever a signature is generated for {permit}. * * Every successful call to {permit} increases ``owner``'s nonce by one. This * prevents a signature from being used multiple times. */ function nonces(address owner) external view returns (uint256); /** * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}. */ // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC20 standard as defined in the EIP. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed to, uint256 value); /** * @dev Emitted when the allowance of a `spender` for an `owner` is set by * a call to {approve}. `value` is the new allowance. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the value of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the value of tokens owned by `account`. */ function balanceOf(address account) external view returns (uint256); /** * @dev Moves a `value` amount of tokens from the caller's account to `to`. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transfer(address to, uint256 value) external returns (bool); /** * @dev Returns the remaining number of tokens that `spender` will be * allowed to spend on behalf of `owner` through {transferFrom}. This is * zero by default. * * This value changes when {approve} or {transferFrom} are called. */ function allowance(address owner, address spender) external view returns (uint256); /** * @dev Sets a `value` amount of tokens as the allowance of `spender` over the * caller's tokens. * * Returns a boolean value indicating whether the operation succeeded. * * IMPORTANT: Beware that changing an allowance with this method brings the risk * that someone may use both the old and the new allowance by unfortunate * transaction ordering. One possible solution to mitigate this race * condition is to first reduce the spender's allowance to 0 and set the * desired value afterwards: * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 * * Emits an {Approval} event. */ function approve(address spender, uint256 value) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the * allowance mechanism. `value` is then deducted from the caller's * allowance. * * Returns a boolean value indicating whether the operation succeeded. * * Emits a {Transfer} event. */ function transferFrom(address from, address to, uint256 value) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.20; import {IERC20} from "../IERC20.sol"; import {IERC20Permit} from "../extensions/IERC20Permit.sol"; import {Address} from "../../../utils/Address.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { using Address for address; /** * @dev An operation with an ERC20 token failed. */ error SafeERC20FailedOperation(address token); /** * @dev Indicates a failed `decreaseAllowance` request. */ error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease); /** * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeTransfer(IERC20 token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value))); } /** * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful. */ function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value))); } /** * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 oldAllowance = token.allowance(address(this), spender); forceApprove(token, spender, oldAllowance + value); } /** * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no * value, non-reverting calls are assumed to be successful. */ function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal { unchecked { uint256 currentAllowance = token.allowance(address(this), spender); if (currentAllowance < requestedDecrease) { revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease); } forceApprove(token, spender, currentAllowance - requestedDecrease); } } /** * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval * to be set to zero before setting it to a non-zero value, such as USDT. */ function forceApprove(IERC20 token, address spender, uint256 value) internal { bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value)); if (!_callOptionalReturnBool(token, approvalCall)) { _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0))); _callOptionalReturn(token, approvalCall); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). */ function _callOptionalReturn(IERC20 token, bytes memory data) private { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that // the target address contains contract code and also asserts for success in the low-level call. bytes memory returndata = address(token).functionCall(data); if (returndata.length != 0 && !abi.decode(returndata, (bool))) { revert SafeERC20FailedOperation(address(token)); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). * * This is a variant of {_callOptionalReturn} that silents catches all reverts and returns a bool instead. */ function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) { // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since // we're implementing it ourselves. We cannot use {Address-functionCall} here since this should return false // and not revert is the subcall reverts. (bool success, bytes memory returndata) = address(token).call(data); return success && (returndata.length == 0 || abi.decode(returndata, (bool))) && address(token).code.length > 0; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol) pragma solidity ^0.8.20; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev The ETH balance of the account is not enough to perform the operation. */ error AddressInsufficientBalance(address account); /** * @dev There's no code at `target` (it is not a contract). */ error AddressEmptyCode(address target); /** * @dev A call to an address target failed. The target may have reverted. */ error FailedInnerCall(); /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { if (address(this).balance < amount) { revert AddressInsufficientBalance(address(this)); } (bool success, ) = recipient.call{value: amount}(""); if (!success) { revert FailedInnerCall(); } } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason or custom error, it is bubbled * up by this function (like regular Solidity function calls). However, if * the call reverted with no returned reason, this function reverts with a * {FailedInnerCall} error. * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { if (address(this).balance < value) { revert AddressInsufficientBalance(address(this)); } (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an * unsuccessful call. */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata ) internal view returns (bytes memory) { if (!success) { _revert(returndata); } else { // only check if target is a contract if the call was successful and the return data is empty // otherwise we already know that it was a contract if (returndata.length == 0 && target.code.length == 0) { revert AddressEmptyCode(target); } return returndata; } } /** * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the * revert reason or with a default {FailedInnerCall} error. */ function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) { if (!success) { _revert(returndata); } else { return returndata; } } /** * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}. */ function _revert(bytes memory returndata) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly /// @solidity memory-safe-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert FailedInnerCall(); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/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: MIT // OpenZeppelin Contracts (last updated v5.0.0) (utils/structs/BitMaps.sol) pragma solidity ^0.8.20; /** * @dev Library for managing uint256 to bool mapping in a compact and efficient way, provided the keys are sequential. * Largely inspired by Uniswap's https://github.com/Uniswap/merkle-distributor/blob/master/contracts/MerkleDistributor.sol[merkle-distributor]. * * BitMaps pack 256 booleans across each bit of a single 256-bit slot of `uint256` type. * Hence booleans corresponding to 256 _sequential_ indices would only consume a single slot, * unlike the regular `bool` which would consume an entire slot for a single value. * * This results in gas savings in two ways: * * - Setting a zero value to non-zero only once every 256 times * - Accessing the same warm slot for every 256 _sequential_ indices */ library BitMaps { struct BitMap { mapping(uint256 bucket => 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; } }
{ "evmVersion": "paris", "optimizer": { "enabled": false, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"target","type":"address"}],"name":"AddressEmptyCode","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"AddressInsufficientBalance","type":"error"},{"inputs":[],"name":"ArraysLengthMismatch","type":"error"},{"inputs":[{"internalType":"uint256","name":"claimedTokens","type":"uint256"},{"internalType":"uint256","name":"lockedTokens","type":"uint256"}],"name":"ClaimedTokensExceedLockedAmount","type":"error"},{"inputs":[{"internalType":"uint256","name":"distributionId","type":"uint256"}],"name":"DistributionAlreadyReplaced","type":"error"},{"inputs":[{"internalType":"uint256","name":"distributionId","type":"uint256"}],"name":"DistributionInvalidated","type":"error"},{"inputs":[{"internalType":"uint256","name":"distributionId","type":"uint256"}],"name":"DistributionMarkedForReplacement","type":"error"},{"inputs":[{"internalType":"uint256","name":"distributionId","type":"uint256"}],"name":"DistributionNotInvalidated","type":"error"},{"inputs":[{"internalType":"uint256","name":"distributionId","type":"uint256"}],"name":"DistributionNotMarkedForReplacement","type":"error"},{"inputs":[],"name":"FailedInnerCall","type":"error"},{"inputs":[],"name":"InvalidMerkleProof","type":"error"},{"inputs":[],"name":"NonExactAmountTransfer","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"inputs":[],"name":"TokenMismatch","type":"error"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"}],"name":"TokensAlreadyClaimed","type":"error"},{"inputs":[{"internalType":"address","name":"caller","type":"address"},{"internalType":"address","name":"owner","type":"address"}],"name":"UnauthorizedAccess","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"distributionReplacedId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"distributionId","type":"uint256"},{"indexed":true,"internalType":"address","name":"owner","type":"address"}],"name":"DistributionReplaced","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"distributionId","type":"uint256"},{"indexed":false,"internalType":"bool","name":"invalidated","type":"bool"}],"name":"DistributionSetInvalidated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"distributionId","type":"uint256"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"transferRecipient","type":"address"}],"name":"TokensClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"distributionId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"lockedTokens","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"depositedTokens","type":"uint256"},{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"bool","name":"forceExactAmountTransfer","type":"bool"}],"name":"TokensDeposited","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"distributionId","type":"uint256"},{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"bytes32","name":"merkleRoot","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"lockedTokens","type":"uint256"},{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"bool","name":"forceExactAmountTransfer","type":"bool"}],"name":"TokensLocked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"distributionId","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"reclaimedTokens","type":"uint256"},{"indexed":false,"internalType":"address","name":"token","type":"address"}],"name":"TokensReclaimed","type":"event"},{"inputs":[{"internalType":"uint256","name":"_distributionId","type":"uint256"},{"internalType":"uint256[]","name":"_indexes","type":"uint256[]"}],"name":"areClaimed","outputs":[{"internalType":"bool[]","name":"","type":"bool[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_distributionId","type":"uint256"}],"name":"cancelInvalidateDistributionForReplacement","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_distributionIds","type":"uint256[]"},{"internalType":"uint256[]","name":"_indexes","type":"uint256[]"},{"internalType":"uint256[]","name":"_amounts","type":"uint256[]"},{"internalType":"bytes32[][]","name":"_proofs","type":"bytes32[][]"}],"name":"claimMultipleTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_distributionId","type":"uint256"},{"internalType":"uint256","name":"_index","type":"uint256"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"bytes32[]","name":"_proof","type":"bytes32[]"}],"name":"claimTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_distributionId","type":"uint256"},{"internalType":"uint256","name":"_index","type":"uint256"},{"internalType":"address","name":"_account","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"bytes32[]","name":"_proof","type":"bytes32[]"}],"name":"clawbackTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_distributionId","type":"uint256"},{"internalType":"uint256","name":"_tokenAmount","type":"uint256"},{"internalType":"bool","name":"_forceExactAmountTransfer","type":"bool"}],"name":"depositTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"distributions","outputs":[{"internalType":"bytes32","name":"merkleRoot","type":"bytes32"},{"internalType":"uint256","name":"lockedTokens","type":"uint256"},{"internalType":"uint256","name":"claimedTokens","type":"uint256"},{"internalType":"address","name":"token","type":"address"},{"internalType":"bool","name":"invalidated","type":"bool"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"bool","name":"markedForReplacement","type":"bool"},{"internalType":"bool","name":"replaced","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"distributionsCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_distributionId","type":"uint256"}],"name":"invalidateDistributionForReplacement","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_distributionId","type":"uint256"},{"internalType":"uint256","name":"_index","type":"uint256"}],"name":"isClaimed","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_totalTokens","type":"uint256"},{"internalType":"bytes32","name":"_merkleRoot","type":"bytes32"},{"internalType":"bool","name":"_replacesDistribution","type":"bool"},{"internalType":"uint256","name":"_distributionToReplace","type":"uint256"},{"internalType":"bool","name":"_forceExactAmountTransfer","type":"bool"}],"name":"lockTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_distributionId","type":"uint256"}],"name":"reclaimTokensAndInvalidateDistribution","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
608060405234801561001057600080fd5b50612a87806100206000396000f3fe608060405234801561001057600080fd5b50600436106100b45760003560e01c8063a823513d11610071578063a823513d14610190578063b15cb39c146101ac578063daafd1b6146101c8578063ec7239c9146101e6578063f364c90c14610202578063f6e213ef14610232576100b4565b80631078f946146100b95780634487d3df146100d55780635697d1d51461010c5780636117202e146101285780638df3a04314610144578063957d485d14610160575b600080fd5b6100d360048036038101906100ce9190611e4c565b61024e565b005b6100ef60048036038101906100ea9190611e4c565b6104b3565b604051610103989796959493929190611efd565b60405180910390f35b61012660048036038101906101219190611fff565b610562565b005b610142600480360381019061013d91906120f1565b610ac8565b005b61015e60048036038101906101599190612179565b610ade565b005b61017a60048036038101906101759190612222565b610e96565b6040516101879190612340565b60405180910390f35b6101aa60048036038101906101a59190612362565b610f69565b005b6101c660048036038101906101c19190612452565b611099565b005b6101d061119f565b6040516101dd919061253b565b60405180910390f35b61020060048036038101906101fb9190611e4c565b6111a5565b005b61021c60048036038101906102179190612556565b61140c565b6040516102299190612596565b60405180910390f35b61024c60048036038101906102479190611e4c565b611432565b005b803373ffffffffffffffffffffffffffffffffffffffff1660008083815260200190815260200160002060040160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461032b573360008083815260200190815260200160002060040160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166040517f4116c50f0000000000000000000000000000000000000000000000000000000081526004016103229291906125b1565b60405180910390fd5b600080600084815260200190815260200160002090508060030160149054906101000a900460ff1661039457826040517f8c0c84b000000000000000000000000000000000000000000000000000000000815260040161038b919061253b565b60405180910390fd5b8060040160159054906101000a900460ff16156103e857826040517f642bd49b0000000000000000000000000000000000000000000000000000000081526004016103df919061253b565b60405180910390fd5b8060040160149054906101000a900460ff1661043b57826040517f06b71ff6000000000000000000000000000000000000000000000000000000008152600401610432919061253b565b60405180910390fd5b60008160030160146101000a81548160ff02191690831515021790555060008160040160146101000a81548160ff021916908315150217905550827f57393e4ee03ae6e27c99ac585130d8c60ee9bf27d14ee2e1652279adf187320860006040516104a69190612596565b60405180910390a2505050565b60006020528060005260406000206000915090508060000154908060010154908060020154908060030160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060030160149054906101000a900460ff16908060040160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060040160149054906101000a900460ff16908060040160159054906101000a900460ff16905088565b60006002549050600084156107eb57600080600086815260200190815260200160002090508060040160159054906101000a900460ff16156105db57846040517f642bd49b0000000000000000000000000000000000000000000000000000000081526004016105d2919061253b565b60405180910390fd5b8060040160149054906101000a900460ff1661062e57846040517f06b71ff6000000000000000000000000000000000000000000000000000000008152600401610625919061253b565b60405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff168160040160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146106e857338160040160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166040517f4116c50f0000000000000000000000000000000000000000000000000000000081526004016106df9291906125b1565b60405180910390fd5b8873ffffffffffffffffffffffffffffffffffffffff168160030160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610771576040517f936bb5ad00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018160040160156101000a81548160ff021916908315150217905550806002015481600101546107a29190612609565b91503373ffffffffffffffffffffffffffffffffffffffff1683867ffd27571d31e4622ccb1eeb720cbabd67673e92690e750788fd3a0a857965514160405160405180910390a4505b600260008154809291906107fe9061263d565b919050555085600080848152602001908152602001600020600001819055508760008084815260200190815260200160002060030160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055503360008084815260200190815260200160002060040160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060008873ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016109009190612685565b602060405180830381865afa15801561091d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061094191906126b5565b905061097033308a8c73ffffffffffffffffffffffffffffffffffffffff166116be909392919063ffffffff16565b60008973ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016109ab9190612685565b602060405180830381865afa1580156109c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109ec91906126b5565b9050600082826109fc9190612609565b9050858015610a0b5750808a14155b15610a42576040517f24f0dbb100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8084610a4e91906126e2565b60008087815260200190815260200160002060010181905550883373ffffffffffffffffffffffffffffffffffffffff16867fc3a4d207d43d9806cd211418ce2ac1c8e36f9903bfb9efe3f46ec1db1934c9be848f8b604051610ab393929190612716565b60405180910390a45050505050505050505050565b610ad785853386868633611740565b5050505050565b823373ffffffffffffffffffffffffffffffffffffffff1660008083815260200190815260200160002060040160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610bbb573360008083815260200190815260200160002060040160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166040517f4116c50f000000000000000000000000000000000000000000000000000000008152600401610bb29291906125b1565b60405180910390fd5b600080600086815260200190815260200160002090508060030160149054906101000a900460ff1615610c2557846040517fb13d20eb000000000000000000000000000000000000000000000000000000008152600401610c1c919061253b565b60405180910390fd5b60008160030160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401610c849190612685565b602060405180830381865afa158015610ca1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cc591906126b5565b9050610d183330878560030160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166116be909392919063ffffffff16565b60008260030160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401610d779190612685565b602060405180830381865afa158015610d94573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610db891906126b5565b905060008282610dc89190612609565b9050858015610dd75750808714155b15610e0e576040517f24f0dbb100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b808460010154610e1e91906126e2565b8460010181905550877ff10c3c897adc89dd38d281f3011b528a14643341a05d794201dd7045d40792d58560010154838760030160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168a604051610e84949392919061274d565b60405180910390a25050505050505050565b606060008383905067ffffffffffffffff811115610eb757610eb6612792565b5b604051908082528060200260200182016040528015610ee55781602001602082028036833780820191505090505b50905060005b84849050811015610f5d57610f2b60016000888152602001908152602001600020868684818110610f1f57610f1e6127c1565b5b905060200201356119bc565b828281518110610f3e57610f3d6127c1565b5b6020026020010190151590811515815250508080600101915050610eeb565b50809150509392505050565b853373ffffffffffffffffffffffffffffffffffffffff1660008083815260200190815260200160002060040160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611046573360008083815260200190815260200160002060040160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166040517f4116c50f00000000000000000000000000000000000000000000000000000000815260040161103d9291906125b1565b60405180910390fd5b6000806000898152602001908152602001600020905061108f8888888888888760040160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16611740565b5050505050505050565b85859050888890501415806110b45750838390508888905014155b806110c55750818190508888905014155b156110fc576040517ffc23596000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b88889050811015611194576111878989838181106111205761111f6127c1565b5b9050602002013588888481811061113a576111396127c1565b5b9050602002013533888886818110611155576111546127c1565b5b9050602002013587878781811061116f5761116e6127c1565b5b905060200281019061118191906127ff565b33611740565b80806001019150506110ff565b505050505050505050565b60025481565b803373ffffffffffffffffffffffffffffffffffffffff1660008083815260200190815260200160002060040160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611282573360008083815260200190815260200160002060040160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166040517f4116c50f0000000000000000000000000000000000000000000000000000000081526004016112799291906125b1565b60405180910390fd5b600080600084815260200190815260200160002090508060030160149054906101000a900460ff16156112ec57826040517fb13d20eb0000000000000000000000000000000000000000000000000000000081526004016112e3919061253b565b60405180910390fd5b8060040160159054906101000a900460ff161561134057826040517f642bd49b000000000000000000000000000000000000000000000000000000008152600401611337919061253b565b60405180910390fd5b8060040160149054906101000a900460ff161561139457826040517f6aa7a53c00000000000000000000000000000000000000000000000000000000815260040161138b919061253b565b60405180910390fd5b60018160030160146101000a81548160ff02191690831515021790555060018160040160146101000a81548160ff021916908315150217905550827f57393e4ee03ae6e27c99ac585130d8c60ee9bf27d14ee2e1652279adf187320860016040516113ff9190612596565b60405180910390a2505050565b600061142a60016000858152602001908152602001600020836119bc565b905092915050565b803373ffffffffffffffffffffffffffffffffffffffff1660008083815260200190815260200160002060040160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461150f573360008083815260200190815260200160002060040160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166040517f4116c50f0000000000000000000000000000000000000000000000000000000081526004016115069291906125b1565b60405180910390fd5b600080600084815260200190815260200160002090508060030160149054906101000a900460ff161561157957826040517fb13d20eb000000000000000000000000000000000000000000000000000000008152600401611570919061253b565b60405180910390fd5b60018160030160146101000a81548160ff0219169083151502179055506000816002015482600101546115ac9190612609565b90506116218260040160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16828460030160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166119f89092919063ffffffff16565b837f3b1542e3b68b50ef46ddf8fd60dc5f9eb6ce6c74985d6de7a0e6b19dd5b07581828460030160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16604051611677929190612862565b60405180910390a2837f57393e4ee03ae6e27c99ac585130d8c60ee9bf27d14ee2e1652279adf187320860016040516116b09190612596565b60405180910390a250505050565b61173a848573ffffffffffffffffffffffffffffffffffffffff166323b872dd8686866040516024016116f39392919061288b565b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050611a77565b50505050565b600080600089815260200190815260200160002090508060030160149054906101000a900460ff16156117aa57876040517fb13d20eb0000000000000000000000000000000000000000000000000000000081526004016117a1919061253b565b60405180910390fd5b6117b4888861140c565b156117f657856040517f146d3dc40000000000000000000000000000000000000000000000000000000081526004016117ed9190612685565b60405180910390fd5b6118108484836000015461180b8b8b8b611b0e565b611b6a565b611846576040517fb05e92fa00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000600160008a815260200190815260200160002090506118678189611b83565b85826002015461187791906126e2565b82600201819055508160010154826002015411156118d657816002015482600101546040517fc6dfccc50000000000000000000000000000000000000000000000000000000081526004016118cd9291906128c2565b60405180910390fd5b61192583878460030160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166119f89092919063ffffffff16565b8273ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff168a7f954c759088d05ae7f78a37be709eafdb540ce82e3fca292566570ee0bed29975898660030160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166040516119a9929190612862565b60405180910390a4505050505050505050565b600080600883901c9050600060ff84166001901b9050600081866000016000858152602001908152602001600020541614159250505092915050565b611a72838473ffffffffffffffffffffffffffffffffffffffff1663a9059cbb8585604051602401611a2b9291906128eb565b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050611a77565b505050565b6000611aa2828473ffffffffffffffffffffffffffffffffffffffff16611bc190919063ffffffff16565b90506000815114158015611ac7575080806020019051810190611ac59190612929565b155b15611b0957826040517f5274afe7000000000000000000000000000000000000000000000000000000008152600401611b009190612685565b60405180910390fd5b505050565b6000838383604051602001611b2593929190612956565b60405160208183030381529060405280519060200120604051602001611b4b91906129ae565b6040516020818303038152906040528051906020012090509392505050565b600082611b78868685611bd7565b149050949350505050565b6000600882901c9050600060ff83166001901b9050808460000160008481526020019081526020016000206000828254179250508190555050505050565b6060611bcf83836000611c29565b905092915050565b60008082905060005b85859050811015611c1d57611c0e82878784818110611c0257611c016127c1565b5b90506020020135611cf6565b91508080600101915050611be0565b50809150509392505050565b606081471015611c7057306040517fcd786059000000000000000000000000000000000000000000000000000000008152600401611c679190612685565b60405180910390fd5b6000808573ffffffffffffffffffffffffffffffffffffffff168486604051611c999190612a3a565b60006040518083038185875af1925050503d8060008114611cd6576040519150601f19603f3d011682016040523d82523d6000602084013e611cdb565b606091505b5091509150611ceb868383611d21565b925050509392505050565b6000818310611d0e57611d098284611db0565b611d19565b611d188383611db0565b5b905092915050565b606082611d3657611d3182611dc7565b611da8565b60008251148015611d5e575060008473ffffffffffffffffffffffffffffffffffffffff163b145b15611da057836040517f9996b315000000000000000000000000000000000000000000000000000000008152600401611d979190612685565b60405180910390fd5b819050611da9565b5b9392505050565b600082600052816020526040600020905092915050565b600081511115611dda5780518082602001fd5b6040517f1425ea4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080fd5b600080fd5b6000819050919050565b611e2981611e16565b8114611e3457600080fd5b50565b600081359050611e4681611e20565b92915050565b600060208284031215611e6257611e61611e0c565b5b6000611e7084828501611e37565b91505092915050565b6000819050919050565b611e8c81611e79565b82525050565b611e9b81611e16565b82525050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000611ecc82611ea1565b9050919050565b611edc81611ec1565b82525050565b60008115159050919050565b611ef781611ee2565b82525050565b600061010082019050611f13600083018b611e83565b611f20602083018a611e92565b611f2d6040830189611e92565b611f3a6060830188611ed3565b611f476080830187611eee565b611f5460a0830186611ed3565b611f6160c0830185611eee565b611f6e60e0830184611eee565b9998505050505050505050565b611f8481611ec1565b8114611f8f57600080fd5b50565b600081359050611fa181611f7b565b92915050565b611fb081611e79565b8114611fbb57600080fd5b50565b600081359050611fcd81611fa7565b92915050565b611fdc81611ee2565b8114611fe757600080fd5b50565b600081359050611ff981611fd3565b92915050565b60008060008060008060c0878903121561201c5761201b611e0c565b5b600061202a89828a01611f92565b965050602061203b89828a01611e37565b955050604061204c89828a01611fbe565b945050606061205d89828a01611fea565b935050608061206e89828a01611e37565b92505060a061207f89828a01611fea565b9150509295509295509295565b600080fd5b600080fd5b600080fd5b60008083601f8401126120b1576120b061208c565b5b8235905067ffffffffffffffff8111156120ce576120cd612091565b5b6020830191508360208202830111156120ea576120e9612096565b5b9250929050565b60008060008060006080868803121561210d5761210c611e0c565b5b600061211b88828901611e37565b955050602061212c88828901611e37565b945050604061213d88828901611e37565b935050606086013567ffffffffffffffff81111561215e5761215d611e11565b5b61216a8882890161209b565b92509250509295509295909350565b60008060006060848603121561219257612191611e0c565b5b60006121a086828701611e37565b93505060206121b186828701611e37565b92505060406121c286828701611fea565b9150509250925092565b60008083601f8401126121e2576121e161208c565b5b8235905067ffffffffffffffff8111156121ff576121fe612091565b5b60208301915083602082028301111561221b5761221a612096565b5b9250929050565b60008060006040848603121561223b5761223a611e0c565b5b600061224986828701611e37565b935050602084013567ffffffffffffffff81111561226a57612269611e11565b5b612276868287016121cc565b92509250509250925092565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6122b781611ee2565b82525050565b60006122c983836122ae565b60208301905092915050565b6000602082019050919050565b60006122ed82612282565b6122f7818561228d565b93506123028361229e565b8060005b8381101561233357815161231a88826122bd565b9750612325836122d5565b925050600181019050612306565b5085935050505092915050565b6000602082019050818103600083015261235a81846122e2565b905092915050565b60008060008060008060a0878903121561237f5761237e611e0c565b5b600061238d89828a01611e37565b965050602061239e89828a01611e37565b95505060406123af89828a01611f92565b94505060606123c089828a01611e37565b935050608087013567ffffffffffffffff8111156123e1576123e0611e11565b5b6123ed89828a0161209b565b92509250509295509295509295565b60008083601f8401126124125761241161208c565b5b8235905067ffffffffffffffff81111561242f5761242e612091565b5b60208301915083602082028301111561244b5761244a612096565b5b9250929050565b6000806000806000806000806080898b03121561247257612471611e0c565b5b600089013567ffffffffffffffff8111156124905761248f611e11565b5b61249c8b828c016121cc565b9850985050602089013567ffffffffffffffff8111156124bf576124be611e11565b5b6124cb8b828c016121cc565b9650965050604089013567ffffffffffffffff8111156124ee576124ed611e11565b5b6124fa8b828c016121cc565b9450945050606089013567ffffffffffffffff81111561251d5761251c611e11565b5b6125298b828c016123fc565b92509250509295985092959890939650565b60006020820190506125506000830184611e92565b92915050565b6000806040838503121561256d5761256c611e0c565b5b600061257b85828601611e37565b925050602061258c85828601611e37565b9150509250929050565b60006020820190506125ab6000830184611eee565b92915050565b60006040820190506125c66000830185611ed3565b6125d36020830184611ed3565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061261482611e16565b915061261f83611e16565b9250828203905081811115612637576126366125da565b5b92915050565b600061264882611e16565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361267a576126796125da565b5b600182019050919050565b600060208201905061269a6000830184611ed3565b92915050565b6000815190506126af81611e20565b92915050565b6000602082840312156126cb576126ca611e0c565b5b60006126d9848285016126a0565b91505092915050565b60006126ed82611e16565b91506126f883611e16565b92508282019050808211156127105761270f6125da565b5b92915050565b600060608201905061272b6000830186611e92565b6127386020830185611ed3565b6127456040830184611eee565b949350505050565b60006080820190506127626000830187611e92565b61276f6020830186611e92565b61277c6040830185611ed3565b6127896060830184611eee565b95945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600080fd5b600080fd5b600080fd5b6000808335600160200384360303811261281c5761281b6127f0565b5b80840192508235915067ffffffffffffffff82111561283e5761283d6127f5565b5b60208301925060208202360383131561285a576128596127fa565b5b509250929050565b60006040820190506128776000830185611e92565b6128846020830184611ed3565b9392505050565b60006060820190506128a06000830186611ed3565b6128ad6020830185611ed3565b6128ba6040830184611e92565b949350505050565b60006040820190506128d76000830185611e92565b6128e46020830184611e92565b9392505050565b60006040820190506129006000830185611ed3565b61290d6020830184611e92565b9392505050565b60008151905061292381611fd3565b92915050565b60006020828403121561293f5761293e611e0c565b5b600061294d84828501612914565b91505092915050565b600060608201905061296b6000830186611e92565b6129786020830185611ed3565b6129856040830184611e92565b949350505050565b6000819050919050565b6129a86129a382611e79565b61298d565b82525050565b60006129ba8284612997565b60208201915081905092915050565b600081519050919050565b600081905092915050565b60005b838110156129fd5780820151818401526020810190506129e2565b60008484015250505050565b6000612a14826129c9565b612a1e81856129d4565b9350612a2e8185602086016129df565b80840191505092915050565b6000612a468284612a09565b91508190509291505056fea26469706673582212202025ca4a21d3f84ef8b28a428454e994bcc4a68c6180062d62f26bdab4ac977b64736f6c63430008180033
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106100b45760003560e01c8063a823513d11610071578063a823513d14610190578063b15cb39c146101ac578063daafd1b6146101c8578063ec7239c9146101e6578063f364c90c14610202578063f6e213ef14610232576100b4565b80631078f946146100b95780634487d3df146100d55780635697d1d51461010c5780636117202e146101285780638df3a04314610144578063957d485d14610160575b600080fd5b6100d360048036038101906100ce9190611e4c565b61024e565b005b6100ef60048036038101906100ea9190611e4c565b6104b3565b604051610103989796959493929190611efd565b60405180910390f35b61012660048036038101906101219190611fff565b610562565b005b610142600480360381019061013d91906120f1565b610ac8565b005b61015e60048036038101906101599190612179565b610ade565b005b61017a60048036038101906101759190612222565b610e96565b6040516101879190612340565b60405180910390f35b6101aa60048036038101906101a59190612362565b610f69565b005b6101c660048036038101906101c19190612452565b611099565b005b6101d061119f565b6040516101dd919061253b565b60405180910390f35b61020060048036038101906101fb9190611e4c565b6111a5565b005b61021c60048036038101906102179190612556565b61140c565b6040516102299190612596565b60405180910390f35b61024c60048036038101906102479190611e4c565b611432565b005b803373ffffffffffffffffffffffffffffffffffffffff1660008083815260200190815260200160002060040160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461032b573360008083815260200190815260200160002060040160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166040517f4116c50f0000000000000000000000000000000000000000000000000000000081526004016103229291906125b1565b60405180910390fd5b600080600084815260200190815260200160002090508060030160149054906101000a900460ff1661039457826040517f8c0c84b000000000000000000000000000000000000000000000000000000000815260040161038b919061253b565b60405180910390fd5b8060040160159054906101000a900460ff16156103e857826040517f642bd49b0000000000000000000000000000000000000000000000000000000081526004016103df919061253b565b60405180910390fd5b8060040160149054906101000a900460ff1661043b57826040517f06b71ff6000000000000000000000000000000000000000000000000000000008152600401610432919061253b565b60405180910390fd5b60008160030160146101000a81548160ff02191690831515021790555060008160040160146101000a81548160ff021916908315150217905550827f57393e4ee03ae6e27c99ac585130d8c60ee9bf27d14ee2e1652279adf187320860006040516104a69190612596565b60405180910390a2505050565b60006020528060005260406000206000915090508060000154908060010154908060020154908060030160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060030160149054906101000a900460ff16908060040160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060040160149054906101000a900460ff16908060040160159054906101000a900460ff16905088565b60006002549050600084156107eb57600080600086815260200190815260200160002090508060040160159054906101000a900460ff16156105db57846040517f642bd49b0000000000000000000000000000000000000000000000000000000081526004016105d2919061253b565b60405180910390fd5b8060040160149054906101000a900460ff1661062e57846040517f06b71ff6000000000000000000000000000000000000000000000000000000008152600401610625919061253b565b60405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff168160040160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16146106e857338160040160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166040517f4116c50f0000000000000000000000000000000000000000000000000000000081526004016106df9291906125b1565b60405180910390fd5b8873ffffffffffffffffffffffffffffffffffffffff168160030160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610771576040517f936bb5ad00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60018160040160156101000a81548160ff021916908315150217905550806002015481600101546107a29190612609565b91503373ffffffffffffffffffffffffffffffffffffffff1683867ffd27571d31e4622ccb1eeb720cbabd67673e92690e750788fd3a0a857965514160405160405180910390a4505b600260008154809291906107fe9061263d565b919050555085600080848152602001908152602001600020600001819055508760008084815260200190815260200160002060030160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055503360008084815260200190815260200160002060040160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060008873ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016109009190612685565b602060405180830381865afa15801561091d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061094191906126b5565b905061097033308a8c73ffffffffffffffffffffffffffffffffffffffff166116be909392919063ffffffff16565b60008973ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b81526004016109ab9190612685565b602060405180830381865afa1580156109c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109ec91906126b5565b9050600082826109fc9190612609565b9050858015610a0b5750808a14155b15610a42576040517f24f0dbb100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8084610a4e91906126e2565b60008087815260200190815260200160002060010181905550883373ffffffffffffffffffffffffffffffffffffffff16867fc3a4d207d43d9806cd211418ce2ac1c8e36f9903bfb9efe3f46ec1db1934c9be848f8b604051610ab393929190612716565b60405180910390a45050505050505050505050565b610ad785853386868633611740565b5050505050565b823373ffffffffffffffffffffffffffffffffffffffff1660008083815260200190815260200160002060040160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610bbb573360008083815260200190815260200160002060040160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166040517f4116c50f000000000000000000000000000000000000000000000000000000008152600401610bb29291906125b1565b60405180910390fd5b600080600086815260200190815260200160002090508060030160149054906101000a900460ff1615610c2557846040517fb13d20eb000000000000000000000000000000000000000000000000000000008152600401610c1c919061253b565b60405180910390fd5b60008160030160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401610c849190612685565b602060405180830381865afa158015610ca1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cc591906126b5565b9050610d183330878560030160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166116be909392919063ffffffff16565b60008260030160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401610d779190612685565b602060405180830381865afa158015610d94573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610db891906126b5565b905060008282610dc89190612609565b9050858015610dd75750808714155b15610e0e576040517f24f0dbb100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b808460010154610e1e91906126e2565b8460010181905550877ff10c3c897adc89dd38d281f3011b528a14643341a05d794201dd7045d40792d58560010154838760030160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff168a604051610e84949392919061274d565b60405180910390a25050505050505050565b606060008383905067ffffffffffffffff811115610eb757610eb6612792565b5b604051908082528060200260200182016040528015610ee55781602001602082028036833780820191505090505b50905060005b84849050811015610f5d57610f2b60016000888152602001908152602001600020868684818110610f1f57610f1e6127c1565b5b905060200201356119bc565b828281518110610f3e57610f3d6127c1565b5b6020026020010190151590811515815250508080600101915050610eeb565b50809150509392505050565b853373ffffffffffffffffffffffffffffffffffffffff1660008083815260200190815260200160002060040160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611046573360008083815260200190815260200160002060040160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166040517f4116c50f00000000000000000000000000000000000000000000000000000000815260040161103d9291906125b1565b60405180910390fd5b6000806000898152602001908152602001600020905061108f8888888888888760040160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16611740565b5050505050505050565b85859050888890501415806110b45750838390508888905014155b806110c55750818190508888905014155b156110fc576040517ffc23596000000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60005b88889050811015611194576111878989838181106111205761111f6127c1565b5b9050602002013588888481811061113a576111396127c1565b5b9050602002013533888886818110611155576111546127c1565b5b9050602002013587878781811061116f5761116e6127c1565b5b905060200281019061118191906127ff565b33611740565b80806001019150506110ff565b505050505050505050565b60025481565b803373ffffffffffffffffffffffffffffffffffffffff1660008083815260200190815260200160002060040160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614611282573360008083815260200190815260200160002060040160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166040517f4116c50f0000000000000000000000000000000000000000000000000000000081526004016112799291906125b1565b60405180910390fd5b600080600084815260200190815260200160002090508060030160149054906101000a900460ff16156112ec57826040517fb13d20eb0000000000000000000000000000000000000000000000000000000081526004016112e3919061253b565b60405180910390fd5b8060040160159054906101000a900460ff161561134057826040517f642bd49b000000000000000000000000000000000000000000000000000000008152600401611337919061253b565b60405180910390fd5b8060040160149054906101000a900460ff161561139457826040517f6aa7a53c00000000000000000000000000000000000000000000000000000000815260040161138b919061253b565b60405180910390fd5b60018160030160146101000a81548160ff02191690831515021790555060018160040160146101000a81548160ff021916908315150217905550827f57393e4ee03ae6e27c99ac585130d8c60ee9bf27d14ee2e1652279adf187320860016040516113ff9190612596565b60405180910390a2505050565b600061142a60016000858152602001908152602001600020836119bc565b905092915050565b803373ffffffffffffffffffffffffffffffffffffffff1660008083815260200190815260200160002060040160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461150f573360008083815260200190815260200160002060040160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166040517f4116c50f0000000000000000000000000000000000000000000000000000000081526004016115069291906125b1565b60405180910390fd5b600080600084815260200190815260200160002090508060030160149054906101000a900460ff161561157957826040517fb13d20eb000000000000000000000000000000000000000000000000000000008152600401611570919061253b565b60405180910390fd5b60018160030160146101000a81548160ff0219169083151502179055506000816002015482600101546115ac9190612609565b90506116218260040160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16828460030160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166119f89092919063ffffffff16565b837f3b1542e3b68b50ef46ddf8fd60dc5f9eb6ce6c74985d6de7a0e6b19dd5b07581828460030160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16604051611677929190612862565b60405180910390a2837f57393e4ee03ae6e27c99ac585130d8c60ee9bf27d14ee2e1652279adf187320860016040516116b09190612596565b60405180910390a250505050565b61173a848573ffffffffffffffffffffffffffffffffffffffff166323b872dd8686866040516024016116f39392919061288b565b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050611a77565b50505050565b600080600089815260200190815260200160002090508060030160149054906101000a900460ff16156117aa57876040517fb13d20eb0000000000000000000000000000000000000000000000000000000081526004016117a1919061253b565b60405180910390fd5b6117b4888861140c565b156117f657856040517f146d3dc40000000000000000000000000000000000000000000000000000000081526004016117ed9190612685565b60405180910390fd5b6118108484836000015461180b8b8b8b611b0e565b611b6a565b611846576040517fb05e92fa00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000600160008a815260200190815260200160002090506118678189611b83565b85826002015461187791906126e2565b82600201819055508160010154826002015411156118d657816002015482600101546040517fc6dfccc50000000000000000000000000000000000000000000000000000000081526004016118cd9291906128c2565b60405180910390fd5b61192583878460030160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166119f89092919063ffffffff16565b8273ffffffffffffffffffffffffffffffffffffffff168773ffffffffffffffffffffffffffffffffffffffff168a7f954c759088d05ae7f78a37be709eafdb540ce82e3fca292566570ee0bed29975898660030160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166040516119a9929190612862565b60405180910390a4505050505050505050565b600080600883901c9050600060ff84166001901b9050600081866000016000858152602001908152602001600020541614159250505092915050565b611a72838473ffffffffffffffffffffffffffffffffffffffff1663a9059cbb8585604051602401611a2b9291906128eb565b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050611a77565b505050565b6000611aa2828473ffffffffffffffffffffffffffffffffffffffff16611bc190919063ffffffff16565b90506000815114158015611ac7575080806020019051810190611ac59190612929565b155b15611b0957826040517f5274afe7000000000000000000000000000000000000000000000000000000008152600401611b009190612685565b60405180910390fd5b505050565b6000838383604051602001611b2593929190612956565b60405160208183030381529060405280519060200120604051602001611b4b91906129ae565b6040516020818303038152906040528051906020012090509392505050565b600082611b78868685611bd7565b149050949350505050565b6000600882901c9050600060ff83166001901b9050808460000160008481526020019081526020016000206000828254179250508190555050505050565b6060611bcf83836000611c29565b905092915050565b60008082905060005b85859050811015611c1d57611c0e82878784818110611c0257611c016127c1565b5b90506020020135611cf6565b91508080600101915050611be0565b50809150509392505050565b606081471015611c7057306040517fcd786059000000000000000000000000000000000000000000000000000000008152600401611c679190612685565b60405180910390fd5b6000808573ffffffffffffffffffffffffffffffffffffffff168486604051611c999190612a3a565b60006040518083038185875af1925050503d8060008114611cd6576040519150601f19603f3d011682016040523d82523d6000602084013e611cdb565b606091505b5091509150611ceb868383611d21565b925050509392505050565b6000818310611d0e57611d098284611db0565b611d19565b611d188383611db0565b5b905092915050565b606082611d3657611d3182611dc7565b611da8565b60008251148015611d5e575060008473ffffffffffffffffffffffffffffffffffffffff163b145b15611da057836040517f9996b315000000000000000000000000000000000000000000000000000000008152600401611d979190612685565b60405180910390fd5b819050611da9565b5b9392505050565b600082600052816020526040600020905092915050565b600081511115611dda5780518082602001fd5b6040517f1425ea4200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600080fd5b600080fd5b6000819050919050565b611e2981611e16565b8114611e3457600080fd5b50565b600081359050611e4681611e20565b92915050565b600060208284031215611e6257611e61611e0c565b5b6000611e7084828501611e37565b91505092915050565b6000819050919050565b611e8c81611e79565b82525050565b611e9b81611e16565b82525050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000611ecc82611ea1565b9050919050565b611edc81611ec1565b82525050565b60008115159050919050565b611ef781611ee2565b82525050565b600061010082019050611f13600083018b611e83565b611f20602083018a611e92565b611f2d6040830189611e92565b611f3a6060830188611ed3565b611f476080830187611eee565b611f5460a0830186611ed3565b611f6160c0830185611eee565b611f6e60e0830184611eee565b9998505050505050505050565b611f8481611ec1565b8114611f8f57600080fd5b50565b600081359050611fa181611f7b565b92915050565b611fb081611e79565b8114611fbb57600080fd5b50565b600081359050611fcd81611fa7565b92915050565b611fdc81611ee2565b8114611fe757600080fd5b50565b600081359050611ff981611fd3565b92915050565b60008060008060008060c0878903121561201c5761201b611e0c565b5b600061202a89828a01611f92565b965050602061203b89828a01611e37565b955050604061204c89828a01611fbe565b945050606061205d89828a01611fea565b935050608061206e89828a01611e37565b92505060a061207f89828a01611fea565b9150509295509295509295565b600080fd5b600080fd5b600080fd5b60008083601f8401126120b1576120b061208c565b5b8235905067ffffffffffffffff8111156120ce576120cd612091565b5b6020830191508360208202830111156120ea576120e9612096565b5b9250929050565b60008060008060006080868803121561210d5761210c611e0c565b5b600061211b88828901611e37565b955050602061212c88828901611e37565b945050604061213d88828901611e37565b935050606086013567ffffffffffffffff81111561215e5761215d611e11565b5b61216a8882890161209b565b92509250509295509295909350565b60008060006060848603121561219257612191611e0c565b5b60006121a086828701611e37565b93505060206121b186828701611e37565b92505060406121c286828701611fea565b9150509250925092565b60008083601f8401126121e2576121e161208c565b5b8235905067ffffffffffffffff8111156121ff576121fe612091565b5b60208301915083602082028301111561221b5761221a612096565b5b9250929050565b60008060006040848603121561223b5761223a611e0c565b5b600061224986828701611e37565b935050602084013567ffffffffffffffff81111561226a57612269611e11565b5b612276868287016121cc565b92509250509250925092565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b6122b781611ee2565b82525050565b60006122c983836122ae565b60208301905092915050565b6000602082019050919050565b60006122ed82612282565b6122f7818561228d565b93506123028361229e565b8060005b8381101561233357815161231a88826122bd565b9750612325836122d5565b925050600181019050612306565b5085935050505092915050565b6000602082019050818103600083015261235a81846122e2565b905092915050565b60008060008060008060a0878903121561237f5761237e611e0c565b5b600061238d89828a01611e37565b965050602061239e89828a01611e37565b95505060406123af89828a01611f92565b94505060606123c089828a01611e37565b935050608087013567ffffffffffffffff8111156123e1576123e0611e11565b5b6123ed89828a0161209b565b92509250509295509295509295565b60008083601f8401126124125761241161208c565b5b8235905067ffffffffffffffff81111561242f5761242e612091565b5b60208301915083602082028301111561244b5761244a612096565b5b9250929050565b6000806000806000806000806080898b03121561247257612471611e0c565b5b600089013567ffffffffffffffff8111156124905761248f611e11565b5b61249c8b828c016121cc565b9850985050602089013567ffffffffffffffff8111156124bf576124be611e11565b5b6124cb8b828c016121cc565b9650965050604089013567ffffffffffffffff8111156124ee576124ed611e11565b5b6124fa8b828c016121cc565b9450945050606089013567ffffffffffffffff81111561251d5761251c611e11565b5b6125298b828c016123fc565b92509250509295985092959890939650565b60006020820190506125506000830184611e92565b92915050565b6000806040838503121561256d5761256c611e0c565b5b600061257b85828601611e37565b925050602061258c85828601611e37565b9150509250929050565b60006020820190506125ab6000830184611eee565b92915050565b60006040820190506125c66000830185611ed3565b6125d36020830184611ed3565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061261482611e16565b915061261f83611e16565b9250828203905081811115612637576126366125da565b5b92915050565b600061264882611e16565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361267a576126796125da565b5b600182019050919050565b600060208201905061269a6000830184611ed3565b92915050565b6000815190506126af81611e20565b92915050565b6000602082840312156126cb576126ca611e0c565b5b60006126d9848285016126a0565b91505092915050565b60006126ed82611e16565b91506126f883611e16565b92508282019050808211156127105761270f6125da565b5b92915050565b600060608201905061272b6000830186611e92565b6127386020830185611ed3565b6127456040830184611eee565b949350505050565b60006080820190506127626000830187611e92565b61276f6020830186611e92565b61277c6040830185611ed3565b6127896060830184611eee565b95945050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b600080fd5b600080fd5b600080fd5b6000808335600160200384360303811261281c5761281b6127f0565b5b80840192508235915067ffffffffffffffff82111561283e5761283d6127f5565b5b60208301925060208202360383131561285a576128596127fa565b5b509250929050565b60006040820190506128776000830185611e92565b6128846020830184611ed3565b9392505050565b60006060820190506128a06000830186611ed3565b6128ad6020830185611ed3565b6128ba6040830184611e92565b949350505050565b60006040820190506128d76000830185611e92565b6128e46020830184611e92565b9392505050565b60006040820190506129006000830185611ed3565b61290d6020830184611e92565b9392505050565b60008151905061292381611fd3565b92915050565b60006020828403121561293f5761293e611e0c565b5b600061294d84828501612914565b91505092915050565b600060608201905061296b6000830186611e92565b6129786020830185611ed3565b6129856040830184611e92565b949350505050565b6000819050919050565b6129a86129a382611e79565b61298d565b82525050565b60006129ba8284612997565b60208201915081905092915050565b600081519050919050565b600081905092915050565b60005b838110156129fd5780820151818401526020810190506129e2565b60008484015250505050565b6000612a14826129c9565b612a1e81856129d4565b9350612a2e8185602086016129df565b80840191505092915050565b6000612a468284612a09565b91508190509291505056fea26469706673582212202025ca4a21d3f84ef8b28a428454e994bcc4a68c6180062d62f26bdab4ac977b64736f6c63430008180033
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|---|---|---|---|---|
ETH | 61.37% | $0.194713 | 2,226,472.1098 | $433,523.06 | |
ETH | 14.51% | $0.007268 | 14,105,951.003 | $102,519.94 | |
ETH | 9.25% | $0.017132 | 3,812,033.0657 | $65,306.3 | |
ETH | 4.73% | $0.018727 | 1,785,950.0936 | $33,445.97 | |
ETH | 2.17% | $0.075557 | 202,894.6509 | $15,330.11 | |
ETH | 1.55% | $0.007649 | 1,429,029.2829 | $10,930.59 | |
ETH | 1.21% | $0.000063 | 135,725,000 | $8,535.09 | |
ETH | 1.03% | $0.046034 | 158,627.7727 | $7,302.23 | |
ETH | 0.96% | $0.048305 | 140,209.9637 | $6,772.78 | |
ETH | 0.76% | $0.121814 | 43,851.2501 | $5,341.7 | |
ETH | 0.55% | $1.97 | 1,968.9244 | $3,878.78 | |
ETH | 0.44% | $0.003034 | 1,029,037.3805 | $3,122.38 | |
ETH | 0.36% | $0.000897 | 2,875,121.7121 | $2,577.62 | |
ETH | 0.34% | $0.001431 | 1,672,538.485 | $2,393.16 | |
ETH | 0.23% | $0.906643 | 1,754.0763 | $1,590.32 | |
ETH | 0.22% | $0.105386 | 14,620.1983 | $1,540.76 | |
ETH | 0.19% | $0.178771 | 7,344 | $1,312.89 | |
ETH | 0.07% | $0.003794 | 131,876.4424 | $500.34 | |
ETH | 0.02% | $0.035659 | 4,300.998 | $153.37 | |
ETH | 0.02% | $0.115096 | 991.6604 | $114.14 | |
ETH | 0.01% | $0.006226 | 13,230 | $82.37 | |
ETH | <0.01% | $0.323953 | 166.2897 | $53.87 | |
ETH | <0.01% | $0.001548 | 10,400 | $16.09 | |
ETH | <0.01% | $0.999592 | 13.444 | $13.44 | |
ETH | <0.01% | $0.997733 | 0.9 | $0.8979 | |
ETH | <0.01% | $0.079808 | 1.8 | $0.1436 |
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.