Contract 0xbb0f594143208eCd04DC7AAe48955902A716F9F7

Contract Overview

Balance:
0 Ether
Txn Hash
Method
Block
From
To
Value
0xd82af20601eb4c8382bd94939969cb34d8ba169966612f2f56edfc805faa461b0x6101006096703242021-11-19 16:05:37315 days 5 hrs ago0x2a61d3ba5030ef471c74f612962c7367eca3a62d IN  Create: TopUpRewardPrograms0 Ether0.000714421.00000001
[ Download CSV Export 
Latest 25 internal transaction
Parent Txn Hash Block From To Value
0xbcdbecac621de49b0e32cd67211cc076c7c0fc4dbf2bb2ff5f8a5ff4fa003618113314722022-09-06 5:57:1924 days 15 hrs ago 0xbb0f594143208ecd04dc7aae48955902a716f9f7 0x648c8be548f43eca4e482c0801ebccccfb9449310 Ether
0xbcdbecac621de49b0e32cd67211cc076c7c0fc4dbf2bb2ff5f8a5ff4fa003618113314722022-09-06 5:57:1924 days 15 hrs ago 0x661090cb830757b2d0cd53c49bf0d17a28992e5d 0xbb0f594143208ecd04dc7aae48955902a716f9f70 Ether
0xe5d81b0d8fa98b41d42f77cc3bb8aaf89c9e0e37aee1c91da47c3680bcab3849101430922022-02-10 11:11:18232 days 10 hrs ago 0xbb0f594143208ecd04dc7aae48955902a716f9f7 0x648c8be548f43eca4e482c0801ebccccfb9449310 Ether
0xe5d81b0d8fa98b41d42f77cc3bb8aaf89c9e0e37aee1c91da47c3680bcab3849101430922022-02-10 11:11:18232 days 10 hrs ago 0x661090cb830757b2d0cd53c49bf0d17a28992e5d 0xbb0f594143208ecd04dc7aae48955902a716f9f70 Ether
0xcea7535511e24cba1bc5bb8f834e42c79bf799eabcdfb36e286d990b01bb98dc101281082022-02-07 14:26:42235 days 7 hrs ago 0xbb0f594143208ecd04dc7aae48955902a716f9f7 0x648c8be548f43eca4e482c0801ebccccfb9449310 Ether
0xcea7535511e24cba1bc5bb8f834e42c79bf799eabcdfb36e286d990b01bb98dc101281082022-02-07 14:26:42235 days 7 hrs ago 0x661090cb830757b2d0cd53c49bf0d17a28992e5d 0xbb0f594143208ecd04dc7aae48955902a716f9f70 Ether
0xb59fe3476c05dfe9cbc4756333e7e791e720643db211b4e320c1c31357c613ac101279652022-02-07 13:50:57235 days 7 hrs ago 0xbb0f594143208ecd04dc7aae48955902a716f9f7 0x648c8be548f43eca4e482c0801ebccccfb9449310 Ether
0xb59fe3476c05dfe9cbc4756333e7e791e720643db211b4e320c1c31357c613ac101279652022-02-07 13:50:57235 days 7 hrs ago 0x661090cb830757b2d0cd53c49bf0d17a28992e5d 0xbb0f594143208ecd04dc7aae48955902a716f9f70 Ether
0x72fff67892dc087558c2c676a5007e5f62aeac78182f8d0ad0b0815fd6dda399100702992022-01-28 13:26:51245 days 8 hrs ago 0xbb0f594143208ecd04dc7aae48955902a716f9f7 0x648c8be548f43eca4e482c0801ebccccfb9449310 Ether
0x72fff67892dc087558c2c676a5007e5f62aeac78182f8d0ad0b0815fd6dda399100702992022-01-28 13:26:51245 days 8 hrs ago 0x661090cb830757b2d0cd53c49bf0d17a28992e5d 0xbb0f594143208ecd04dc7aae48955902a716f9f70 Ether
0xa50462e820709dbba74a8b5b389e0791dd88d1ad9cf5cfcce622318041cb5cb299661102022-01-10 8:46:41263 days 12 hrs ago 0xbb0f594143208ecd04dc7aae48955902a716f9f7 0x648c8be548f43eca4e482c0801ebccccfb9449310 Ether
0xa50462e820709dbba74a8b5b389e0791dd88d1ad9cf5cfcce622318041cb5cb299661102022-01-10 8:46:41263 days 12 hrs ago 0x661090cb830757b2d0cd53c49bf0d17a28992e5d 0xbb0f594143208ecd04dc7aae48955902a716f9f70 Ether
0x691f6310bcf10b94a346874f1d92c2de6327aaf0e728b6131216f9d3cf5d061c98924612021-12-28 8:58:22276 days 12 hrs ago 0xbb0f594143208ecd04dc7aae48955902a716f9f7 0x648c8be548f43eca4e482c0801ebccccfb9449310 Ether
0x691f6310bcf10b94a346874f1d92c2de6327aaf0e728b6131216f9d3cf5d061c98924612021-12-28 8:58:22276 days 12 hrs ago 0x661090cb830757b2d0cd53c49bf0d17a28992e5d 0xbb0f594143208ecd04dc7aae48955902a716f9f70 Ether
0x5b656099d11f2d1204c9a615142e7f14f928684ae3fd8ec0cea44c19603bfed898637982021-12-23 9:30:20281 days 12 hrs ago 0xbb0f594143208ecd04dc7aae48955902a716f9f7 0x648c8be548f43eca4e482c0801ebccccfb9449310 Ether
0x5b656099d11f2d1204c9a615142e7f14f928684ae3fd8ec0cea44c19603bfed898637982021-12-23 9:30:20281 days 12 hrs ago 0x661090cb830757b2d0cd53c49bf0d17a28992e5d 0xbb0f594143208ecd04dc7aae48955902a716f9f70 Ether
0x1ba4215820a86ee5ecb114129f87fe95c3e2dd222d1cc0a33d80ee00d05a3de798464062021-12-20 9:00:55284 days 12 hrs ago 0xbb0f594143208ecd04dc7aae48955902a716f9f7 0x648c8be548f43eca4e482c0801ebccccfb9449310 Ether
0x1ba4215820a86ee5ecb114129f87fe95c3e2dd222d1cc0a33d80ee00d05a3de798464062021-12-20 9:00:55284 days 12 hrs ago 0x661090cb830757b2d0cd53c49bf0d17a28992e5d 0xbb0f594143208ecd04dc7aae48955902a716f9f70 Ether
0x9390d60620b79e793742fadb37121fae640371f2ed0e2d2bfabbdf4ded49740e98187042021-12-15 13:32:09289 days 7 hrs ago 0xbb0f594143208ecd04dc7aae48955902a716f9f7 0x648c8be548f43eca4e482c0801ebccccfb9449310 Ether
0x9390d60620b79e793742fadb37121fae640371f2ed0e2d2bfabbdf4ded49740e98187042021-12-15 13:32:09289 days 7 hrs ago 0x661090cb830757b2d0cd53c49bf0d17a28992e5d 0xbb0f594143208ecd04dc7aae48955902a716f9f70 Ether
0x011c1f8c4b09951be900cf92d987be682dbb603b555f67e031ec0b928bc28e4197490622021-12-03 8:17:57301 days 13 hrs ago 0xbb0f594143208ecd04dc7aae48955902a716f9f7 0x648c8be548f43eca4e482c0801ebccccfb9449310 Ether
0x011c1f8c4b09951be900cf92d987be682dbb603b555f67e031ec0b928bc28e4197490622021-12-03 8:17:57301 days 13 hrs ago 0xbb0f594143208ecd04dc7aae48955902a716f9f7 0x648c8be548f43eca4e482c0801ebccccfb9449310 Ether
0x011c1f8c4b09951be900cf92d987be682dbb603b555f67e031ec0b928bc28e4197490622021-12-03 8:17:57301 days 13 hrs ago 0x661090cb830757b2d0cd53c49bf0d17a28992e5d 0xbb0f594143208ecd04dc7aae48955902a716f9f70 Ether
0xec3b792768e0ef9c0e86710404ed6ad78b7d095bbee34947d9fb44f974a5fb0d97456422021-12-02 18:02:29302 days 3 hrs ago 0xbb0f594143208ecd04dc7aae48955902a716f9f7 0x648c8be548f43eca4e482c0801ebccccfb9449310 Ether
0xec3b792768e0ef9c0e86710404ed6ad78b7d095bbee34947d9fb44f974a5fb0d97456422021-12-02 18:02:29302 days 3 hrs ago 0xbb0f594143208ecd04dc7aae48955902a716f9f7 0x648c8be548f43eca4e482c0801ebccccfb9449310 Ether
[ Download CSV Export 
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
TopUpRewardPrograms

Compiler Version
v0.8.6+commit.11564f7e

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, GNU GPLv3 license

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2021-11-19
*/

// SPDX-License-Identifier: GPL-3.0 AND MIT
// File: contracts/TrustedCaller.sol

// SPDX-FileCopyrightText: 2021 Lido <[email protected]>

pragma solidity ^0.8.4;

/// @author psirex
/// @notice A helper contract contains logic to validate that only a trusted caller has access to certain methods.
/// @dev Trusted caller set once on deployment and can't be changed.
contract TrustedCaller {
    string private constant ERROR_TRUSTED_CALLER_IS_ZERO_ADDRESS = "TRUSTED_CALLER_IS_ZERO_ADDRESS";
    string private constant ERROR_CALLER_IS_FORBIDDEN = "CALLER_IS_FORBIDDEN";

    address public immutable trustedCaller;

    constructor(address _trustedCaller) {
        require(_trustedCaller != address(0), ERROR_TRUSTED_CALLER_IS_ZERO_ADDRESS);
        trustedCaller = _trustedCaller;
    }

    modifier onlyTrustedCaller(address _caller) {
        require(_caller == trustedCaller, ERROR_CALLER_IS_FORBIDDEN);
        _;
    }
}

// File: OpenZeppelin/[email protected]/contracts/access/IAccessControl.sol


pragma solidity ^0.8.0;

/**
 * @dev External interface of AccessControl declared to support ERC165 detection.
 */
interface IAccessControl {
    /**
     * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
     *
     * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
     * {RoleAdminChanged} not being emitted signaling this.
     *
     * _Available since v3.1._
     */
    event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);

    /**
     * @dev Emitted when `account` is granted `role`.
     *
     * `sender` is the account that originated the contract call, an admin role
     * bearer except when using {AccessControl-_setupRole}.
     */
    event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);

    /**
     * @dev Emitted when `account` is revoked `role`.
     *
     * `sender` is the account that originated the contract call:
     *   - if using `revokeRole`, it is the admin role bearer
     *   - if using `renounceRole`, it is the role bearer (i.e. `account`)
     */
    event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);

    /**
     * @dev Returns `true` if `account` has been granted `role`.
     */
    function hasRole(bytes32 role, address account) external view returns (bool);

    /**
     * @dev Returns the admin role that controls `role`. See {grantRole} and
     * {revokeRole}.
     *
     * To change a role's admin, use {AccessControl-_setRoleAdmin}.
     */
    function getRoleAdmin(bytes32 role) external view returns (bytes32);

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function grantRole(bytes32 role, address account) external;

    /**
     * @dev Revokes `role` from `account`.
     *
     * If `account` had been granted `role`, emits a {RoleRevoked} event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function revokeRole(bytes32 role, address account) external;

    /**
     * @dev Revokes `role` from the calling account.
     *
     * Roles are often managed via {grantRole} and {revokeRole}: this function's
     * purpose is to provide a mechanism for accounts to lose their privileges
     * if they are compromised (such as when a trusted device is misplaced).
     *
     * If the calling account had been granted `role`, emits a {RoleRevoked}
     * event.
     *
     * Requirements:
     *
     * - the caller must be `account`.
     */
    function renounceRole(bytes32 role, address account) external;
}

// File: OpenZeppelin/[email protected]/contracts/utils/Context.sol


pragma solidity ^0.8.0;

/**
 * @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/[email protected]/contracts/utils/Strings.sol


pragma solidity ^0.8.0;

/**
 * @dev String operations.
 */
library Strings {
    bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";

    /**
     * @dev Converts a `uint256` to its ASCII `string` decimal representation.
     */
    function toString(uint256 value) internal pure returns (string memory) {
        // Inspired by OraclizeAPI's implementation - MIT licence
        // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol

        if (value == 0) {
            return "0";
        }
        uint256 temp = value;
        uint256 digits;
        while (temp != 0) {
            digits++;
            temp /= 10;
        }
        bytes memory buffer = new bytes(digits);
        while (value != 0) {
            digits -= 1;
            buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
            value /= 10;
        }
        return string(buffer);
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
     */
    function toHexString(uint256 value) internal pure returns (string memory) {
        if (value == 0) {
            return "0x00";
        }
        uint256 temp = value;
        uint256 length = 0;
        while (temp != 0) {
            length++;
            temp >>= 8;
        }
        return toHexString(value, length);
    }

    /**
     * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
     */
    function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
        bytes memory buffer = new bytes(2 * length + 2);
        buffer[0] = "0";
        buffer[1] = "x";
        for (uint256 i = 2 * length + 1; i > 1; --i) {
            buffer[i] = _HEX_SYMBOLS[value & 0xf];
            value >>= 4;
        }
        require(value == 0, "Strings: hex length insufficient");
        return string(buffer);
    }
}

// File: OpenZeppelin/[email protected]/contracts/utils/introspection/IERC165.sol


pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[EIP].
 *
 * Implementers can declare support of contract interfaces, which can then be
 * queried by others ({ERC165Checker}).
 *
 * For an implementation, see {ERC165}.
 */
interface IERC165 {
    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

// File: OpenZeppelin/[email protected]/contracts/utils/introspection/ERC165.sol


pragma solidity ^0.8.0;


/**
 * @dev Implementation of the {IERC165} interface.
 *
 * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
 * for the additional interface id that will be supported. For example:
 *
 * ```solidity
 * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
 *     return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
 * }
 * ```
 *
 * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
 */
abstract contract ERC165 is IERC165 {
    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return interfaceId == type(IERC165).interfaceId;
    }
}

// File: OpenZeppelin/[email protected]/contracts/access/AccessControl.sol


pragma solidity ^0.8.0;





/**
 * @dev Contract module that allows children to implement role-based access
 * control mechanisms. This is a lightweight version that doesn't allow enumerating role
 * members except through off-chain means by accessing the contract event logs. Some
 * applications may benefit from on-chain enumerability, for those cases see
 * {AccessControlEnumerable}.
 *
 * Roles are referred to by their `bytes32` identifier. These should be exposed
 * in the external API and be unique. The best way to achieve this is by
 * using `public constant` hash digests:
 *
 * ```
 * bytes32 public constant MY_ROLE = keccak256("MY_ROLE");
 * ```
 *
 * Roles can be used to represent a set of permissions. To restrict access to a
 * function call, use {hasRole}:
 *
 * ```
 * function foo() public {
 *     require(hasRole(MY_ROLE, msg.sender));
 *     ...
 * }
 * ```
 *
 * Roles can be granted and revoked dynamically via the {grantRole} and
 * {revokeRole} functions. Each role has an associated admin role, and only
 * accounts that have a role's admin role can call {grantRole} and {revokeRole}.
 *
 * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means
 * that only accounts with this role will be able to grant or revoke other
 * roles. More complex role relationships can be created by using
 * {_setRoleAdmin}.
 *
 * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to
 * grant and revoke this role. Extra precautions should be taken to secure
 * accounts that have been granted it.
 */
abstract contract AccessControl is Context, IAccessControl, ERC165 {
    struct RoleData {
        mapping(address => bool) members;
        bytes32 adminRole;
    }

    mapping(bytes32 => RoleData) private _roles;

    bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;

    /**
     * @dev Modifier that checks that an account has a specific role. Reverts
     * with a standardized message including the required role.
     *
     * The format of the revert reason is given by the following regular expression:
     *
     *  /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/
     *
     * _Available since v4.1._
     */
    modifier onlyRole(bytes32 role) {
        _checkRole(role, _msgSender());
        _;
    }

    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);
    }

    /**
     * @dev Returns `true` if `account` has been granted `role`.
     */
    function hasRole(bytes32 role, address account) public view override returns (bool) {
        return _roles[role].members[account];
    }

    /**
     * @dev Revert with a standard message if `account` is missing `role`.
     *
     * The format of the revert reason is given by the following regular expression:
     *
     *  /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/
     */
    function _checkRole(bytes32 role, address account) internal view {
        if (!hasRole(role, account)) {
            revert(
                string(
                    abi.encodePacked(
                        "AccessControl: account ",
                        Strings.toHexString(uint160(account), 20),
                        " is missing role ",
                        Strings.toHexString(uint256(role), 32)
                    )
                )
            );
        }
    }

    /**
     * @dev Returns the admin role that controls `role`. See {grantRole} and
     * {revokeRole}.
     *
     * To change a role's admin, use {_setRoleAdmin}.
     */
    function getRoleAdmin(bytes32 role) public view override returns (bytes32) {
        return _roles[role].adminRole;
    }

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {
        _grantRole(role, account);
    }

    /**
     * @dev Revokes `role` from `account`.
     *
     * If `account` had been granted `role`, emits a {RoleRevoked} event.
     *
     * Requirements:
     *
     * - the caller must have ``role``'s admin role.
     */
    function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {
        _revokeRole(role, account);
    }

    /**
     * @dev Revokes `role` from the calling account.
     *
     * Roles are often managed via {grantRole} and {revokeRole}: this function's
     * purpose is to provide a mechanism for accounts to lose their privileges
     * if they are compromised (such as when a trusted device is misplaced).
     *
     * If the calling account had been granted `role`, emits a {RoleRevoked}
     * event.
     *
     * Requirements:
     *
     * - the caller must be `account`.
     */
    function renounceRole(bytes32 role, address account) public virtual override {
        require(account == _msgSender(), "AccessControl: can only renounce roles for self");

        _revokeRole(role, account);
    }

    /**
     * @dev Grants `role` to `account`.
     *
     * If `account` had not been already granted `role`, emits a {RoleGranted}
     * event. Note that unlike {grantRole}, this function doesn't perform any
     * checks on the calling account.
     *
     * [WARNING]
     * ====
     * This function should only be called from the constructor when setting
     * up the initial roles for the system.
     *
     * Using this function in any other way is effectively circumventing the admin
     * system imposed by {AccessControl}.
     * ====
     */
    function _setupRole(bytes32 role, address account) internal virtual {
        _grantRole(role, account);
    }

    /**
     * @dev Sets `adminRole` as ``role``'s admin role.
     *
     * Emits a {RoleAdminChanged} event.
     */
    function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
        bytes32 previousAdminRole = getRoleAdmin(role);
        _roles[role].adminRole = adminRole;
        emit RoleAdminChanged(role, previousAdminRole, adminRole);
    }

    function _grantRole(bytes32 role, address account) private {
        if (!hasRole(role, account)) {
            _roles[role].members[account] = true;
            emit RoleGranted(role, account, _msgSender());
        }
    }

    function _revokeRole(bytes32 role, address account) private {
        if (hasRole(role, account)) {
            _roles[role].members[account] = false;
            emit RoleRevoked(role, account, _msgSender());
        }
    }
}

// File: contracts/RewardProgramsRegistry.sol

// SPDX-FileCopyrightText: 2021 Lido <[email protected]>

pragma solidity ^0.8.4;


/// @author psirex
/// @title Registry of allowed reward programs
/// @notice Stores list of addresses with reward programs
contract RewardProgramsRegistry is AccessControl {
    // -------------
    // EVENTS
    // -------------
    event RewardProgramAdded(address indexed _rewardProgram, string _title);
    event RewardProgramRemoved(address indexed _rewardProgram);

    // -------------
    // ROLES
    // -------------
    bytes32 public constant ADD_REWARD_PROGRAM_ROLE = keccak256("ADD_REWARD_PROGRAM_ROLE");
    bytes32 public constant REMOVE_REWARD_PROGRAM_ROLE = keccak256("REMOVE_REWARD_PROGRAM_ROLE");

    // -------------
    // ERRORS
    // -------------
    string private constant ERROR_REWARD_PROGRAM_ALREADY_ADDED = "REWARD_PROGRAM_ALREADY_ADDED";
    string private constant ERROR_REWARD_PROGRAM_NOT_FOUND = "REWARD_PROGRAM_NOT_FOUND";

    // -------------
    // VARIABLES
    // -------------

    /// @dev List of allowed reward program addresses
    address[] public rewardPrograms;

    // Position of the reward program in the `rewardPrograms` array,
    // plus 1 because index 0 means a value is not in the set.
    mapping(address => uint256) private rewardProgramIndices;

    // -------------
    // CONSTRUCTOR
    // -------------

    /// @param _admin Address which will be granted with role DEFAULT_ADMIN_ROLE
    /// @param _addRewardProgramRoleHolders List of addresses which will be
    ///     granted with role ADD_REWARD_PROGRAM_ROLE
    /// @param _removeRewardProgramRoleHolders List of addresses which will
    ///     be granted with role REMOVE_REWARD_PROGRAM_ROLE
    constructor(
        address _admin,
        address[] memory _addRewardProgramRoleHolders,
        address[] memory _removeRewardProgramRoleHolders
    ) {
        _setupRole(DEFAULT_ADMIN_ROLE, _admin);
        for (uint256 i = 0; i < _addRewardProgramRoleHolders.length; i++) {
            _setupRole(ADD_REWARD_PROGRAM_ROLE, _addRewardProgramRoleHolders[i]);
        }
        for (uint256 i = 0; i < _removeRewardProgramRoleHolders.length; i++) {
            _setupRole(REMOVE_REWARD_PROGRAM_ROLE, _removeRewardProgramRoleHolders[i]);
        }
    }

    // -------------
    // EXTERNAL METHODS
    // -------------

    /// @notice Adds address to list of allowed reward programs
    function addRewardProgram(address _rewardProgram, string memory _title)
        external
        onlyRole(ADD_REWARD_PROGRAM_ROLE)
    {
        require(rewardProgramIndices[_rewardProgram] == 0, ERROR_REWARD_PROGRAM_ALREADY_ADDED);

        rewardPrograms.push(_rewardProgram);
        rewardProgramIndices[_rewardProgram] = rewardPrograms.length;
        emit RewardProgramAdded(_rewardProgram, _title);
    }

    /// @notice Removes address from list of allowed reward programs
    /// @dev To delete a reward program from the rewardPrograms array in O(1), we swap the element to delete with the last one in
    /// the array, and then remove the last element (sometimes called as 'swap and pop').
    function removeRewardProgram(address _rewardProgram)
        external
        onlyRole(REMOVE_REWARD_PROGRAM_ROLE)
    {
        uint256 index = _getRewardProgramIndex(_rewardProgram);
        uint256 lastIndex = rewardPrograms.length - 1;

        if (index != lastIndex) {
            address lastRewardProgram = rewardPrograms[lastIndex];
            rewardPrograms[index] = lastRewardProgram;
            rewardProgramIndices[lastRewardProgram] = index + 1;
        }

        rewardPrograms.pop();
        delete rewardProgramIndices[_rewardProgram];
        emit RewardProgramRemoved(_rewardProgram);
    }

    /// @notice Returns if passed address are listed as reward program in the registry
    function isRewardProgram(address _maybeRewardProgram) external view returns (bool) {
        return rewardProgramIndices[_maybeRewardProgram] > 0;
    }

    /// @notice Returns current list of reward programs
    function getRewardPrograms() external view returns (address[] memory) {
        return rewardPrograms;
    }

    // ------------------
    // PRIVATE METHODS
    // ------------------

    function _getRewardProgramIndex(address _evmScriptFactory)
        private
        view
        returns (uint256 _index)
    {
        _index = rewardProgramIndices[_evmScriptFactory];
        require(_index > 0, ERROR_REWARD_PROGRAM_NOT_FOUND);
        _index -= 1;
    }
}

// File: contracts/interfaces/IFinance.sol

// SPDX-FileCopyrightText: 2021 Lido <[email protected]>

pragma solidity ^0.8.4;

/// @author psirex
/// @notice Interface of method from Aragon's Finance contract to create a new payment
interface IFinance {
    function newImmediatePayment(
        address _token,
        address _receiver,
        uint256 _amount,
        string memory _reference
    ) external;
}

// File: contracts/libraries/EVMScriptCreator.sol

// SPDX-FileCopyrightText: 2021 Lido <[email protected]>

pragma solidity ^0.8.4;

/// @author psirex
/// @notice Contains methods for convenient creation
/// of EVMScripts in EVMScript factories contracts
library EVMScriptCreator {
    // Id of default CallsScript Aragon's executor.
    bytes4 private constant SPEC_ID = hex"00000001";

    /// @notice Encodes one method call as EVMScript
    function createEVMScript(
        address _to,
        bytes4 _methodId,
        bytes memory _evmScriptCallData
    ) internal pure returns (bytes memory _commands) {
        return
            abi.encodePacked(
                SPEC_ID,
                _to,
                uint32(_evmScriptCallData.length) + 4,
                _methodId,
                _evmScriptCallData
            );
    }

    /// @notice Encodes multiple calls of the same method on one contract as EVMScript
    function createEVMScript(
        address _to,
        bytes4 _methodId,
        bytes[] memory _evmScriptCallData
    ) internal pure returns (bytes memory _evmScript) {
        for (uint256 i = 0; i < _evmScriptCallData.length; ++i) {
            _evmScript = bytes.concat(
                _evmScript,
                abi.encodePacked(
                    _to,
                    uint32(_evmScriptCallData[i].length) + 4,
                    _methodId,
                    _evmScriptCallData[i]
                )
            );
        }
        _evmScript = bytes.concat(SPEC_ID, _evmScript);
    }

    /// @notice Encodes multiple calls to different methods within the same contract as EVMScript
    function createEVMScript(
        address _to,
        bytes4[] memory _methodIds,
        bytes[] memory _evmScriptCallData
    ) internal pure returns (bytes memory _evmScript) {
        require(_methodIds.length == _evmScriptCallData.length, "LENGTH_MISMATCH");

        for (uint256 i = 0; i < _methodIds.length; ++i) {
            _evmScript = bytes.concat(
                _evmScript,
                abi.encodePacked(
                    _to,
                    uint32(_evmScriptCallData[i].length) + 4,
                    _methodIds[i],
                    _evmScriptCallData[i]
                )
            );
        }
        _evmScript = bytes.concat(SPEC_ID, _evmScript);
    }

    /// @notice Encodes multiple calls to different contracts as EVMScript
    function createEVMScript(
        address[] memory _to,
        bytes4[] memory _methodIds,
        bytes[] memory _evmScriptCallData
    ) internal pure returns (bytes memory _evmScript) {
        require(_to.length == _methodIds.length, "LENGTH_MISMATCH");
        require(_to.length == _evmScriptCallData.length, "LENGTH_MISMATCH");

        for (uint256 i = 0; i < _to.length; ++i) {
            _evmScript = bytes.concat(
                _evmScript,
                abi.encodePacked(
                    _to[i],
                    uint32(_evmScriptCallData[i].length) + 4,
                    _methodIds[i],
                    _evmScriptCallData[i]
                )
            );
        }
        _evmScript = bytes.concat(SPEC_ID, _evmScript);
    }
}

// File: contracts/interfaces/IEVMScriptFactory.sol

// SPDX-FileCopyrightText: 2021 Lido <[email protected]>

pragma solidity ^0.8.4;

/// @author psirex
/// @notice Interface which every EVMScript factory used in EasyTrack contract has to implement
interface IEVMScriptFactory {
    function createEVMScript(address _creator, bytes memory _evmScriptCallData)
        external
        returns (bytes memory);
}

// File: contracts/EVMScriptFactories/TopUpRewardPrograms.sol

// SPDX-FileCopyrightText: 2021 Lido <[email protected]>

pragma solidity ^0.8.4;






/// @author psirex
/// @notice Creates EVMScript to top up balances of reward programs
contract TopUpRewardPrograms is TrustedCaller, IEVMScriptFactory {
    // -------------
    // ERRORS
    // -------------
    string private constant ERROR_LENGTH_MISMATCH = "LENGTH_MISMATCH";
    string private constant ERROR_EMPTY_DATA = "EMPTY_DATA";
    string private constant ERROR_ZERO_AMOUNT = "ZERO_AMOUNT";
    string private constant ERROR_REWARD_PROGRAM_NOT_ALLOWED = "REWARD_PROGRAM_NOT_ALLOWED";

    // -------------
    // VARIABLES
    // -------------

    /// @notice Address of Aragon's Finance contract
    IFinance public immutable finance;

    /// @notice Address of reward token
    address public immutable rewardToken;

    /// @notice Address of RewardProgramsRegistry
    RewardProgramsRegistry public immutable rewardProgramsRegistry;

    // -------------
    // CONSTRUCTOR
    // -------------

    constructor(
        address _trustedCaller,
        address _rewardProgramsRegistry,
        address _finance,
        address _rewardToken
    ) TrustedCaller(_trustedCaller) {
        finance = IFinance(_finance);
        rewardToken = _rewardToken;
        rewardProgramsRegistry = RewardProgramsRegistry(_rewardProgramsRegistry);
    }

    // -------------
    // EXTERNAL METHODS
    // -------------

    /// @notice Creates EVMScript to top up balances of reward programs
    /// @param _creator Address who creates EVMScript
    /// @param _evmScriptCallData Encoded tuple: (address[] _rewardPrograms, uint256[] _amounts) where
    /// _rewardPrograms - addresses of reward programs to top up
    /// _amounts - corresponding amount of tokens to transfer
    function createEVMScript(address _creator, bytes memory _evmScriptCallData)
        external
        view
        override
        onlyTrustedCaller(_creator)
        returns (bytes memory)
    {
        (address[] memory rewardPrograms, uint256[] memory amounts) =
            _decodeEVMScriptCallData(_evmScriptCallData);

        _validateEVMScriptCallData(rewardPrograms, amounts);

        bytes[] memory evmScriptsCalldata = new bytes[](rewardPrograms.length);
        for (uint256 i = 0; i < rewardPrograms.length; ++i) {
            evmScriptsCalldata[i] = abi.encode(
                rewardToken,
                rewardPrograms[i],
                amounts[i],
                "Reward program top up"
            );
        }
        return
            EVMScriptCreator.createEVMScript(
                address(finance),
                finance.newImmediatePayment.selector,
                evmScriptsCalldata
            );
    }

    /// @notice Decodes call data used by createEVMScript method
    /// @param _evmScriptCallData Encoded tuple: (address[] _rewardPrograms, uint256[] _amounts) where
    /// _rewardPrograms - addresses of reward programs to top up
    /// _amounts - corresponding amount of tokens to transfer
    /// @return _rewardPrograms Addresses of reward programs to top up
    /// @return _amounts Amounts of tokens to transfer
    function decodeEVMScriptCallData(bytes memory _evmScriptCallData)
        external
        pure
        returns (address[] memory _rewardPrograms, uint256[] memory _amounts)
    {
        return _decodeEVMScriptCallData(_evmScriptCallData);
    }

    // ------------------
    // PRIVATE METHODS
    // ------------------

    function _validateEVMScriptCallData(address[] memory _rewardPrograms, uint256[] memory _amounts)
        private
        view
    {
        require(_rewardPrograms.length == _amounts.length, ERROR_LENGTH_MISMATCH);
        require(_rewardPrograms.length > 0, ERROR_EMPTY_DATA);
        for (uint256 i = 0; i < _rewardPrograms.length; ++i) {
            require(_amounts[i] > 0, ERROR_ZERO_AMOUNT);
            require(
                rewardProgramsRegistry.isRewardProgram(_rewardPrograms[i]),
                ERROR_REWARD_PROGRAM_NOT_ALLOWED
            );
        }
    }

    function _decodeEVMScriptCallData(bytes memory _evmScriptCallData)
        private
        pure
        returns (address[] memory _rewardPrograms, uint256[] memory _amounts)
    {
        return abi.decode(_evmScriptCallData, (address[], uint256[]));
    }
}

Contract ABI

[{"inputs":[{"internalType":"address","name":"_trustedCaller","type":"address"},{"internalType":"address","name":"_rewardProgramsRegistry","type":"address"},{"internalType":"address","name":"_finance","type":"address"},{"internalType":"address","name":"_rewardToken","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"_creator","type":"address"},{"internalType":"bytes","name":"_evmScriptCallData","type":"bytes"}],"name":"createEVMScript","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"_evmScriptCallData","type":"bytes"}],"name":"decodeEVMScriptCallData","outputs":[{"internalType":"address[]","name":"_rewardPrograms","type":"address[]"},{"internalType":"uint256[]","name":"_amounts","type":"uint256[]"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"finance","outputs":[{"internalType":"contract IFinance","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardProgramsRegistry","outputs":[{"internalType":"contract RewardProgramsRegistry","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"rewardToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"trustedCaller","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"}]

61010060405234801561001157600080fd5b5060405162000dc638038062000dc6833981016040819052610032916100e6565b60408051808201909152601e81527f545255535445445f43414c4c45525f49535f5a45524f5f414444524553530000602082015284906001600160a01b0382166100985760405162461bcd60e51b815260040161008f919061013a565b60405180910390fd5b506001600160601b0319606091821b811660805292811b831660a05290811b821660c0529190911b1660e0525061018f565b80516001600160a01b03811681146100e157600080fd5b919050565b600080600080608085870312156100fc57600080fd5b610105856100ca565b9350610113602086016100ca565b9250610121604086016100ca565b915061012f606086016100ca565b905092959194509250565b600060208083528351808285015260005b818110156101675785810183015185820160400152820161014b565b81811115610179576000604083870101525b50601f01601f1916929092016040019392505050565b60805160601c60a05160601c60c05160601c60e05160601c610bd8620001ee6000396000818160d701526104c001526000818161011f015261027c01526000818160b00152610370015260008181606c015261017b0152610bd86000f3fe608060405234801561001057600080fd5b50600436106100625760003560e01c8063268f076014610067578063313b7b19146100ab5780633f052ae9146100d2578063ecf7c690146100f9578063f7c618c11461011a578063fea21c9c14610141575b600080fd5b61008e7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b0390911681526020015b60405180910390f35b61008e7f000000000000000000000000000000000000000000000000000000000000000081565b61008e7f000000000000000000000000000000000000000000000000000000000000000081565b61010c6101073660046108de565b610161565b6040516100a29291906109ff565b61008e7f000000000000000000000000000000000000000000000000000000000000000081565b61015461014f3660046107a3565b610176565b6040516100a29190610a76565b60608061016d836103a8565b91509150915091565b6060827f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316816001600160a01b0316146040518060400160405280601381526020017221a0a62622a92fa4a9afa327a92124a22222a760691b815250906102015760405162461bcd60e51b81526004016101f89190610a76565b60405180910390fd5b5060008061020e856103a8565b9150915061021c82826103bf565b6000825167ffffffffffffffff81111561023857610238610b74565b60405190808252806020026020018201604052801561026b57816020015b60608152602001906001900390816102565790505b50905060005b835181101561036a577f00000000000000000000000000000000000000000000000000000000000000008482815181106102ad576102ad610b5e565b60200260200101518483815181106102c7576102c7610b5e565b602002602001015160405160200161032d939291906001600160a01b03938416815291909216602082015260408101919091526080606082018190526015908201527405265776172642070726f6772616d20746f7020757605c1b60a082015260c00190565b60405160208183030381529060405282828151811061034e5761034e610b5e565b60200260200101819052508061036390610b2d565b9050610271565b5061039d7f0000000000000000000000000000000000000000000000000000000000000000637b1b242360e11b836105ec565b979650505050505050565b6060808280602001905181019061016d91906107f3565b80518251146040518060400160405280600f81526020016e0988a9c8ea890be9a92a69a82a8869608b1b8152509061040a5760405162461bcd60e51b81526004016101f89190610a76565b5060008251116040518060400160405280600a815260200169454d5054595f4441544160b01b815250906104515760405162461bcd60e51b81526004016101f89190610a76565b5060005b82518110156105e757600082828151811061047257610472610b5e565b6020026020010151116040518060400160405280600b81526020016a16915493d7d05353d5539560aa1b815250906104bd5760405162461bcd60e51b81526004016101f89190610a76565b507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316639525581c8483815181106104ff576104ff610b5e565b60200260200101516040518263ffffffff1660e01b815260040161053291906001600160a01b0391909116815260200190565b60206040518083038186803b15801561054a57600080fd5b505afa15801561055e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061058291906108b5565b6040518060400160405280601a81526020017f5245574152445f50524f4752414d5f4e4f545f414c4c4f574544000000000000815250906105d65760405162461bcd60e51b81526004016101f89190610a76565b506105e081610b2d565b9050610455565b505050565b606060005b825181101561069157818584838151811061060e5761060e610b5e565b60200260200101515160046106239190610ade565b8686858151811061063657610636610b5e565b60200260200101516040516020016106519493929190610947565b60408051601f198184030181529082905261066f92916020016109d0565b60405160208183030381529060405291508061068a90610b2d565b90506105f1565b50600160e01b816040516020016106a992919061099f565b60405160208183030381529060405290509392505050565b600082601f8301126106d257600080fd5b815160206106e76106e283610aba565b610a89565b80838252828201915082860187848660051b890101111561070757600080fd5b60005b858110156107265781518452928401929084019060010161070a565b5090979650505050505050565b600082601f83011261074457600080fd5b813567ffffffffffffffff81111561075e5761075e610b74565b610771601f8201601f1916602001610a89565b81815284602083860101111561078657600080fd5b816020850160208301376000918101602001919091529392505050565b600080604083850312156107b657600080fd5b82356107c181610b8a565b9150602083013567ffffffffffffffff8111156107dd57600080fd5b6107e985828601610733565b9150509250929050565b6000806040838503121561080657600080fd5b825167ffffffffffffffff8082111561081e57600080fd5b818501915085601f83011261083257600080fd5b815160206108426106e283610aba565b8083825282820191508286018a848660051b890101111561086257600080fd5b600096505b8487101561088e57805161087a81610b8a565b835260019690960195918301918301610867565b50918801519196509093505050808211156108a857600080fd5b506107e9858286016106c1565b6000602082840312156108c757600080fd5b815180151581146108d757600080fd5b9392505050565b6000602082840312156108f057600080fd5b813567ffffffffffffffff81111561090757600080fd5b61091384828501610733565b949350505050565b60008151808452610933816020860160208601610afd565b601f01601f19169290920160200192915050565b6bffffffffffffffffffffffff19606086901b1681526001600160e01b031960e085901b8116601483015283166018820152815160009061098f81601c850160208701610afd565b91909101601c0195945050505050565b6001600160e01b03198316815281516000906109c2816004850160208701610afd565b919091016004019392505050565b600083516109e2818460208801610afd565b8351908301906109f6818360208801610afd565b01949350505050565b604080825283519082018190526000906020906060840190828701845b82811015610a415781516001600160a01b031684529284019290840190600101610a1c565b5050508381038285015284518082528583019183019060005b8181101561072657835183529284019291840191600101610a5a565b6020815260006108d7602083018461091b565b604051601f8201601f1916810167ffffffffffffffff81118282101715610ab257610ab2610b74565b604052919050565b600067ffffffffffffffff821115610ad457610ad4610b74565b5060051b60200190565b600063ffffffff8083168185168083038211156109f6576109f6610b48565b60005b83811015610b18578181015183820152602001610b00565b83811115610b27576000848401525b50505050565b6000600019821415610b4157610b41610b48565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b0381168114610b9f57600080fd5b5056fea26469706673582212202917cd3f5a591a57d448cc6d3fcf34059fa861f3547a324b89e05e4f35e0b79564736f6c63430008060033000000000000000000000000b9b953bb58411d7932d76a2493e309c88f9f2e13000000000000000000000000648c8be548f43eca4e482c0801ebccccfb94493100000000000000000000000072cd2b30020fb28de0dfa64d930a183eb732cf4600000000000000000000000006c6ab60f0ad054236d7d4faf98a5d33e852e717

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

000000000000000000000000b9b953bb58411d7932d76a2493e309c88f9f2e13000000000000000000000000648c8be548f43eca4e482c0801ebccccfb94493100000000000000000000000072cd2b30020fb28de0dfa64d930a183eb732cf4600000000000000000000000006c6ab60f0ad054236d7d4faf98a5d33e852e717

-----Decoded View---------------
Arg [0] : _trustedCaller (address): 0xB9b953Bb58411D7932D76A2493e309c88F9f2e13
Arg [1] : _rewardProgramsRegistry (address): 0x648C8Be548F43eca4e482C0801Ebccccfb944931
Arg [2] : _finance (address): 0x72cd2B30020FB28DE0DFa64d930A183eb732Cf46
Arg [3] : _rewardToken (address): 0x06c6Ab60F0Ad054236d7d4Faf98A5D33e852E717

-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 000000000000000000000000b9b953bb58411d7932d76a2493e309c88f9f2e13
Arg [1] : 000000000000000000000000648c8be548f43eca4e482c0801ebccccfb944931
Arg [2] : 00000000000000000000000072cd2b30020fb28de0dfa64d930a183eb732cf46
Arg [3] : 00000000000000000000000006c6ab60f0ad054236d7d4faf98a5d33e852e717


Deployed ByteCode Sourcemap

24969:4248:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;587:38;;;;;;;;-1:-1:-1;;;;;5382:32:1;;;5364:51;;5352:2;5337:18;587:38:0;;;;;;;;25512:33;;;;;25691:62;;;;;28017:252;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;:::i;25595:36::-;;;;;26617:965;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;28017:252::-;28133:32;28167:25;28217:44;28242:18;28217:24;:44::i;:::-;28210:51;;;;28017:252;;;:::o;26617:965::-;26798:12;26770:8;887:13;-1:-1:-1;;;;;876:24:0;:7;-1:-1:-1;;;;;876:24:0;;902:25;;;;;;;;;;;;;-1:-1:-1;;;902:25:0;;;868:60;;;;;-1:-1:-1;;;868:60:0;;;;;;;;:::i;:::-;;;;;;;;;;26829:31:::1;26862:24:::0;26903:44:::1;26928:18;26903:24;:44::i;:::-;26828:119;;;;26960:51;26987:14;27003:7;26960:26;:51::i;:::-;27024:33;27072:14;:21;27060:34;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;27024:70;;27110:9;27105:265;27129:14;:21;27125:1;:25;27105:265;;;27225:11;27255:14;27270:1;27255:17;;;;;;;;:::i;:::-;;;;;;;27291:7;27299:1;27291:10;;;;;;;;:::i;:::-;;;;;;;27196:162;;;;;;;;;-1:-1:-1::0;;;;;5750:15:1;;;5732:34;;5802:15;;;;5797:2;5782:18;;5775:43;5849:2;5834:18;;5827:34;;;;5897:3;5892:2;5877:18;;5870:31;;;5938:2;5917:19;;;5910:31;-1:-1:-1;;;5712:3:1;5957:19;;5950:52;6034:3;6019:19;;5684:360;27196:162:0::1;;;;;;;;;;;;;27172:18;27191:1;27172:21;;;;;;;;:::i;:::-;;;;;;:186;;;;27152:3;;;;:::i;:::-;;;27105:265;;;-1:-1:-1::0;27400:174:0::1;27459:7;-1:-1:-1::0;;;27541:18:0;27400:32:::1;:174::i;:::-;27380:194:::0;26617:965;-1:-1:-1;;;;;;;26617:965:0:o;28952:262::-;29068:32;29102:25;29163:18;29152:54;;;;;;;;;;;;:::i;28357:587::-;28535:8;:15;28509;:22;:41;28552:21;;;;;;;;;;;;;-1:-1:-1;;;28552:21:0;;;28501:73;;;;;-1:-1:-1;;;28501:73:0;;;;;;;;:::i;:::-;;28618:1;28593:15;:22;:26;28621:16;;;;;;;;;;;;;-1:-1:-1;;;28621:16:0;;;28585:53;;;;;-1:-1:-1;;;28585:53:0;;;;;;;;:::i;:::-;;28654:9;28649:288;28673:15;:22;28669:1;:26;28649:288;;;28739:1;28725:8;28734:1;28725:11;;;;;;;;:::i;:::-;;;;;;;:15;28742:17;;;;;;;;;;;;;-1:-1:-1;;;28742:17:0;;;28717:43;;;;;-1:-1:-1;;;28717:43:0;;;;;;;;:::i;:::-;;28801:22;-1:-1:-1;;;;;28801:38:0;;28840:15;28856:1;28840:18;;;;;;;;:::i;:::-;;;;;;;28801:58;;;;;;;;;;;;;;-1:-1:-1;;;;;5382:32:1;;;;5364:51;;5352:2;5337:18;;5319:102;28801:58:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;28878:32;;;;;;;;;;;;;;;;;28775:150;;;;;-1:-1:-1;;;28775:150:0;;;;;;;;:::i;:::-;-1:-1:-1;28697:3:0;;;:::i;:::-;;;28649:288;;;;28357:587;;:::o;21992:619::-;22140:23;22181:9;22176:371;22200:18;:25;22196:1;:29;22176:371;;;22291:10;22359:3;22392:18;22411:1;22392:21;;;;;;;;:::i;:::-;;;;;;;:28;22424:1;22385:40;;;;:::i;:::-;22448:9;22480:18;22499:1;22480:21;;;;;;;;:::i;:::-;;;;;;;22320:200;;;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;22320:200:0;;;;;;;;;;22260:275;;;22320:200;22260:275;;:::i;:::-;;;;;;;;;;;;;22247:288;;22227:3;;;;:::i;:::-;;;22176:371;;;;-1:-1:-1;;;22592:10:0;22570:33;;;;;;;;;:::i;:::-;;;;;;;;;;;;;22557:46;;21992:619;;;;;:::o;14:670:1:-;79:5;132:3;125:4;117:6;113:17;109:27;99:2;;150:1;147;140:12;99:2;179:6;173:13;205:4;229:60;245:43;285:2;245:43;:::i;:::-;229:60;:::i;:::-;311:3;335:2;330:3;323:15;363:2;358:3;354:12;347:19;;398:2;390:6;386:15;450:3;445:2;439;436:1;432:10;424:6;420:23;416:32;413:41;410:2;;;467:1;464;457:12;410:2;489:1;499:156;513:2;510:1;507:9;499:156;;;570:10;;558:23;;601:12;;;;633;;;;531:1;524:9;499:156;;;-1:-1:-1;673:5:1;;89:595;-1:-1:-1;;;;;;;89:595:1:o;689:530::-;731:5;784:3;777:4;769:6;765:17;761:27;751:2;;802:1;799;792:12;751:2;838:6;825:20;864:18;860:2;857:26;854:2;;;886:18;;:::i;:::-;930:55;973:2;954:13;;-1:-1:-1;;950:27:1;979:4;946:38;930:55;:::i;:::-;1010:2;1001:7;994:19;1056:3;1049:4;1044:2;1036:6;1032:15;1028:26;1025:35;1022:2;;;1073:1;1070;1063:12;1022:2;1138;1131:4;1123:6;1119:17;1112:4;1103:7;1099:18;1086:55;1186:1;1161:16;;;1179:4;1157:27;1150:38;;;;1165:7;741:478;-1:-1:-1;;;741:478:1:o;1224:455::-;1301:6;1309;1362:2;1350:9;1341:7;1337:23;1333:32;1330:2;;;1378:1;1375;1368:12;1330:2;1417:9;1404:23;1436:31;1461:5;1436:31;:::i;:::-;1486:5;-1:-1:-1;1542:2:1;1527:18;;1514:32;1569:18;1558:30;;1555:2;;;1601:1;1598;1591:12;1555:2;1624:49;1665:7;1656:6;1645:9;1641:22;1624:49;:::i;:::-;1614:59;;;1320:359;;;;;:::o;1684:1220::-;1813:6;1821;1874:2;1862:9;1853:7;1849:23;1845:32;1842:2;;;1890:1;1887;1880:12;1842:2;1923:9;1917:16;1952:18;1993:2;1985:6;1982:14;1979:2;;;2009:1;2006;1999:12;1979:2;2047:6;2036:9;2032:22;2022:32;;2092:7;2085:4;2081:2;2077:13;2073:27;2063:2;;2114:1;2111;2104:12;2063:2;2143;2137:9;2165:4;2189:60;2205:43;2245:2;2205:43;:::i;2189:60::-;2271:3;2295:2;2290:3;2283:15;2323:2;2318:3;2314:12;2307:19;;2354:2;2350;2346:11;2402:7;2397:2;2391;2388:1;2384:10;2380:2;2376:19;2372:28;2369:41;2366:2;;;2423:1;2420;2413:12;2366:2;2445:1;2436:10;;2455:231;2469:2;2466:1;2463:9;2455:231;;;2533:3;2527:10;2550:31;2575:5;2550:31;:::i;:::-;2594:18;;2487:1;2480:9;;;;;2632:12;;;;2664;;2455:231;;;-1:-1:-1;2741:18:1;;;2735:25;2705:5;;-1:-1:-1;2735:25:1;;-1:-1:-1;;;2772:16:1;;;2769:2;;;2801:1;2798;2791:12;2769:2;;2824:74;2890:7;2879:8;2868:9;2864:24;2824:74;:::i;2909:277::-;2976:6;3029:2;3017:9;3008:7;3004:23;3000:32;2997:2;;;3045:1;3042;3035:12;2997:2;3077:9;3071:16;3130:5;3123:13;3116:21;3109:5;3106:32;3096:2;;3152:1;3149;3142:12;3096:2;3175:5;2987:199;-1:-1:-1;;;2987:199:1:o;3191:320::-;3259:6;3312:2;3300:9;3291:7;3287:23;3283:32;3280:2;;;3328:1;3325;3318:12;3280:2;3368:9;3355:23;3401:18;3393:6;3390:30;3387:2;;;3433:1;3430;3423:12;3387:2;3456:49;3497:7;3488:6;3477:9;3473:22;3456:49;:::i;:::-;3446:59;3270:241;-1:-1:-1;;;;3270:241:1:o;3516:257::-;3557:3;3595:5;3589:12;3622:6;3617:3;3610:19;3638:63;3694:6;3687:4;3682:3;3678:14;3671:4;3664:5;3660:16;3638:63;:::i;:::-;3755:2;3734:15;-1:-1:-1;;3730:29:1;3721:39;;;;3762:4;3717:50;;3565:208;-1:-1:-1;;3565:208:1:o;3778:588::-;-1:-1:-1;;4025:2:1;4021:15;;;4017:53;4005:66;;-1:-1:-1;;;;;;4094:3:1;4144:16;;;4140:25;;4135:2;4126:12;;4119:47;4196:15;;4191:2;4182:12;;4175:37;4235:13;;-1:-1:-1;;4257:62:1;4235:13;4307:2;4298:12;;4291:4;4279:17;;4257:62;:::i;:::-;4339:16;;;;4357:2;4335:25;;3995:371;-1:-1:-1;;;;;3995:371:1:o;4371:::-;-1:-1:-1;;;;;;4556:33:1;;4544:46;;4613:13;;4526:3;;4635:61;4613:13;4685:1;4676:11;;4669:4;4657:17;;4635:61;:::i;:::-;4716:16;;;;4734:1;4712:24;;4534:208;-1:-1:-1;;;4534:208:1:o;4747:466::-;4922:3;4960:6;4954:13;4976:53;5022:6;5017:3;5010:4;5002:6;4998:17;4976:53;:::i;:::-;5092:13;;5051:16;;;;5114:57;5092:13;5051:16;5148:4;5136:17;;5114:57;:::i;:::-;5187:20;;4930:283;-1:-1:-1;;;;4930:283:1:o;6049:1178::-;6317:2;6329:21;;;6399:13;;6302:18;;;6421:22;;;6269:4;;6496;;6474:2;6459:18;;;6523:15;;;6269:4;6566:195;6580:6;6577:1;6574:13;6566:195;;;6645:13;;-1:-1:-1;;;;;6641:39:1;6629:52;;6701:12;;;;6736:15;;;;6677:1;6595:9;6566:195;;;-1:-1:-1;;;6797:19:1;;;6777:18;;;6770:47;6867:13;;6889:21;;;6965:15;;;;6928:12;;;7000:1;7010:189;7026:8;7021:3;7018:17;7010:189;;;7095:15;;7081:30;;7172:17;;;;7133:14;;;;7054:1;7045:11;7010:189;;7232:217;7379:2;7368:9;7361:21;7342:4;7399:44;7439:2;7428:9;7424:18;7416:6;7399:44;:::i;8140:275::-;8211:2;8205:9;8276:2;8257:13;;-1:-1:-1;;8253:27:1;8241:40;;8311:18;8296:34;;8332:22;;;8293:62;8290:2;;;8358:18;;:::i;:::-;8394:2;8387:22;8185:230;;-1:-1:-1;8185:230:1:o;8420:183::-;8480:4;8513:18;8505:6;8502:30;8499:2;;;8535:18;;:::i;:::-;-1:-1:-1;8580:1:1;8576:14;8592:4;8572:25;;8489:114::o;8608:228::-;8647:3;8675:10;8712:2;8709:1;8705:10;8742:2;8739:1;8735:10;8773:3;8769:2;8765:12;8760:3;8757:21;8754:2;;;8781:18;;:::i;8841:258::-;8913:1;8923:113;8937:6;8934:1;8931:13;8923:113;;;9013:11;;;9007:18;8994:11;;;8987:39;8959:2;8952:10;8923:113;;;9054:6;9051:1;9048:13;9045:2;;;9089:1;9080:6;9075:3;9071:16;9064:27;9045:2;;8894:205;;;:::o;9104:135::-;9143:3;-1:-1:-1;;9164:17:1;;9161:2;;;9184:18;;:::i;:::-;-1:-1:-1;9231:1:1;9220:13;;9151:88::o;9244:127::-;9305:10;9300:3;9296:20;9293:1;9286:31;9336:4;9333:1;9326:15;9360:4;9357:1;9350:15;9376:127;9437:10;9432:3;9428:20;9425:1;9418:31;9468:4;9465:1;9458:15;9492:4;9489:1;9482:15;9508:127;9569:10;9564:3;9560:20;9557:1;9550:31;9600:4;9597:1;9590:15;9624:4;9621:1;9614:15;9640:131;-1:-1:-1;;;;;9715:31:1;;9705:42;;9695:2;;9761:1;9758;9751:12;9695:2;9685:86;:::o

Swarm Source

ipfs://2917cd3f5a591a57d448cc6d3fcf34059fa861f3547a324b89e05e4f35e0b795
Block Transaction Difficulty Gas Used Reward
Block Uncle Number Difficulty Gas Used Reward
Loading

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.