ETH Price: $3,393.64 (-1.24%)
Gas: 2 Gwei

Contract

0xd7807E5752B368A6a64b76828Aaff0750522a76E
 

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Value
Claim201958362024-06-29 7:24:475 hrs ago1719645887IN
Redacted Cartel: Rewards Distributor
0 ETH0.000435182.60476493
Claim201951052024-06-29 4:57:597 hrs ago1719637079IN
Redacted Cartel: Rewards Distributor
0 ETH0.00027541.49533404
Claim201946642024-06-29 3:29:238 hrs ago1719631763IN
Redacted Cartel: Rewards Distributor
0 ETH0.00021361.62723694
Claim201941352024-06-29 1:42:4710 hrs ago1719625367IN
Redacted Cartel: Rewards Distributor
0 ETH0.000210151.58152747
Claim201935292024-06-28 23:40:3512 hrs ago1719618035IN
Redacted Cartel: Rewards Distributor
0 ETH0.000209171.80675227
Claim201935032024-06-28 23:35:1112 hrs ago1719617711IN
Redacted Cartel: Rewards Distributor
0 ETH0.000242152.09127222
Claim201934952024-06-28 23:33:3512 hrs ago1719617615IN
Redacted Cartel: Rewards Distributor
0 ETH0.00023381.57598097
Claim201933352024-06-28 23:01:3513 hrs ago1719615695IN
Redacted Cartel: Rewards Distributor
0 ETH0.000258361.9449649
Claim201930562024-06-28 22:05:2314 hrs ago1719612323IN
Redacted Cartel: Rewards Distributor
0 ETH0.000405313.05081126
Claim201930072024-06-28 21:55:3514 hrs ago1719611735IN
Redacted Cartel: Rewards Distributor
0 ETH0.000157941.81722604
Claim201926652024-06-28 20:46:4715 hrs ago1719607607IN
Redacted Cartel: Rewards Distributor
0 ETH0.000406073.05560102
Claim201920762024-06-28 18:48:3517 hrs ago1719600515IN
Redacted Cartel: Rewards Distributor
0 ETH0.000468893.57134155
Claim201919672024-06-28 18:26:4717 hrs ago1719599207IN
Redacted Cartel: Rewards Distributor
0 ETH0.000557124.24576202
Claim201918732024-06-28 18:07:4718 hrs ago1719598067IN
Redacted Cartel: Rewards Distributor
0 ETH0.000867437.49054345
Claim201907592024-06-28 14:23:2322 hrs ago1719584603IN
Redacted Cartel: Rewards Distributor
0 ETH0.001038927.81955696
Claim201906662024-06-28 14:04:4722 hrs ago1719583487IN
Redacted Cartel: Rewards Distributor
0 ETH0.00122838.19079837
Claim201901582024-06-28 12:22:5924 hrs ago1719577379IN
Redacted Cartel: Rewards Distributor
0 ETH0.000877655.25306822
Claim201900682024-06-28 12:04:5924 hrs ago1719576299IN
Redacted Cartel: Rewards Distributor
0 ETH0.000324333.73104044
Claim201897832024-06-28 11:07:3525 hrs ago1719572855IN
Redacted Cartel: Rewards Distributor
0 ETH0.000632114.7564881
Claim201897162024-06-28 10:53:5925 hrs ago1719572039IN
Redacted Cartel: Rewards Distributor
0 ETH0.000925967.05164483
Claim201892532024-06-28 9:21:1127 hrs ago1719566471IN
Redacted Cartel: Rewards Distributor
0 ETH0.000486073.65816579
Claim201889122024-06-28 8:12:4728 hrs ago1719562367IN
Redacted Cartel: Rewards Distributor
0 ETH0.000154493.00434686
Claim201889122024-06-28 8:12:4728 hrs ago1719562367IN
Redacted Cartel: Rewards Distributor
0 ETH0.000312593.00434686
Claim201887232024-06-28 7:34:4728 hrs ago1719560087IN
Redacted Cartel: Rewards Distributor
0 ETH0.000603684.54369727
Claim201885332024-06-28 6:56:3529 hrs ago1719557795IN
Redacted Cartel: Rewards Distributor
0 ETH0.000380712.86521575
View all transactions

Latest 25 internal transactions (View All)

Advanced mode:
Parent Transaction Hash Block From To Value
201898302024-06-28 11:17:1125 hrs ago1719573431
Redacted Cartel: Rewards Distributor
0.00046696 ETH
201814172024-06-27 7:05:112 days ago1719471911
Redacted Cartel: Rewards Distributor
0.00061697 ETH
201673972024-06-25 8:07:114 days ago1719302831
Redacted Cartel: Rewards Distributor
0.0012886 ETH
201608522024-06-24 10:09:355 days ago1719223775
Redacted Cartel: Rewards Distributor
0.00124599 ETH
201601892024-06-24 7:55:355 days ago1719215735
Redacted Cartel: Rewards Distributor
0.00267884 ETH
201551752024-06-23 15:06:355 days ago1719155195
Redacted Cartel: Rewards Distributor
0.00534841 ETH
201537362024-06-23 10:17:116 days ago1719137831
Redacted Cartel: Rewards Distributor
0.00064546 ETH
201496692024-06-22 20:36:476 days ago1719088607
Redacted Cartel: Rewards Distributor
0.00020417 ETH
201472792024-06-22 12:35:116 days ago1719059711
Redacted Cartel: Rewards Distributor
0.03083685 ETH
201455842024-06-22 6:54:117 days ago1719039251
Redacted Cartel: Rewards Distributor
0.00121854 ETH
201452862024-06-22 5:54:117 days ago1719035651
Redacted Cartel: Rewards Distributor
0.00491599 ETH
201398842024-06-21 11:45:358 days ago1718970335
Redacted Cartel: Rewards Distributor
0.00069739 ETH
201398152024-06-21 11:31:358 days ago1718969495
Redacted Cartel: Rewards Distributor
0.00525423 ETH
201384592024-06-21 6:59:478 days ago1718953187
Redacted Cartel: Rewards Distributor
0.00096849 ETH
201351162024-06-20 19:47:118 days ago1718912831
Redacted Cartel: Rewards Distributor
0.00069749 ETH
201351012024-06-20 19:44:118 days ago1718912651
Redacted Cartel: Rewards Distributor
0.00186902 ETH
201289802024-06-19 23:10:479 days ago1718838647
Redacted Cartel: Rewards Distributor
0.00060362 ETH
201280082024-06-19 19:55:119 days ago1718826911
Redacted Cartel: Rewards Distributor
0.00197144 ETH
201138562024-06-17 20:21:4711 days ago1718655707
Redacted Cartel: Rewards Distributor
0.00511447 ETH
201037802024-06-16 10:33:1113 days ago1718533991
Redacted Cartel: Rewards Distributor
0.01484655 ETH
201010402024-06-16 1:22:5913 days ago1718500979
Redacted Cartel: Rewards Distributor
0.00131696 ETH
200993562024-06-15 19:42:5913 days ago1718480579
Redacted Cartel: Rewards Distributor
0.0001504 ETH
200992602024-06-15 19:23:4713 days ago1718479427
Redacted Cartel: Rewards Distributor
0.00043156 ETH
200925292024-06-14 20:47:1114 days ago1718398031
Redacted Cartel: Rewards Distributor
0.00841131 ETH
200814572024-06-13 7:36:5916 days ago1718264219
Redacted Cartel: Rewards Distributor
0.00276699 ETH
View All Internal Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
RewardDistributor

Compiler Version
v0.8.12+commit.f00d7308

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, MIT license
/**
 *Submitted for verification at Etherscan.io on 2022-08-08
*/

/**
 *Submitted for verification at Etherscan.io on 2022-07-27
*/

// Sources flattened with hardhat v2.9.2 https://hardhat.org

// File @openzeppelin/contracts/utils/[email protected]


// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)



/**
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }
}


// File @openzeppelin/contracts/access/[email protected]


// OpenZeppelin Contracts v4.4.1 (access/Ownable.sol)



/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * By default, the owner account will be the one that deploys the contract. This
 * can later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
abstract contract Ownable is Context {
    address private _owner;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    constructor() {
        _transferOwnership(_msgSender());
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
        _;
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions anymore. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby removing any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        _transferOwnership(address(0));
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        _transferOwnership(newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}


// File @rari-capital/solmate/src/utils/[email protected]


pragma solidity >=0.8.0;

/// @notice Gas optimized reentrancy protection for smart contracts.
/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/utils/ReentrancyGuard.sol)
/// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/security/ReentrancyGuard.sol)
abstract contract ReentrancyGuard {
    uint256 private reentrancyStatus = 1;

    modifier nonReentrant() {
        require(reentrancyStatus == 1, "REENTRANCY");

        reentrancyStatus = 2;

        _;

        reentrancyStatus = 1;
    }
}


// File @rari-capital/solmate/src/tokens/[email protected]


pragma solidity >=0.8.0;

/// @notice Modern and gas efficient ERC20 + EIP-2612 implementation.
/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/tokens/ERC20.sol)
/// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol)
/// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it.
abstract contract ERC20 {
    /*///////////////////////////////////////////////////////////////
                                  EVENTS
    //////////////////////////////////////////////////////////////*/

    event Transfer(address indexed from, address indexed to, uint256 amount);

    event Approval(address indexed owner, address indexed spender, uint256 amount);

    /*///////////////////////////////////////////////////////////////
                             METADATA STORAGE
    //////////////////////////////////////////////////////////////*/

    string public name;

    string public symbol;

    uint8 public immutable decimals;

    /*///////////////////////////////////////////////////////////////
                              ERC20 STORAGE
    //////////////////////////////////////////////////////////////*/

    uint256 public totalSupply;

    mapping(address => uint256) public balanceOf;

    mapping(address => mapping(address => uint256)) public allowance;

    /*///////////////////////////////////////////////////////////////
                             EIP-2612 STORAGE
    //////////////////////////////////////////////////////////////*/

    bytes32 public constant PERMIT_TYPEHASH =
        keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");

    uint256 internal immutable INITIAL_CHAIN_ID;

    bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR;

    mapping(address => uint256) public nonces;

    /*///////////////////////////////////////////////////////////////
                               CONSTRUCTOR
    //////////////////////////////////////////////////////////////*/

    constructor(
        string memory _name,
        string memory _symbol,
        uint8 _decimals
    ) {
        name = _name;
        symbol = _symbol;
        decimals = _decimals;

        INITIAL_CHAIN_ID = block.chainid;
        INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator();
    }

    /*///////////////////////////////////////////////////////////////
                              ERC20 LOGIC
    //////////////////////////////////////////////////////////////*/

    function approve(address spender, uint256 amount) public virtual returns (bool) {
        allowance[msg.sender][spender] = amount;

        emit Approval(msg.sender, spender, amount);

        return true;
    }

    function transfer(address to, uint256 amount) public virtual returns (bool) {
        balanceOf[msg.sender] -= amount;

        // Cannot overflow because the sum of all user
        // balances can't exceed the max uint256 value.
        unchecked {
            balanceOf[to] += amount;
        }

        emit Transfer(msg.sender, to, amount);

        return true;
    }

    function transferFrom(
        address from,
        address to,
        uint256 amount
    ) public virtual returns (bool) {
        uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals.

        if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount;

        balanceOf[from] -= amount;

        // Cannot overflow because the sum of all user
        // balances can't exceed the max uint256 value.
        unchecked {
            balanceOf[to] += amount;
        }

        emit Transfer(from, to, amount);

        return true;
    }

    /*///////////////////////////////////////////////////////////////
                              EIP-2612 LOGIC
    //////////////////////////////////////////////////////////////*/

    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) public virtual {
        require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED");

        // Unchecked because the only math done is incrementing
        // the owner's nonce which cannot realistically overflow.
        unchecked {
            bytes32 digest = keccak256(
                abi.encodePacked(
                    "\x19\x01",
                    DOMAIN_SEPARATOR(),
                    keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, value, nonces[owner]++, deadline))
                )
            );

            address recoveredAddress = ecrecover(digest, v, r, s);

            require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER");

            allowance[recoveredAddress][spender] = value;
        }

        emit Approval(owner, spender, value);
    }

    function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {
        return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator();
    }

    function computeDomainSeparator() internal view virtual returns (bytes32) {
        return
            keccak256(
                abi.encode(
                    keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"),
                    keccak256(bytes(name)),
                    keccak256("1"),
                    block.chainid,
                    address(this)
                )
            );
    }

    /*///////////////////////////////////////////////////////////////
                       INTERNAL MINT/BURN LOGIC
    //////////////////////////////////////////////////////////////*/

    function _mint(address to, uint256 amount) internal virtual {
        totalSupply += amount;

        // Cannot overflow because the sum of all user
        // balances can't exceed the max uint256 value.
        unchecked {
            balanceOf[to] += amount;
        }

        emit Transfer(address(0), to, amount);
    }

    function _burn(address from, uint256 amount) internal virtual {
        balanceOf[from] -= amount;

        // Cannot underflow because a user's balance
        // will never be larger than the total supply.
        unchecked {
            totalSupply -= amount;
        }

        emit Transfer(from, address(0), amount);
    }
}


// File @rari-capital/solmate/src/utils/[email protected]


pragma solidity >=0.8.0;

/// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values.
/// @author Solmate (https://github.com/Rari-Capital/solmate/blob/main/src/utils/SafeTransferLib.sol)
/// @author Modified from Gnosis (https://github.com/gnosis/gp-v2-contracts/blob/main/src/contracts/libraries/GPv2SafeERC20.sol)
/// @dev Use with caution! Some functions in this library knowingly create dirty bits at the destination of the free memory pointer.
library SafeTransferLib {
    /*///////////////////////////////////////////////////////////////
                            ETH OPERATIONS
    //////////////////////////////////////////////////////////////*/

    function safeTransferETH(address to, uint256 amount) internal {
        bool callStatus;

        assembly {
            // Transfer the ETH and store if it succeeded or not.
            callStatus := call(gas(), to, amount, 0, 0, 0, 0)
        }

        require(callStatus, "ETH_TRANSFER_FAILED");
    }

    /*///////////////////////////////////////////////////////////////
                           ERC20 OPERATIONS
    //////////////////////////////////////////////////////////////*/

    function safeTransferFrom(
        ERC20 token,
        address from,
        address to,
        uint256 amount
    ) internal {
        bool callStatus;

        assembly {
            // Get a pointer to some free memory.
            let freeMemoryPointer := mload(0x40)

            // Write the abi-encoded calldata to memory piece by piece:
            mstore(freeMemoryPointer, 0x23b872dd00000000000000000000000000000000000000000000000000000000) // Begin with the function selector.
            mstore(add(freeMemoryPointer, 4), and(from, 0xffffffffffffffffffffffffffffffffffffffff)) // Mask and append the "from" argument.
            mstore(add(freeMemoryPointer, 36), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Mask and append the "to" argument.
            mstore(add(freeMemoryPointer, 68), amount) // Finally append the "amount" argument. No mask as it's a full 32 byte value.

            // Call the token and store if it succeeded or not.
            // We use 100 because the calldata length is 4 + 32 * 3.
            callStatus := call(gas(), token, 0, freeMemoryPointer, 100, 0, 0)
        }

        require(didLastOptionalReturnCallSucceed(callStatus), "TRANSFER_FROM_FAILED");
    }

    function safeTransfer(
        ERC20 token,
        address to,
        uint256 amount
    ) internal {
        bool callStatus;

        assembly {
            // Get a pointer to some free memory.
            let freeMemoryPointer := mload(0x40)

            // Write the abi-encoded calldata to memory piece by piece:
            mstore(freeMemoryPointer, 0xa9059cbb00000000000000000000000000000000000000000000000000000000) // Begin with the function selector.
            mstore(add(freeMemoryPointer, 4), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Mask and append the "to" argument.
            mstore(add(freeMemoryPointer, 36), amount) // Finally append the "amount" argument. No mask as it's a full 32 byte value.

            // Call the token and store if it succeeded or not.
            // We use 68 because the calldata length is 4 + 32 * 2.
            callStatus := call(gas(), token, 0, freeMemoryPointer, 68, 0, 0)
        }

        require(didLastOptionalReturnCallSucceed(callStatus), "TRANSFER_FAILED");
    }

    function safeApprove(
        ERC20 token,
        address to,
        uint256 amount
    ) internal {
        bool callStatus;

        assembly {
            // Get a pointer to some free memory.
            let freeMemoryPointer := mload(0x40)

            // Write the abi-encoded calldata to memory piece by piece:
            mstore(freeMemoryPointer, 0x095ea7b300000000000000000000000000000000000000000000000000000000) // Begin with the function selector.
            mstore(add(freeMemoryPointer, 4), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Mask and append the "to" argument.
            mstore(add(freeMemoryPointer, 36), amount) // Finally append the "amount" argument. No mask as it's a full 32 byte value.

            // Call the token and store if it succeeded or not.
            // We use 68 because the calldata length is 4 + 32 * 2.
            callStatus := call(gas(), token, 0, freeMemoryPointer, 68, 0, 0)
        }

        require(didLastOptionalReturnCallSucceed(callStatus), "APPROVE_FAILED");
    }

    /*///////////////////////////////////////////////////////////////
                         INTERNAL HELPER LOGIC
    //////////////////////////////////////////////////////////////*/

    function didLastOptionalReturnCallSucceed(bool callStatus) private pure returns (bool success) {
        assembly {
            // Get how many bytes the call returned.
            let returnDataSize := returndatasize()

            // If the call reverted:
            if iszero(callStatus) {
                // Copy the revert message into memory.
                returndatacopy(0, 0, returnDataSize)

                // Revert with the same message.
                revert(0, returnDataSize)
            }

            switch returnDataSize
            case 32 {
                // Copy the return data into memory.
                returndatacopy(0, 0, returnDataSize)

                // Set success to whether it returned true.
                success := iszero(iszero(mload(0)))
            }
            case 0 {
                // There was no return data.
                success := 1
            }
            default {
                // It returned some malformed input.
                success := 0
            }
        }
    }
}


// File @openzeppelin/contracts/utils/cryptography/[email protected]


// OpenZeppelin Contracts (last updated v4.5.0) (utils/cryptography/MerkleProof.sol)



/**
 * @dev These functions deal with verification of Merkle Trees proofs.
 *
 * The proofs can be generated using the JavaScript library
 * https://github.com/miguelmota/merkletreejs[merkletreejs].
 * Note: the hashing algorithm should be keccak256 and pair sorting should be enabled.
 *
 * See `test/utils/cryptography/MerkleProof.test.js` for some examples.
 */
library MerkleProof {
    /**
     * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree
     * defined by `root`. For this, a `proof` must be provided, containing
     * sibling hashes on the branch from the leaf to the root of the tree. Each
     * pair of leaves and each pair of pre-images are assumed to be sorted.
     */
    function verify(
        bytes32[] memory proof,
        bytes32 root,
        bytes32 leaf
    ) internal pure returns (bool) {
        return processProof(proof, leaf) == root;
    }

    /**
     * @dev Returns the rebuilt hash obtained by traversing a Merklee tree up
     * from `leaf` using `proof`. A `proof` is valid if and only if the rebuilt
     * hash matches the root of the tree. When processing the proof, the pairs
     * of leafs & pre-images are assumed to be sorted.
     *
     * _Available since v4.4._
     */
    function processProof(bytes32[] memory proof, bytes32 leaf) internal pure returns (bytes32) {
        bytes32 computedHash = leaf;
        for (uint256 i = 0; i < proof.length; i++) {
            bytes32 proofElement = proof[i];
            if (computedHash <= proofElement) {
                // Hash(current computed hash + current element of the proof)
                computedHash = _efficientHash(computedHash, proofElement);
            } else {
                // Hash(current element of the proof + current computed hash)
                computedHash = _efficientHash(proofElement, computedHash);
            }
        }
        return computedHash;
    }

    function _efficientHash(bytes32 a, bytes32 b) private pure returns (bytes32 value) {
        assembly {
            mstore(0x00, a)
            mstore(0x20, b)
            value := keccak256(0x00, 0x40)
        }
    }
}


// File contracts/core/RewardDistributor.sol

// SPDX-License-Identifier: MIT
pragma solidity 0.8.12;





/// @title RewardDistributor
/// @author ████

/**
    @notice
    Adapted from Hidden-Hand's RewardDistributor
*/

contract RewardDistributor is Ownable, ReentrancyGuard {
    using SafeTransferLib for ERC20;

    struct Distribution {
        address token;
        bytes32 merkleRoot;
        bytes32 proof;
    }

    struct Reward {
        address token;
        bytes32 merkleRoot;
        bytes32 proof;
        uint256 updateCount;
    }

    struct Claim {
        address token;
        address account;
        uint256 amount;
        bytes32[] merkleProof;
    }

    // Address of the Multisig (also as the primary source of rewards)
    address public immutable MULTISIG;

    // Maps each of the token address to its reward metadata
    mapping(address => Reward) public rewards;
    // Tracks the amount of claimed reward for the specified token address + account
    mapping(address => mapping(address => uint256)) public claimed;

    event RewardClaimed(
        address indexed token,
        address indexed account,
        uint256 amount,
        uint256 updateCount
    );

    event RewardMetadataUpdated(
        address indexed token,
        bytes32 merkleRoot,
        bytes32 proof,
        uint256 indexed updateCount
    );

    constructor(address multisig) {
        require(multisig != address(0), "Invalid address");
        MULTISIG = multisig;
    }

    /**
        @notice Enables and restricts native token ingress to Multisig
     */
    receive() external payable {
        if (msg.sender != MULTISIG) revert("Not MULTISIG");
    }

    /**
        @notice Claim rewards based on the specified metadata
        @param  claims  Claim[] List of claim metadata
     */
    function claim(Claim[] calldata claims) external nonReentrant {
        require(claims.length != 0, "Invalid claims");

        for (uint256 i; i < claims.length; ++i) {
            _claim(
                claims[i].token,
                claims[i].account,
                claims[i].amount,
                claims[i].merkleProof
            );
        }
    }

    /**
        @notice Update rewards metadata
        @param  distributions  Distribution[] List of reward distribution details
     */
    function updateRewardsMetadata(Distribution[] calldata distributions)
        external
        onlyOwner
    {
        require(distributions.length != 0, "Invalid distributions");

        for (uint256 i; i < distributions.length; ++i) {
            // Update the metadata and also increment the update counter
            Distribution calldata distribution = distributions[i];
            Reward storage reward = rewards[distribution.token];
            reward.token = distribution.token;
            reward.merkleRoot = distribution.merkleRoot;
            reward.proof = distribution.proof;
            ++reward.updateCount;

            emit RewardMetadataUpdated(
                distribution.token,
                distribution.merkleRoot,
                distribution.proof,
                reward.updateCount
            );
        }
    }

    /**
        @notice Claim a reward
        @param  token        address    Token address
        @param  account      address    Eligible user account
        @param  amount       uint256    Reward amount
        @param  merkleProof  bytes32[]  Merkle proof
     */
    function _claim(
        address token,
        address account,
        uint256 amount,
        bytes32[] calldata merkleProof
    ) private {
        Reward memory reward = rewards[token];

        require(reward.merkleRoot != 0, "Distribution not enabled");

        // Verify the merkle proof
        require(
            MerkleProof.verify(
                merkleProof,
                reward.merkleRoot,
                keccak256(abi.encodePacked(account, amount))
            ),
            "Invalid proof"
        );

        // Verify the claimable amount
        require(claimed[token][account] < amount, "No claimable reward");

        // Calculate the claimable amount based off the total of reward (used in the merkle tree)
        // since the beginning for the user, minus the total claimed so far
        uint256 claimable = amount - claimed[token][account];
        // Update the claimed amount to the current total
        claimed[token][account] = amount;

        // Check whether the reward is in the form of native tokens or ERC20
        // by checking if the token address is set to the Multisig or not
        if (token != MULTISIG) {
            ERC20(token).safeTransfer(account, claimable);
        } else {
            (bool sent, ) = payable(account).call{value: claimable}("");
            require(sent, "Failed to transfer to account");
        }

        emit RewardClaimed(
            token,
            account,
            claimable,
            reward.updateCount
        );
    }
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"multisig","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"updateCount","type":"uint256"}],"name":"RewardClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"bytes32","name":"merkleRoot","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"proof","type":"bytes32"},{"indexed":true,"internalType":"uint256","name":"updateCount","type":"uint256"}],"name":"RewardMetadataUpdated","type":"event"},{"inputs":[],"name":"MULTISIG","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes32[]","name":"merkleProof","type":"bytes32[]"}],"internalType":"struct RewardDistributor.Claim[]","name":"claims","type":"tuple[]"}],"name":"claim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"claimed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"rewards","outputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"bytes32","name":"merkleRoot","type":"bytes32"},{"internalType":"bytes32","name":"proof","type":"bytes32"},{"internalType":"uint256","name":"updateCount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"bytes32","name":"merkleRoot","type":"bytes32"},{"internalType":"bytes32","name":"proof","type":"bytes32"}],"internalType":"struct RewardDistributor.Distribution[]","name":"distributions","type":"tuple[]"}],"name":"updateRewardsMetadata","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]

60a06040526001805534801561001457600080fd5b50604051610f34380380610f34833981016040819052610033916100e9565b61003c33610099565b6001600160a01b0381166100885760405162461bcd60e51b815260206004820152600f60248201526e496e76616c6964206164647265737360881b604482015260640160405180910390fd5b6001600160a01b0316608052610119565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000602082840312156100fb57600080fd5b81516001600160a01b038116811461011257600080fd5b9392505050565b608051610df361014160003960008181608f015281816101cc015261088a0152610df36000f3fe60806040526004361061007f5760003560e01c8063715018a61161004e578063715018a6146102265780638da5cb5b1461023b57806396e859d814610259578063f2fde38b1461027957600080fd5b80630700037d146100f75780630c9cbf0e146101745780632530b145146101ba578063486866261461020657600080fd5b366100f257336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146100f05760405162461bcd60e51b815260206004820152600c60248201526b4e6f74204d554c544953494760a01b60448201526064015b60405180910390fd5b005b600080fd5b34801561010357600080fd5b50610145610112366004610b8c565b600260208190526000918252604090912080546001820154928201546003909201546001600160a01b0390911692919084565b604080516001600160a01b03909516855260208501939093529183015260608201526080015b60405180910390f35b34801561018057600080fd5b506101ac61018f366004610bae565b600360209081526000928352604080842090915290825290205481565b60405190815260200161016b565b3480156101c657600080fd5b506101ee7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b03909116815260200161016b565b34801561021257600080fd5b506100f0610221366004610be1565b610299565b34801561023257600080fd5b506100f0610408565b34801561024757600080fd5b506000546001600160a01b03166101ee565b34801561026557600080fd5b506100f0610274366004610c56565b61043e565b34801561028557600080fd5b506100f0610294366004610b8c565b6105d2565b6001546001146102d85760405162461bcd60e51b815260206004820152600a6024820152695245454e5452414e435960b01b60448201526064016100e7565b60026001558061031b5760405162461bcd60e51b815260206004820152600e60248201526d496e76616c696420636c61696d7360901b60448201526064016100e7565b60005b818110156103ff576103ef83838381811061033b5761033b610cb9565b905060200281019061034d9190610ccf565b61035b906020810190610b8c565b84848481811061036d5761036d610cb9565b905060200281019061037f9190610ccf565b610390906040810190602001610b8c565b8585858181106103a2576103a2610cb9565b90506020028101906103b49190610ccf565b604001358686868181106103ca576103ca610cb9565b90506020028101906103dc9190610ccf565b6103ea906060810190610cef565b61066d565b6103f881610d56565b905061031e565b50506001805550565b6000546001600160a01b031633146104325760405162461bcd60e51b81526004016100e790610d71565b61043c60006109d0565b565b6000546001600160a01b031633146104685760405162461bcd60e51b81526004016100e790610d71565b806104ad5760405162461bcd60e51b8152602060048201526015602482015274496e76616c696420646973747269627574696f6e7360581b60448201526064016100e7565b60005b818110156105cd57368383838181106104cb576104cb610cb9565b606002919091019150600090506002816104e86020850185610b8c565b6001600160a01b03168152602080820192909252604001600020915061051090830183610b8c565b81546001600160a01b0319166001600160a01b0391909116178155602082013560018201556040820135600282015560038101805460009061055190610d56565b9091555060038101546105676020840184610b8c565b6001600160a01b03167f9ca93988e299d8264919a188c320f8d8efa97e1976a234f3c6c42315fc10b4e0846020013585604001356040516105b2929190918252602082015260400190565b60405180910390a35050806105c690610d56565b90506104b0565b505050565b6000546001600160a01b031633146105fc5760405162461bcd60e51b81526004016100e790610d71565b6001600160a01b0381166106615760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016100e7565b61066a816109d0565b50565b6001600160a01b03808616600090815260026020818152604092839020835160808101855281549095168552600181015491850182905291820154928401929092526003015460608301526107045760405162461bcd60e51b815260206004820152601860248201527f446973747269627574696f6e206e6f7420656e61626c6564000000000000000060448201526064016100e7565b6107848383808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152505050506020838101516040516bffffffffffffffffffffffff1960608b901b1692810192909252603482018890529060540160405160208183030381529060405280519060200120610a20565b6107c05760405162461bcd60e51b815260206004820152600d60248201526c24b73b30b634b210383937b7b360991b60448201526064016100e7565b6001600160a01b03808716600090815260036020908152604080832093891683529290522054841161082a5760405162461bcd60e51b8152602060048201526013602482015272139bc818db185a5b58589b19481c995dd85c99606a1b60448201526064016100e7565b6001600160a01b03808716600090815260036020908152604080832093891683529290529081205461085c9086610da6565b6001600160a01b0380891660008181526003602090815260408083208c8616845290915290208890559192507f000000000000000000000000000000000000000000000000000000000000000016146108c8576108c36001600160a01b0388168783610a36565b61096d565b6000866001600160a01b03168260405160006040518083038185875af1925050503d8060008114610915576040519150601f19603f3d011682016040523d82523d6000602084013e61091a565b606091505b505090508061096b5760405162461bcd60e51b815260206004820152601d60248201527f4661696c656420746f207472616e7366657220746f206163636f756e7400000060448201526064016100e7565b505b856001600160a01b0316876001600160a01b03167f7a84a08b02c91f3c62d572853f966fc799bbd121e8ad7833a4494ab8dcfcb4048385606001516040516109bf929190918252602082015260400190565b60405180910390a350505050505050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600082610a2d8584610ab5565b14949350505050565b600060405163a9059cbb60e01b81526001600160a01b03841660048201528260248201526000806044836000895af1915050610a7181610b29565b610aaf5760405162461bcd60e51b815260206004820152600f60248201526e1514905394d1915497d19052531151608a1b60448201526064016100e7565b50505050565b600081815b8451811015610b21576000858281518110610ad757610ad7610cb9565b60200260200101519050808311610afd5760008381526020829052604090209250610b0e565b600081815260208490526040902092505b5080610b1981610d56565b915050610aba565b509392505050565b60003d82610b3b57806000803e806000fd5b8060208114610b53578015610b645760009250610b69565b816000803e60005115159250610b69565b600192505b5050919050565b80356001600160a01b0381168114610b8757600080fd5b919050565b600060208284031215610b9e57600080fd5b610ba782610b70565b9392505050565b60008060408385031215610bc157600080fd5b610bca83610b70565b9150610bd860208401610b70565b90509250929050565b60008060208385031215610bf457600080fd5b823567ffffffffffffffff80821115610c0c57600080fd5b818501915085601f830112610c2057600080fd5b813581811115610c2f57600080fd5b8660208260051b8501011115610c4457600080fd5b60209290920196919550909350505050565b60008060208385031215610c6957600080fd5b823567ffffffffffffffff80821115610c8157600080fd5b818501915085601f830112610c9557600080fd5b813581811115610ca457600080fd5b866020606083028501011115610c4457600080fd5b634e487b7160e01b600052603260045260246000fd5b60008235607e19833603018112610ce557600080fd5b9190910192915050565b6000808335601e19843603018112610d0657600080fd5b83018035915067ffffffffffffffff821115610d2157600080fd5b6020019150600581901b3603821315610d3957600080fd5b9250929050565b634e487b7160e01b600052601160045260246000fd5b6000600019821415610d6a57610d6a610d40565b5060010190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b600082821015610db857610db8610d40565b50039056fea2646970667358221220e686f6bcec02b95fda91dc3aabca349a2d71402ac10c33ecba0ca921213a073364736f6c634300080c0033000000000000000000000000a52fd396891e7a74b641a2cb1a6999fcf56b077e

Deployed Bytecode

0x60806040526004361061007f5760003560e01c8063715018a61161004e578063715018a6146102265780638da5cb5b1461023b57806396e859d814610259578063f2fde38b1461027957600080fd5b80630700037d146100f75780630c9cbf0e146101745780632530b145146101ba578063486866261461020657600080fd5b366100f257336001600160a01b037f000000000000000000000000a52fd396891e7a74b641a2cb1a6999fcf56b077e16146100f05760405162461bcd60e51b815260206004820152600c60248201526b4e6f74204d554c544953494760a01b60448201526064015b60405180910390fd5b005b600080fd5b34801561010357600080fd5b50610145610112366004610b8c565b600260208190526000918252604090912080546001820154928201546003909201546001600160a01b0390911692919084565b604080516001600160a01b03909516855260208501939093529183015260608201526080015b60405180910390f35b34801561018057600080fd5b506101ac61018f366004610bae565b600360209081526000928352604080842090915290825290205481565b60405190815260200161016b565b3480156101c657600080fd5b506101ee7f000000000000000000000000a52fd396891e7a74b641a2cb1a6999fcf56b077e81565b6040516001600160a01b03909116815260200161016b565b34801561021257600080fd5b506100f0610221366004610be1565b610299565b34801561023257600080fd5b506100f0610408565b34801561024757600080fd5b506000546001600160a01b03166101ee565b34801561026557600080fd5b506100f0610274366004610c56565b61043e565b34801561028557600080fd5b506100f0610294366004610b8c565b6105d2565b6001546001146102d85760405162461bcd60e51b815260206004820152600a6024820152695245454e5452414e435960b01b60448201526064016100e7565b60026001558061031b5760405162461bcd60e51b815260206004820152600e60248201526d496e76616c696420636c61696d7360901b60448201526064016100e7565b60005b818110156103ff576103ef83838381811061033b5761033b610cb9565b905060200281019061034d9190610ccf565b61035b906020810190610b8c565b84848481811061036d5761036d610cb9565b905060200281019061037f9190610ccf565b610390906040810190602001610b8c565b8585858181106103a2576103a2610cb9565b90506020028101906103b49190610ccf565b604001358686868181106103ca576103ca610cb9565b90506020028101906103dc9190610ccf565b6103ea906060810190610cef565b61066d565b6103f881610d56565b905061031e565b50506001805550565b6000546001600160a01b031633146104325760405162461bcd60e51b81526004016100e790610d71565b61043c60006109d0565b565b6000546001600160a01b031633146104685760405162461bcd60e51b81526004016100e790610d71565b806104ad5760405162461bcd60e51b8152602060048201526015602482015274496e76616c696420646973747269627574696f6e7360581b60448201526064016100e7565b60005b818110156105cd57368383838181106104cb576104cb610cb9565b606002919091019150600090506002816104e86020850185610b8c565b6001600160a01b03168152602080820192909252604001600020915061051090830183610b8c565b81546001600160a01b0319166001600160a01b0391909116178155602082013560018201556040820135600282015560038101805460009061055190610d56565b9091555060038101546105676020840184610b8c565b6001600160a01b03167f9ca93988e299d8264919a188c320f8d8efa97e1976a234f3c6c42315fc10b4e0846020013585604001356040516105b2929190918252602082015260400190565b60405180910390a35050806105c690610d56565b90506104b0565b505050565b6000546001600160a01b031633146105fc5760405162461bcd60e51b81526004016100e790610d71565b6001600160a01b0381166106615760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084016100e7565b61066a816109d0565b50565b6001600160a01b03808616600090815260026020818152604092839020835160808101855281549095168552600181015491850182905291820154928401929092526003015460608301526107045760405162461bcd60e51b815260206004820152601860248201527f446973747269627574696f6e206e6f7420656e61626c6564000000000000000060448201526064016100e7565b6107848383808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152505050506020838101516040516bffffffffffffffffffffffff1960608b901b1692810192909252603482018890529060540160405160208183030381529060405280519060200120610a20565b6107c05760405162461bcd60e51b815260206004820152600d60248201526c24b73b30b634b210383937b7b360991b60448201526064016100e7565b6001600160a01b03808716600090815260036020908152604080832093891683529290522054841161082a5760405162461bcd60e51b8152602060048201526013602482015272139bc818db185a5b58589b19481c995dd85c99606a1b60448201526064016100e7565b6001600160a01b03808716600090815260036020908152604080832093891683529290529081205461085c9086610da6565b6001600160a01b0380891660008181526003602090815260408083208c8616845290915290208890559192507f000000000000000000000000a52fd396891e7a74b641a2cb1a6999fcf56b077e16146108c8576108c36001600160a01b0388168783610a36565b61096d565b6000866001600160a01b03168260405160006040518083038185875af1925050503d8060008114610915576040519150601f19603f3d011682016040523d82523d6000602084013e61091a565b606091505b505090508061096b5760405162461bcd60e51b815260206004820152601d60248201527f4661696c656420746f207472616e7366657220746f206163636f756e7400000060448201526064016100e7565b505b856001600160a01b0316876001600160a01b03167f7a84a08b02c91f3c62d572853f966fc799bbd121e8ad7833a4494ab8dcfcb4048385606001516040516109bf929190918252602082015260400190565b60405180910390a350505050505050565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b600082610a2d8584610ab5565b14949350505050565b600060405163a9059cbb60e01b81526001600160a01b03841660048201528260248201526000806044836000895af1915050610a7181610b29565b610aaf5760405162461bcd60e51b815260206004820152600f60248201526e1514905394d1915497d19052531151608a1b60448201526064016100e7565b50505050565b600081815b8451811015610b21576000858281518110610ad757610ad7610cb9565b60200260200101519050808311610afd5760008381526020829052604090209250610b0e565b600081815260208490526040902092505b5080610b1981610d56565b915050610aba565b509392505050565b60003d82610b3b57806000803e806000fd5b8060208114610b53578015610b645760009250610b69565b816000803e60005115159250610b69565b600192505b5050919050565b80356001600160a01b0381168114610b8757600080fd5b919050565b600060208284031215610b9e57600080fd5b610ba782610b70565b9392505050565b60008060408385031215610bc157600080fd5b610bca83610b70565b9150610bd860208401610b70565b90509250929050565b60008060208385031215610bf457600080fd5b823567ffffffffffffffff80821115610c0c57600080fd5b818501915085601f830112610c2057600080fd5b813581811115610c2f57600080fd5b8660208260051b8501011115610c4457600080fd5b60209290920196919550909350505050565b60008060208385031215610c6957600080fd5b823567ffffffffffffffff80821115610c8157600080fd5b818501915085601f830112610c9557600080fd5b813581811115610ca457600080fd5b866020606083028501011115610c4457600080fd5b634e487b7160e01b600052603260045260246000fd5b60008235607e19833603018112610ce557600080fd5b9190910192915050565b6000808335601e19843603018112610d0657600080fd5b83018035915067ffffffffffffffff821115610d2157600080fd5b6020019150600581901b3603821315610d3957600080fd5b9250929050565b634e487b7160e01b600052601160045260246000fd5b6000600019821415610d6a57610d6a610d40565b5060010190565b6020808252818101527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604082015260600190565b600082821015610db857610db8610d40565b50039056fea2646970667358221220e686f6bcec02b95fda91dc3aabca349a2d71402ac10c33ecba0ca921213a073364736f6c634300080c0033

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

000000000000000000000000a52fd396891e7a74b641a2cb1a6999fcf56b077e

-----Decoded View---------------
Arg [0] : multisig (address): 0xA52Fd396891E7A74b641a2Cb1A6999Fcf56B077e

-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 000000000000000000000000a52fd396891e7a74b641a2cb1a6999fcf56b077e


Deployed Bytecode Sourcemap

19488:4900:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;20948:10;-1:-1:-1;;;;;20962:8:0;20948:22;;20944:50;;20972:22;;-1:-1:-1;;;20972:22:0;;216:2:1;20972:22:0;;;198:21:1;255:2;235:18;;;228:30;-1:-1:-1;;;274:18:1;;;267:42;326:18;;20972:22:0;;;;;;;;20944:50;19488:4900;;;;;20152:41;;;;;;;;;;-1:-1:-1;20152:41:0;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;20152:41:0;;;;;;;;;;;;-1:-1:-1;;;;;973:32:1;;;955:51;;1037:2;1022:18;;1015:34;;;;1065:18;;;1058:34;1123:2;1108:18;;1101:34;942:3;927:19;20152:41:0;;;;;;;;20286:62;;;;;;;;;;-1:-1:-1;20286:62:0;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;1557:25:1;;;1545:2;1530:18;20286:62:0;1411:177:1;20048:33:0;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;1757:32:1;;;1739:51;;1727:2;1712:18;20048:33:0;1593:203:1;21147:371:0;;;;;;;;;;-1:-1:-1;21147:371:0;;;;;:::i;:::-;;:::i;2707:103::-;;;;;;;;;;;;;:::i;2056:87::-;;;;;;;;;;-1:-1:-1;2102:7:0;2129:6;-1:-1:-1;;;;;2129:6:0;2056:87;;21668:869;;;;;;;;;;-1:-1:-1;21668:869:0;;;;;:::i;:::-;;:::i;2965:201::-;;;;;;;;;;-1:-1:-1;2965:201:0;;;;;:::i;:::-;;:::i;21147:371::-;4076:16;;4096:1;4076:21;4068:44;;;;-1:-1:-1;;;4068:44:0;;3301:2:1;4068:44:0;;;3283:21:1;3340:2;3320:18;;;3313:30;-1:-1:-1;;;3359:18:1;;;3352:40;3409:18;;4068:44:0;3099:334:1;4068:44:0;4144:1;4125:16;:20;21228:18;21220:45:::1;;;::::0;-1:-1:-1;;;21220:45:0;;3640:2:1;21220:45:0::1;::::0;::::1;3622:21:1::0;3679:2;3659:18;;;3652:30;-1:-1:-1;;;3698:18:1;;;3691:44;3752:18;;21220:45:0::1;3438:338:1::0;21220:45:0::1;21283:9;21278:233;21294:17:::0;;::::1;21278:233;;;21333:166;21358:6;;21365:1;21358:9;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;:15;::::0;::::1;::::0;::::1;::::0;::::1;:::i;:::-;21392:6;;21399:1;21392:9;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;:17;::::0;;;;;::::1;;;:::i;:::-;21428:6;;21435:1;21428:9;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;:16;;;21463:6;;21470:1;21463:9;;;;;;;:::i;:::-;;;;;;;;;;;;:::i;:::-;:21;::::0;::::1;::::0;::::1;::::0;::::1;:::i;:::-;21333:6;:166::i;:::-;21313:3;::::0;::::1;:::i;:::-;;;21278:233;;;-1:-1:-1::0;;4191:1:0;4172:20;;-1:-1:-1;21147:371:0:o;2707:103::-;2102:7;2129:6;-1:-1:-1;;;;;2129:6:0;877:10;2276:23;2268:68;;;;-1:-1:-1;;;2268:68:0;;;;;;;:::i;:::-;2772:30:::1;2799:1;2772:18;:30::i;:::-;2707:103::o:0;21668:869::-;2102:7;2129:6;-1:-1:-1;;;;;2129:6:0;877:10;2276:23;2268:68;;;;-1:-1:-1;;;2268:68:0;;;;;;;:::i;:::-;21799:25;21791:59:::1;;;::::0;-1:-1:-1;;;21791:59:0;;5625:2:1;21791:59:0::1;::::0;::::1;5607:21:1::0;5664:2;5644:18;;;5637:30;-1:-1:-1;;;5683:18:1;;;5676:51;5744:18;;21791:59:0::1;5423:345:1::0;21791:59:0::1;21868:9;21863:667;21879:24:::0;;::::1;21863:667;;;21999:34;22036:13;;22050:1;22036:16;;;;;;;:::i;:::-;;;::::0;;;::::1;::::0;-1:-1:-1;22067:21:0::1;::::0;-1:-1:-1;22091:7:0::1;22067:21:::0;22099:18:::1;;::::0;::::1;22036:16:::0;22099:18:::1;:::i;:::-;-1:-1:-1::0;;;;;22091:27:0::1;::::0;;::::1;::::0;;::::1;::::0;;;;;;-1:-1:-1;22091:27:0;;-1:-1:-1;22148:18:0::1;::::0;;::::1;:12:::0;:18:::1;:::i;:::-;22133:33:::0;;-1:-1:-1;;;;;;22133:33:0::1;-1:-1:-1::0;;;;;22133:33:0;;;::::1;;::::0;;22201:23:::1;::::0;::::1;;-1:-1:-1::0;22181:17:0;::::1;:43:::0;22254:18:::1;::::0;::::1;;22239:12;::::0;::::1;:33:::0;22289:18:::1;::::0;::::1;22287:20:::0;;-1:-1:-1;;22287:20:0::1;::::0;::::1;:::i;:::-;::::0;;;-1:-1:-1;22485:18:0::1;::::0;::::1;::::0;22369::::1;;::::0;::::1;:12:::0;:18:::1;:::i;:::-;-1:-1:-1::0;;;;;22329:189:0::1;;22406:12;:23;;;22448:12;:18;;;22329:189;;;;;;5947:25:1::0;;;6003:2;5988:18;;5981:34;5935:2;5920:18;;5773:248;22329:189:0::1;;;;;;;;21910:620;;21905:3;;;;:::i;:::-;;;21863:667;;;;21668:869:::0;;:::o;2965:201::-;2102:7;2129:6;-1:-1:-1;;;;;2129:6:0;877:10;2276:23;2268:68;;;;-1:-1:-1;;;2268:68:0;;;;;;;:::i;:::-;-1:-1:-1;;;;;3054:22:0;::::1;3046:73;;;::::0;-1:-1:-1;;;3046:73:0;;6228:2:1;3046:73:0::1;::::0;::::1;6210:21:1::0;6267:2;6247:18;;;6240:30;6306:34;6286:18;;;6279:62;-1:-1:-1;;;6357:18:1;;;6350:36;6403:19;;3046:73:0::1;6026:402:1::0;3046:73:0::1;3130:28;3149:8;3130:18;:28::i;:::-;2965:201:::0;:::o;22822:1563::-;-1:-1:-1;;;;;23003:14:0;;;22980:20;23003:14;;;:7;:14;;;;;;;;;22980:37;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23030:59;;;;-1:-1:-1;;;23030:59:0;;6635:2:1;23030:59:0;;;6617:21:1;6674:2;6654:18;;;6647:30;6713:26;6693:18;;;6686:54;6757:18;;23030:59:0;6433:348:1;23030:59:0;23160:162;23197:11;;23160:162;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;23227:17:0;;;;;23273:33;;-1:-1:-1;;6963:2:1;6959:15;;;6955:53;23273:33:0;;;6943:66:1;;;;7025:12;;;7018:28;;;23227:17:0;7062:12:1;;23273:33:0;;;;;;;;;;;;23263:44;;;;;;23160:18;:162::i;:::-;23138:225;;;;-1:-1:-1;;;23138:225:0;;7287:2:1;23138:225:0;;;7269:21:1;7326:2;7306:18;;;7299:30;-1:-1:-1;;;7345:18:1;;;7338:43;7398:18;;23138:225:0;7085:337:1;23138:225:0;-1:-1:-1;;;;;23424:14:0;;;;;;;:7;:14;;;;;;;;:23;;;;;;;;;;:32;-1:-1:-1;23416:64:0;;;;-1:-1:-1;;;23416:64:0;;7629:2:1;23416:64:0;;;7611:21:1;7668:2;7648:18;;;7641:30;-1:-1:-1;;;7687:18:1;;;7680:49;7746:18;;23416:64:0;7427:343:1;23416:64:0;-1:-1:-1;;;;;23698:14:0;;;23669:17;23698:14;;;:7;:14;;;;;;;;:23;;;;;;;;;;;;23689:32;;:6;:32;:::i;:::-;-1:-1:-1;;;;;23791:14:0;;;;;;;:7;:14;;;;;;;;:23;;;;;;;;;;:32;;;23669:52;;-1:-1:-1;24002:8:0;23993:17;;23989:248;;24027:45;-1:-1:-1;;;;;24027:25:0;;24053:7;24062:9;24027:25;:45::i;:::-;23989:248;;;24106:9;24129:7;-1:-1:-1;;;;;24121:21:0;24150:9;24121:43;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;24105:59;;;24187:4;24179:46;;;;-1:-1:-1;;;24179:46:0;;8317:2:1;24179:46:0;;;8299:21:1;8356:2;8336:18;;;8329:30;8395:31;8375:18;;;8368:59;8444:18;;24179:46:0;8115:353:1;24179:46:0;24090:147;23989:248;24302:7;-1:-1:-1;;;;;24254:123:0;24282:5;-1:-1:-1;;;;;24254:123:0;;24324:9;24348:6;:18;;;24254:123;;;;;;5947:25:1;;;6003:2;5988:18;;5981:34;5935:2;5920:18;;5773:248;24254:123:0;;;;;;;;22969:1416;;22822:1563;;;;;:::o;3326:191::-;3400:16;3419:6;;-1:-1:-1;;;;;3436:17:0;;;-1:-1:-1;;;;;;3436:17:0;;;;;;3469:40;;3419:6;;;;;;;3469:40;;3400:16;3469:40;3389:128;3326:191;:::o;17772:190::-;17897:4;17950;17921:25;17934:5;17941:4;17921:12;:25::i;:::-;:33;;17772:190;-1:-1:-1;;;;17772:190:0:o;13450:1065::-;13567:15;13701:4;13695:11;-1:-1:-1;;;13802:17:0;13795:93;-1:-1:-1;;;;;13977:2:0;13973:51;13969:1;13950:17;13946:25;13939:86;14112:6;14107:2;14088:17;14084:26;14077:42;14410:1;14407;14403:2;14384:17;14381:1;14374:5;14367;14362:50;14348:64;;;14443:44;14476:10;14443:32;:44::i;:::-;14435:72;;;;-1:-1:-1;;;14435:72:0;;8928:2:1;14435:72:0;;;8910:21:1;8967:2;8947:18;;;8940:30;-1:-1:-1;;;8986:18:1;;;8979:45;9041:18;;14435:72:0;8726:339:1;14435:72:0;13556:959;13450:1065;;;:::o;18324:675::-;18407:7;18450:4;18407:7;18465:497;18489:5;:12;18485:1;:16;18465:497;;;18523:20;18546:5;18552:1;18546:8;;;;;;;;:::i;:::-;;;;;;;18523:31;;18589:12;18573;:28;18569:382;;19075:13;19125:15;;;19161:4;19154:15;;;19208:4;19192:21;;18701:57;;18569:382;;;19075:13;19125:15;;;19161:4;19154:15;;;19208:4;19192:21;;18878:57;;18569:382;-1:-1:-1;18503:3:0;;;;:::i;:::-;;;;18465:497;;;-1:-1:-1;18979:12:0;18324:675;-1:-1:-1;;;18324:675:0:o;15785:1072::-;15866:12;15991:16;16071:10;16061:244;;16180:14;16177:1;16174;16159:36;16275:14;16272:1;16265:25;16061:244;16328:14;16361:2;16356:248;;;;16618:99;;;;16823:1;16812:12;;16321:518;;16356:248;16458:14;16455:1;16452;16437:36;16585:1;16579:8;16572:16;16565:24;16554:35;;16356:248;;16618:99;16701:1;16690:12;;16321:518;;;15785:1072;;;:::o;355:173:1:-;423:20;;-1:-1:-1;;;;;472:31:1;;462:42;;452:70;;518:1;515;508:12;452:70;355:173;;;:::o;533:186::-;592:6;645:2;633:9;624:7;620:23;616:32;613:52;;;661:1;658;651:12;613:52;684:29;703:9;684:29;:::i;:::-;674:39;533:186;-1:-1:-1;;;533:186:1:o;1146:260::-;1214:6;1222;1275:2;1263:9;1254:7;1250:23;1246:32;1243:52;;;1291:1;1288;1281:12;1243:52;1314:29;1333:9;1314:29;:::i;:::-;1304:39;;1362:38;1396:2;1385:9;1381:18;1362:38;:::i;:::-;1352:48;;1146:260;;;;;:::o;1801:639::-;1911:6;1919;1972:2;1960:9;1951:7;1947:23;1943:32;1940:52;;;1988:1;1985;1978:12;1940:52;2028:9;2015:23;2057:18;2098:2;2090:6;2087:14;2084:34;;;2114:1;2111;2104:12;2084:34;2152:6;2141:9;2137:22;2127:32;;2197:7;2190:4;2186:2;2182:13;2178:27;2168:55;;2219:1;2216;2209:12;2168:55;2259:2;2246:16;2285:2;2277:6;2274:14;2271:34;;;2301:1;2298;2291:12;2271:34;2354:7;2349:2;2339:6;2336:1;2332:14;2328:2;2324:23;2320:32;2317:45;2314:65;;;2375:1;2372;2365:12;2314:65;2406:2;2398:11;;;;;2428:6;;-1:-1:-1;1801:639:1;;-1:-1:-1;;;;1801:639:1:o;2445:649::-;2562:6;2570;2623:2;2611:9;2602:7;2598:23;2594:32;2591:52;;;2639:1;2636;2629:12;2591:52;2679:9;2666:23;2708:18;2749:2;2741:6;2738:14;2735:34;;;2765:1;2762;2755:12;2735:34;2803:6;2792:9;2788:22;2778:32;;2848:7;2841:4;2837:2;2833:13;2829:27;2819:55;;2870:1;2867;2860:12;2819:55;2910:2;2897:16;2936:2;2928:6;2925:14;2922:34;;;2952:1;2949;2942:12;2922:34;3008:7;3003:2;2995:4;2987:6;2983:17;2979:2;2975:26;2971:35;2968:48;2965:68;;;3029:1;3026;3019:12;3781:127;3842:10;3837:3;3833:20;3830:1;3823:31;3873:4;3870:1;3863:15;3897:4;3894:1;3887:15;3913:322;4003:4;4061:11;4048:25;4155:3;4151:8;4140;4124:14;4120:29;4116:44;4096:18;4092:69;4082:97;;4175:1;4172;4165:12;4082:97;4196:33;;;;;3913:322;-1:-1:-1;;3913:322:1:o;4240:545::-;4333:4;4339:6;4399:11;4386:25;4493:2;4489:7;4478:8;4462:14;4458:29;4454:43;4434:18;4430:68;4420:96;;4512:1;4509;4502:12;4420:96;4539:33;;4591:20;;;-1:-1:-1;4634:18:1;4623:30;;4620:50;;;4666:1;4663;4656:12;4620:50;4699:4;4687:17;;-1:-1:-1;4750:1:1;4746:14;;;4730;4726:35;4716:46;;4713:66;;;4775:1;4772;4765:12;4713:66;4240:545;;;;;:::o;4790:127::-;4851:10;4846:3;4842:20;4839:1;4832:31;4882:4;4879:1;4872:15;4906:4;4903:1;4896:15;4922:135;4961:3;-1:-1:-1;;4982:17:1;;4979:43;;;5002:18;;:::i;:::-;-1:-1:-1;5049:1:1;5038:13;;4922:135::o;5062:356::-;5264:2;5246:21;;;5283:18;;;5276:30;5342:34;5337:2;5322:18;;5315:62;5409:2;5394:18;;5062:356::o;7775:125::-;7815:4;7843:1;7840;7837:8;7834:34;;;7848:18;;:::i;:::-;-1:-1:-1;7885:9:1;;7775:125::o

Swarm Source

ipfs://e686f6bcec02b95fda91dc3aabca349a2d71402ac10c33ecba0ca921213a0733

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading
[ Download: CSV Export  ]
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.