S Price: $0.486452 (+7.85%)

Contract

0xD3a6b1a9026485bbd39a75A352E968711e21744b

Overview

S Balance

Sonic LogoSonic LogoSonic Logo0 S

S Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Execute134620802025-03-13 13:43:191 hr ago1741873399IN
0xD3a6b1a9...11e21744b
0 S0.0059594155
Execute134620342025-03-13 13:43:011 hr ago1741873381IN
0xD3a6b1a9...11e21744b
0 S0.0059594155
Schedule Set Tok...133490682025-03-13 0:19:0014 hrs ago1741825140IN
0xD3a6b1a9...11e21744b
0 S0.0036550255
Schedule Set Tok...133490632025-03-13 0:18:5814 hrs ago1741825138IN
0xD3a6b1a9...11e21744b
0 S0.0036550255
Schedule Set Tok...132163152025-03-12 9:05:1629 hrs ago1741770316IN
0xD3a6b1a9...11e21744b
0 S0.0036550255
Schedule Set Tok...131264612025-03-11 21:26:3041 hrs ago1741728390IN
0xD3a6b1a9...11e21744b
0 S0.0036550255
Schedule Add Con...130115852025-03-11 8:38:022 days ago1741682282IN
0xD3a6b1a9...11e21744b
0 S0.0035192855
Schedule Add Con...130115812025-03-11 8:38:002 days ago1741682280IN
0xD3a6b1a9...11e21744b
0 S0.0035192855
Execute129444672025-03-10 23:57:222 days ago1741651042IN
0xD3a6b1a9...11e21744b
0 S0.0063163155
Execute129444652025-03-10 23:57:202 days ago1741651040IN
0xD3a6b1a9...11e21744b
0 S0.0059324155
Schedule Set Tok...125476672025-03-08 23:52:504 days ago1741477970IN
0xD3a6b1a9...11e21744b
0 S0.0036550255
Schedule Set Tok...125476632025-03-08 23:52:494 days ago1741477969IN
0xD3a6b1a9...11e21744b
0 S0.0036550255

Parent Transaction Hash Block From To
View All Internal Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
StoutTimelock

Compiler Version
v0.8.24+commit.e11b9ed9

Optimization Enabled:
No with 200 runs

Other Settings:
paris EvmVersion
File 1 of 19 : StoutTimelock.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.24 <0.9.0;

import {TimelockController} from "@openzeppelin/contracts/governance/TimelockController.sol";
import {OracleChainlink} from "./oracle/OracleChainlink.sol";

interface IController {
    function addController(address controller) external;
}

/**
 * @title StoutTimelock
 * @notice Timelock controller for managing vault and oracle operations
 * @dev Inherits OpenZeppelin's TimelockController for secure time-delayed operations
 */
contract StoutTimelock is TimelockController {
    /// @notice Fixed delay for all operations
    uint256 public constant DELAY = 48 hours;
    /// @notice The vault contract that will receive controller management calls
    address public immutable stoutVault;
    /// @notice The oracle contract that will receive configuration calls
    address public immutable oracleChainlink;
    /// @notice Thrown when a vault or oracle address is zero
    error InvalidAddress();
    // Custom errors
    error SchedulingFailed();

    /**
     * @notice Initialize the timelock with the vault and oracle addresses
     * @param vault_ The StoutVault contract address
     * @param oracle_ The Chainlink oracle contract address
     * @param proposers List of addresses that can propose operations
     * @param executors List of addresses that can execute operations
     * @param admin Optional admin address
     */
    constructor(
        address vault_,
        address oracle_,
        address[] memory proposers,
        address[] memory executors,
        address admin
    ) TimelockController(DELAY, proposers, executors, admin) {
        if (vault_ == address(0) || oracle_ == address(0)) {
            revert InvalidAddress();
        }
        stoutVault = vault_;
        oracleChainlink = oracle_;
    }

    /**
     * @notice Schedule adding a controller to the vault
     * @param controller The controller address to add
     */
    function scheduleAddController(
        address controller
    ) external onlyRole(PROPOSER_ROLE) {
        bytes memory data = abi.encodeWithSelector(
            IController.addController.selector,
            controller
        );
        _scheduleOperation(stoutVault, data, keccak256(abi.encode(controller)));
    }

    /**
     * @notice Schedule setting a token configuration in the oracle
     * @param asset The token address to configure
     * @param feed The price feed address for the token
     */
    function scheduleSetTokenConfig(
        address asset,
        address feed
    ) external onlyRole(PROPOSER_ROLE) {
        if (asset == address(0) || feed == address(0)) {
            revert InvalidAddress();
        }
        OracleChainlink.TokenConfig memory config = OracleChainlink
            .TokenConfig({asset: asset, feed: feed});
        bytes memory data = abi.encodeWithSelector(
            OracleChainlink.setTokenConfig.selector,
            config
        );
        _scheduleOperation(
            oracleChainlink,
            data,
            keccak256(abi.encode(asset, feed))
        );
    }

    /**
     * @notice Helper function to schedule a single operation using delegatecall
     */
    function _scheduleOperation(
        address target,
        bytes memory data,
        bytes32 salt
    ) private {
        // Create a separate contract call to handle the scheduling
        (bool success, ) = address(this).delegatecall(
            abi.encodeWithSelector(
                TimelockController.schedule.selector,
                target,
                0, // value
                data,
                bytes32(0), // predecessor
                salt,
                DELAY
            )
        );
        if (!success) revert SchedulingFailed();
    }
}

File 2 of 19 : AccessControl.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/AccessControl.sol)

pragma solidity ^0.8.20;

import {IAccessControl} from "./IAccessControl.sol";
import {Context} from "../utils/Context.sol";
import {ERC165} from "../utils/introspection/ERC165.sol";

/**
 * @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:
 *
 * ```solidity
 * 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}:
 *
 * ```solidity
 * 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. We recommend using {AccessControlDefaultAdminRules}
 * to enforce additional security measures for this role.
 */
abstract contract AccessControl is Context, IAccessControl, ERC165 {
    struct RoleData {
        mapping(address account => bool) hasRole;
        bytes32 adminRole;
    }

    mapping(bytes32 role => RoleData) private _roles;

    bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;

    /**
     * @dev Modifier that checks that an account has a specific role. Reverts
     * with an {AccessControlUnauthorizedAccount} error including the required role.
     */
    modifier onlyRole(bytes32 role) {
        _checkRole(role);
        _;
    }

    /**
     * @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 virtual returns (bool) {
        return _roles[role].hasRole[account];
    }

    /**
     * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `_msgSender()`
     * is missing `role`. Overriding this function changes the behavior of the {onlyRole} modifier.
     */
    function _checkRole(bytes32 role) internal view virtual {
        _checkRole(role, _msgSender());
    }

    /**
     * @dev Reverts with an {AccessControlUnauthorizedAccount} error if `account`
     * is missing `role`.
     */
    function _checkRole(bytes32 role, address account) internal view virtual {
        if (!hasRole(role, account)) {
            revert AccessControlUnauthorizedAccount(account, role);
        }
    }

    /**
     * @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 virtual 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.
     *
     * May emit a {RoleGranted} event.
     */
    function grantRole(bytes32 role, address account) public virtual 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.
     *
     * May emit a {RoleRevoked} event.
     */
    function revokeRole(bytes32 role, address account) public virtual 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 revoked `role`, emits a {RoleRevoked}
     * event.
     *
     * Requirements:
     *
     * - the caller must be `callerConfirmation`.
     *
     * May emit a {RoleRevoked} event.
     */
    function renounceRole(bytes32 role, address callerConfirmation) public virtual {
        if (callerConfirmation != _msgSender()) {
            revert AccessControlBadConfirmation();
        }

        _revokeRole(role, callerConfirmation);
    }

    /**
     * @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);
    }

    /**
     * @dev Attempts to grant `role` to `account` and returns a boolean indicating if `role` was granted.
     *
     * Internal function without access restriction.
     *
     * May emit a {RoleGranted} event.
     */
    function _grantRole(bytes32 role, address account) internal virtual returns (bool) {
        if (!hasRole(role, account)) {
            _roles[role].hasRole[account] = true;
            emit RoleGranted(role, account, _msgSender());
            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Attempts to revoke `role` to `account` and returns a boolean indicating if `role` was revoked.
     *
     * Internal function without access restriction.
     *
     * May emit a {RoleRevoked} event.
     */
    function _revokeRole(bytes32 role, address account) internal virtual returns (bool) {
        if (hasRole(role, account)) {
            _roles[role].hasRole[account] = false;
            emit RoleRevoked(role, account, _msgSender());
            return true;
        } else {
            return false;
        }
    }
}

File 3 of 19 : IAccessControl.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (access/IAccessControl.sol)

pragma solidity ^0.8.20;

/**
 * @dev External interface of AccessControl declared to support ERC-165 detection.
 */
interface IAccessControl {
    /**
     * @dev The `account` is missing a role.
     */
    error AccessControlUnauthorizedAccount(address account, bytes32 neededRole);

    /**
     * @dev The caller of a function is not the expected one.
     *
     * NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.
     */
    error AccessControlBadConfirmation();

    /**
     * @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.
     */
    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. This account bears the admin role (for the granted role).
     * Expected in cases where the role was granted using the internal {AccessControl-_grantRole}.
     */
    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 `callerConfirmation`.
     */
    function renounceRole(bytes32 role, address callerConfirmation) external;
}

File 4 of 19 : TimelockController.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (governance/TimelockController.sol)

pragma solidity ^0.8.20;

import {AccessControl} from "../access/AccessControl.sol";
import {ERC721Holder} from "../token/ERC721/utils/ERC721Holder.sol";
import {ERC1155Holder} from "../token/ERC1155/utils/ERC1155Holder.sol";
import {Address} from "../utils/Address.sol";

/**
 * @dev Contract module which acts as a timelocked controller. When set as the
 * owner of an `Ownable` smart contract, it enforces a timelock on all
 * `onlyOwner` maintenance operations. This gives time for users of the
 * controlled contract to exit before a potentially dangerous maintenance
 * operation is applied.
 *
 * By default, this contract is self administered, meaning administration tasks
 * have to go through the timelock process. The proposer (resp executor) role
 * is in charge of proposing (resp executing) operations. A common use case is
 * to position this {TimelockController} as the owner of a smart contract, with
 * a multisig or a DAO as the sole proposer.
 */
contract TimelockController is AccessControl, ERC721Holder, ERC1155Holder {
    bytes32 public constant PROPOSER_ROLE = keccak256("PROPOSER_ROLE");
    bytes32 public constant EXECUTOR_ROLE = keccak256("EXECUTOR_ROLE");
    bytes32 public constant CANCELLER_ROLE = keccak256("CANCELLER_ROLE");
    uint256 internal constant _DONE_TIMESTAMP = uint256(1);

    mapping(bytes32 id => uint256) private _timestamps;
    uint256 private _minDelay;

    enum OperationState {
        Unset,
        Waiting,
        Ready,
        Done
    }

    /**
     * @dev Mismatch between the parameters length for an operation call.
     */
    error TimelockInvalidOperationLength(uint256 targets, uint256 payloads, uint256 values);

    /**
     * @dev The schedule operation doesn't meet the minimum delay.
     */
    error TimelockInsufficientDelay(uint256 delay, uint256 minDelay);

    /**
     * @dev The current state of an operation is not as required.
     * The `expectedStates` is a bitmap with the bits enabled for each OperationState enum position
     * counting from right to left.
     *
     * See {_encodeStateBitmap}.
     */
    error TimelockUnexpectedOperationState(bytes32 operationId, bytes32 expectedStates);

    /**
     * @dev The predecessor to an operation not yet done.
     */
    error TimelockUnexecutedPredecessor(bytes32 predecessorId);

    /**
     * @dev The caller account is not authorized.
     */
    error TimelockUnauthorizedCaller(address caller);

    /**
     * @dev Emitted when a call is scheduled as part of operation `id`.
     */
    event CallScheduled(
        bytes32 indexed id,
        uint256 indexed index,
        address target,
        uint256 value,
        bytes data,
        bytes32 predecessor,
        uint256 delay
    );

    /**
     * @dev Emitted when a call is performed as part of operation `id`.
     */
    event CallExecuted(bytes32 indexed id, uint256 indexed index, address target, uint256 value, bytes data);

    /**
     * @dev Emitted when new proposal is scheduled with non-zero salt.
     */
    event CallSalt(bytes32 indexed id, bytes32 salt);

    /**
     * @dev Emitted when operation `id` is cancelled.
     */
    event Cancelled(bytes32 indexed id);

    /**
     * @dev Emitted when the minimum delay for future operations is modified.
     */
    event MinDelayChange(uint256 oldDuration, uint256 newDuration);

    /**
     * @dev Initializes the contract with the following parameters:
     *
     * - `minDelay`: initial minimum delay in seconds for operations
     * - `proposers`: accounts to be granted proposer and canceller roles
     * - `executors`: accounts to be granted executor role
     * - `admin`: optional account to be granted admin role; disable with zero address
     *
     * IMPORTANT: The optional admin can aid with initial configuration of roles after deployment
     * without being subject to delay, but this role should be subsequently renounced in favor of
     * administration through timelocked proposals. Previous versions of this contract would assign
     * this admin to the deployer automatically and should be renounced as well.
     */
    constructor(uint256 minDelay, address[] memory proposers, address[] memory executors, address admin) {
        // self administration
        _grantRole(DEFAULT_ADMIN_ROLE, address(this));

        // optional admin
        if (admin != address(0)) {
            _grantRole(DEFAULT_ADMIN_ROLE, admin);
        }

        // register proposers and cancellers
        for (uint256 i = 0; i < proposers.length; ++i) {
            _grantRole(PROPOSER_ROLE, proposers[i]);
            _grantRole(CANCELLER_ROLE, proposers[i]);
        }

        // register executors
        for (uint256 i = 0; i < executors.length; ++i) {
            _grantRole(EXECUTOR_ROLE, executors[i]);
        }

        _minDelay = minDelay;
        emit MinDelayChange(0, minDelay);
    }

    /**
     * @dev Modifier to make a function callable only by a certain role. In
     * addition to checking the sender's role, `address(0)` 's role is also
     * considered. Granting a role to `address(0)` is equivalent to enabling
     * this role for everyone.
     */
    modifier onlyRoleOrOpenRole(bytes32 role) {
        if (!hasRole(role, address(0))) {
            _checkRole(role, _msgSender());
        }
        _;
    }

    /**
     * @dev Contract might receive/hold ETH as part of the maintenance process.
     */
    receive() external payable {}

    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(
        bytes4 interfaceId
    ) public view virtual override(AccessControl, ERC1155Holder) returns (bool) {
        return super.supportsInterface(interfaceId);
    }

    /**
     * @dev Returns whether an id corresponds to a registered operation. This
     * includes both Waiting, Ready, and Done operations.
     */
    function isOperation(bytes32 id) public view returns (bool) {
        return getOperationState(id) != OperationState.Unset;
    }

    /**
     * @dev Returns whether an operation is pending or not. Note that a "pending" operation may also be "ready".
     */
    function isOperationPending(bytes32 id) public view returns (bool) {
        OperationState state = getOperationState(id);
        return state == OperationState.Waiting || state == OperationState.Ready;
    }

    /**
     * @dev Returns whether an operation is ready for execution. Note that a "ready" operation is also "pending".
     */
    function isOperationReady(bytes32 id) public view returns (bool) {
        return getOperationState(id) == OperationState.Ready;
    }

    /**
     * @dev Returns whether an operation is done or not.
     */
    function isOperationDone(bytes32 id) public view returns (bool) {
        return getOperationState(id) == OperationState.Done;
    }

    /**
     * @dev Returns the timestamp at which an operation becomes ready (0 for
     * unset operations, 1 for done operations).
     */
    function getTimestamp(bytes32 id) public view virtual returns (uint256) {
        return _timestamps[id];
    }

    /**
     * @dev Returns operation state.
     */
    function getOperationState(bytes32 id) public view virtual returns (OperationState) {
        uint256 timestamp = getTimestamp(id);
        if (timestamp == 0) {
            return OperationState.Unset;
        } else if (timestamp == _DONE_TIMESTAMP) {
            return OperationState.Done;
        } else if (timestamp > block.timestamp) {
            return OperationState.Waiting;
        } else {
            return OperationState.Ready;
        }
    }

    /**
     * @dev Returns the minimum delay in seconds for an operation to become valid.
     *
     * This value can be changed by executing an operation that calls `updateDelay`.
     */
    function getMinDelay() public view virtual returns (uint256) {
        return _minDelay;
    }

    /**
     * @dev Returns the identifier of an operation containing a single
     * transaction.
     */
    function hashOperation(
        address target,
        uint256 value,
        bytes calldata data,
        bytes32 predecessor,
        bytes32 salt
    ) public pure virtual returns (bytes32) {
        return keccak256(abi.encode(target, value, data, predecessor, salt));
    }

    /**
     * @dev Returns the identifier of an operation containing a batch of
     * transactions.
     */
    function hashOperationBatch(
        address[] calldata targets,
        uint256[] calldata values,
        bytes[] calldata payloads,
        bytes32 predecessor,
        bytes32 salt
    ) public pure virtual returns (bytes32) {
        return keccak256(abi.encode(targets, values, payloads, predecessor, salt));
    }

    /**
     * @dev Schedule an operation containing a single transaction.
     *
     * Emits {CallSalt} if salt is nonzero, and {CallScheduled}.
     *
     * Requirements:
     *
     * - the caller must have the 'proposer' role.
     */
    function schedule(
        address target,
        uint256 value,
        bytes calldata data,
        bytes32 predecessor,
        bytes32 salt,
        uint256 delay
    ) public virtual onlyRole(PROPOSER_ROLE) {
        bytes32 id = hashOperation(target, value, data, predecessor, salt);
        _schedule(id, delay);
        emit CallScheduled(id, 0, target, value, data, predecessor, delay);
        if (salt != bytes32(0)) {
            emit CallSalt(id, salt);
        }
    }

    /**
     * @dev Schedule an operation containing a batch of transactions.
     *
     * Emits {CallSalt} if salt is nonzero, and one {CallScheduled} event per transaction in the batch.
     *
     * Requirements:
     *
     * - the caller must have the 'proposer' role.
     */
    function scheduleBatch(
        address[] calldata targets,
        uint256[] calldata values,
        bytes[] calldata payloads,
        bytes32 predecessor,
        bytes32 salt,
        uint256 delay
    ) public virtual onlyRole(PROPOSER_ROLE) {
        if (targets.length != values.length || targets.length != payloads.length) {
            revert TimelockInvalidOperationLength(targets.length, payloads.length, values.length);
        }

        bytes32 id = hashOperationBatch(targets, values, payloads, predecessor, salt);
        _schedule(id, delay);
        for (uint256 i = 0; i < targets.length; ++i) {
            emit CallScheduled(id, i, targets[i], values[i], payloads[i], predecessor, delay);
        }
        if (salt != bytes32(0)) {
            emit CallSalt(id, salt);
        }
    }

    /**
     * @dev Schedule an operation that is to become valid after a given delay.
     */
    function _schedule(bytes32 id, uint256 delay) private {
        if (isOperation(id)) {
            revert TimelockUnexpectedOperationState(id, _encodeStateBitmap(OperationState.Unset));
        }
        uint256 minDelay = getMinDelay();
        if (delay < minDelay) {
            revert TimelockInsufficientDelay(delay, minDelay);
        }
        _timestamps[id] = block.timestamp + delay;
    }

    /**
     * @dev Cancel an operation.
     *
     * Requirements:
     *
     * - the caller must have the 'canceller' role.
     */
    function cancel(bytes32 id) public virtual onlyRole(CANCELLER_ROLE) {
        if (!isOperationPending(id)) {
            revert TimelockUnexpectedOperationState(
                id,
                _encodeStateBitmap(OperationState.Waiting) | _encodeStateBitmap(OperationState.Ready)
            );
        }
        delete _timestamps[id];

        emit Cancelled(id);
    }

    /**
     * @dev Execute an (ready) operation containing a single transaction.
     *
     * Emits a {CallExecuted} event.
     *
     * Requirements:
     *
     * - the caller must have the 'executor' role.
     */
    // This function can reenter, but it doesn't pose a risk because _afterCall checks that the proposal is pending,
    // thus any modifications to the operation during reentrancy should be caught.
    // slither-disable-next-line reentrancy-eth
    function execute(
        address target,
        uint256 value,
        bytes calldata payload,
        bytes32 predecessor,
        bytes32 salt
    ) public payable virtual onlyRoleOrOpenRole(EXECUTOR_ROLE) {
        bytes32 id = hashOperation(target, value, payload, predecessor, salt);

        _beforeCall(id, predecessor);
        _execute(target, value, payload);
        emit CallExecuted(id, 0, target, value, payload);
        _afterCall(id);
    }

    /**
     * @dev Execute an (ready) operation containing a batch of transactions.
     *
     * Emits one {CallExecuted} event per transaction in the batch.
     *
     * Requirements:
     *
     * - the caller must have the 'executor' role.
     */
    // This function can reenter, but it doesn't pose a risk because _afterCall checks that the proposal is pending,
    // thus any modifications to the operation during reentrancy should be caught.
    // slither-disable-next-line reentrancy-eth
    function executeBatch(
        address[] calldata targets,
        uint256[] calldata values,
        bytes[] calldata payloads,
        bytes32 predecessor,
        bytes32 salt
    ) public payable virtual onlyRoleOrOpenRole(EXECUTOR_ROLE) {
        if (targets.length != values.length || targets.length != payloads.length) {
            revert TimelockInvalidOperationLength(targets.length, payloads.length, values.length);
        }

        bytes32 id = hashOperationBatch(targets, values, payloads, predecessor, salt);

        _beforeCall(id, predecessor);
        for (uint256 i = 0; i < targets.length; ++i) {
            address target = targets[i];
            uint256 value = values[i];
            bytes calldata payload = payloads[i];
            _execute(target, value, payload);
            emit CallExecuted(id, i, target, value, payload);
        }
        _afterCall(id);
    }

    /**
     * @dev Execute an operation's call.
     */
    function _execute(address target, uint256 value, bytes calldata data) internal virtual {
        (bool success, bytes memory returndata) = target.call{value: value}(data);
        Address.verifyCallResult(success, returndata);
    }

    /**
     * @dev Checks before execution of an operation's calls.
     */
    function _beforeCall(bytes32 id, bytes32 predecessor) private view {
        if (!isOperationReady(id)) {
            revert TimelockUnexpectedOperationState(id, _encodeStateBitmap(OperationState.Ready));
        }
        if (predecessor != bytes32(0) && !isOperationDone(predecessor)) {
            revert TimelockUnexecutedPredecessor(predecessor);
        }
    }

    /**
     * @dev Checks after execution of an operation's calls.
     */
    function _afterCall(bytes32 id) private {
        if (!isOperationReady(id)) {
            revert TimelockUnexpectedOperationState(id, _encodeStateBitmap(OperationState.Ready));
        }
        _timestamps[id] = _DONE_TIMESTAMP;
    }

    /**
     * @dev Changes the minimum timelock duration for future operations.
     *
     * Emits a {MinDelayChange} event.
     *
     * Requirements:
     *
     * - the caller must be the timelock itself. This can only be achieved by scheduling and later executing
     * an operation where the timelock is the target and the data is the ABI-encoded call to this function.
     */
    function updateDelay(uint256 newDelay) external virtual {
        address sender = _msgSender();
        if (sender != address(this)) {
            revert TimelockUnauthorizedCaller(sender);
        }
        emit MinDelayChange(_minDelay, newDelay);
        _minDelay = newDelay;
    }

    /**
     * @dev Encodes a `OperationState` into a `bytes32` representation where each bit enabled corresponds to
     * the underlying position in the `OperationState` enum. For example:
     *
     * 0x000...1000
     *   ^^^^^^----- ...
     *         ^---- Done
     *          ^--- Ready
     *           ^-- Waiting
     *            ^- Unset
     */
    function _encodeStateBitmap(OperationState operationState) internal pure returns (bytes32) {
        return bytes32(1 << uint8(operationState));
    }
}

File 5 of 19 : IERC1155Receiver.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC1155/IERC1155Receiver.sol)

pragma solidity ^0.8.20;

import {IERC165} from "../../utils/introspection/IERC165.sol";

/**
 * @dev Interface that must be implemented by smart contracts in order to receive
 * ERC-1155 token transfers.
 */
interface IERC1155Receiver is IERC165 {
    /**
     * @dev Handles the receipt of a single ERC-1155 token type. This function is
     * called at the end of a `safeTransferFrom` after the balance has been updated.
     *
     * NOTE: To accept the transfer, this must return
     * `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))`
     * (i.e. 0xf23a6e61, or its own function selector).
     *
     * @param operator The address which initiated the transfer (i.e. msg.sender)
     * @param from The address which previously owned the token
     * @param id The ID of the token being transferred
     * @param value The amount of tokens being transferred
     * @param data Additional data with no specified format
     * @return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` if transfer is allowed
     */
    function onERC1155Received(
        address operator,
        address from,
        uint256 id,
        uint256 value,
        bytes calldata data
    ) external returns (bytes4);

    /**
     * @dev Handles the receipt of a multiple ERC-1155 token types. This function
     * is called at the end of a `safeBatchTransferFrom` after the balances have
     * been updated.
     *
     * NOTE: To accept the transfer(s), this must return
     * `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))`
     * (i.e. 0xbc197c81, or its own function selector).
     *
     * @param operator The address which initiated the batch transfer (i.e. msg.sender)
     * @param from The address which previously owned the token
     * @param ids An array containing ids of each token being transferred (order and length must match values array)
     * @param values An array containing amounts of each token being transferred (order and length must match ids array)
     * @param data Additional data with no specified format
     * @return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` if transfer is allowed
     */
    function onERC1155BatchReceived(
        address operator,
        address from,
        uint256[] calldata ids,
        uint256[] calldata values,
        bytes calldata data
    ) external returns (bytes4);
}

File 6 of 19 : ERC1155Holder.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC1155/utils/ERC1155Holder.sol)

pragma solidity ^0.8.20;

import {IERC165, ERC165} from "../../../utils/introspection/ERC165.sol";
import {IERC1155Receiver} from "../IERC1155Receiver.sol";

/**
 * @dev Simple implementation of `IERC1155Receiver` that will allow a contract to hold ERC-1155 tokens.
 *
 * IMPORTANT: When inheriting this contract, you must include a way to use the received tokens, otherwise they will be
 * stuck.
 */
abstract contract ERC1155Holder is ERC165, IERC1155Receiver {
    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {
        return interfaceId == type(IERC1155Receiver).interfaceId || super.supportsInterface(interfaceId);
    }

    function onERC1155Received(
        address,
        address,
        uint256,
        uint256,
        bytes memory
    ) public virtual override returns (bytes4) {
        return this.onERC1155Received.selector;
    }

    function onERC1155BatchReceived(
        address,
        address,
        uint256[] memory,
        uint256[] memory,
        bytes memory
    ) public virtual override returns (bytes4) {
        return this.onERC1155BatchReceived.selector;
    }
}

File 7 of 19 : IERC721Receiver.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC721/IERC721Receiver.sol)

pragma solidity ^0.8.20;

/**
 * @title ERC-721 token receiver interface
 * @dev Interface for any contract that wants to support safeTransfers
 * from ERC-721 asset contracts.
 */
interface IERC721Receiver {
    /**
     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}
     * by `operator` from `from`, this function is called.
     *
     * It must return its Solidity selector to confirm the token transfer.
     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be
     * reverted.
     *
     * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.
     */
    function onERC721Received(
        address operator,
        address from,
        uint256 tokenId,
        bytes calldata data
    ) external returns (bytes4);
}

File 8 of 19 : ERC721Holder.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/utils/ERC721Holder.sol)

pragma solidity ^0.8.20;

import {IERC721Receiver} from "../IERC721Receiver.sol";

/**
 * @dev Implementation of the {IERC721Receiver} interface.
 *
 * Accepts all token transfers.
 * Make sure the contract is able to use its token with {IERC721-safeTransferFrom}, {IERC721-approve} or
 * {IERC721-setApprovalForAll}.
 */
abstract contract ERC721Holder is IERC721Receiver {
    /**
     * @dev See {IERC721Receiver-onERC721Received}.
     *
     * Always returns `IERC721Receiver.onERC721Received.selector`.
     */
    function onERC721Received(address, address, uint256, bytes memory) public virtual returns (bytes4) {
        return this.onERC721Received.selector;
    }
}

File 9 of 19 : Address.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.2.0) (utils/Address.sol)

pragma solidity ^0.8.20;

import {Errors} from "./Errors.sol";

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev There's no code at `target` (it is not a contract).
     */
    error AddressEmptyCode(address target);

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].
     *
     * IMPORTANT: because control is transferred to `recipient`, care must be
     * taken to not create reentrancy vulnerabilities. Consider using
     * {ReentrancyGuard} or the
     * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        if (address(this).balance < amount) {
            revert Errors.InsufficientBalance(address(this).balance, amount);
        }

        (bool success, bytes memory returndata) = recipient.call{value: amount}("");
        if (!success) {
            _revert(returndata);
        }
    }

    /**
     * @dev Performs a Solidity function call using a low level `call`. A
     * plain `call` is an unsafe replacement for a function call: use this
     * function instead.
     *
     * If `target` reverts with a revert reason or custom error, it is bubbled
     * up by this function (like regular Solidity function calls). However, if
     * the call reverted with no returned reason, this function reverts with a
     * {Errors.FailedCall} error.
     *
     * Returns the raw returned data. To convert to the expected return value,
     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
     *
     * Requirements:
     *
     * - `target` must be a contract.
     * - calling `target` with `data` must not revert.
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     */
    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
        if (address(this).balance < value) {
            revert Errors.InsufficientBalance(address(this).balance, value);
        }
        (bool success, bytes memory returndata) = target.call{value: value}(data);
        return verifyCallResultFromTarget(target, success, returndata);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a static call.
     */
    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
        (bool success, bytes memory returndata) = target.staticcall(data);
        return verifyCallResultFromTarget(target, success, returndata);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a delegate call.
     */
    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
        (bool success, bytes memory returndata) = target.delegatecall(data);
        return verifyCallResultFromTarget(target, success, returndata);
    }

    /**
     * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target
     * was not a contract or bubbling up the revert reason (falling back to {Errors.FailedCall}) in case
     * of an unsuccessful call.
     */
    function verifyCallResultFromTarget(
        address target,
        bool success,
        bytes memory returndata
    ) internal view returns (bytes memory) {
        if (!success) {
            _revert(returndata);
        } else {
            // only check if target is a contract if the call was successful and the return data is empty
            // otherwise we already know that it was a contract
            if (returndata.length == 0 && target.code.length == 0) {
                revert AddressEmptyCode(target);
            }
            return returndata;
        }
    }

    /**
     * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the
     * revert reason or with a default {Errors.FailedCall} error.
     */
    function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {
        if (!success) {
            _revert(returndata);
        } else {
            return returndata;
        }
    }

    /**
     * @dev Reverts with returndata if present. Otherwise reverts with {Errors.FailedCall}.
     */
    function _revert(bytes memory returndata) private pure {
        // Look for revert reason and bubble it up if present
        if (returndata.length > 0) {
            // The easiest way to bubble the revert reason is using memory via assembly
            assembly ("memory-safe") {
                let returndata_size := mload(returndata)
                revert(add(32, returndata), returndata_size)
            }
        } else {
            revert Errors.FailedCall();
        }
    }
}

File 10 of 19 : Context.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)

pragma solidity ^0.8.20;

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

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

    function _contextSuffixLength() internal view virtual returns (uint256) {
        return 0;
    }
}

File 11 of 19 : Errors.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/Errors.sol)

pragma solidity ^0.8.20;

/**
 * @dev Collection of common custom errors used in multiple contracts
 *
 * IMPORTANT: Backwards compatibility is not guaranteed in future versions of the library.
 * It is recommended to avoid relying on the error API for critical functionality.
 *
 * _Available since v5.1._
 */
library Errors {
    /**
     * @dev The ETH balance of the account is not enough to perform the operation.
     */
    error InsufficientBalance(uint256 balance, uint256 needed);

    /**
     * @dev A call to an address target failed. The target may have reverted.
     */
    error FailedCall();

    /**
     * @dev The deployment failed.
     */
    error FailedDeployment();

    /**
     * @dev A necessary precompile is missing.
     */
    error MissingPrecompile(address);
}

File 12 of 19 : ERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/ERC165.sol)

pragma solidity ^0.8.20;

import {IERC165} from "./IERC165.sol";

/**
 * @dev Implementation of the {IERC165} interface.
 *
 * Contracts that want to implement ERC-165 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);
 * }
 * ```
 */
abstract contract ERC165 is IERC165 {
    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
        return interfaceId == type(IERC165).interfaceId;
    }
}

File 13 of 19 : IERC165.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol)

pragma solidity ^0.8.20;

/**
 * @dev Interface of the ERC-165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[ERC].
 *
 * 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[ERC 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 14 of 19 : Context.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.24 <0.9.0;

/**
 * @title Context
 * @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, as 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).
 * @notice This contract is used through inheritance. It will make available the
 * modifier `_msgSender()`, which can be used to reference the account that
 * called a function within an implementing contract.
 */
abstract contract Context {
    /*//////////////////////////////////////////////////////////////
                            INTERNAL FUNCTIONS
    //////////////////////////////////////////////////////////////*/
    /**
     * @notice Gets the sender of the current call
     * @dev Provides a way to retrieve the message sender that supports meta-transactions
     * @return Sender address (msg.sender in the base implementation)
     */
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    /**
     * @notice Gets the complete calldata of the current call
     * @dev Provides a way to retrieve the message data that supports meta-transactions
     * @return Complete calldata bytes
     */
    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }

    /**
     * @notice Gets the length of any context-specific suffix in the message data
     * @dev Used in meta-transaction implementations to account for additional data
     * @return Length of the context suffix (0 in the base implementation)
     */
    function _contextSuffixLength() internal view virtual returns (uint256) {
        return 0;
    }
}

File 15 of 19 : Ownable.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.24 <0.9.0;

import {Context} from "./Context.sol";

/**
 * @title Ownable
 * @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.
 * @notice By default, the owner account will be the one that deploys the contract.
 * This can later be changed with {transferOwnership} and {renounceOwnership}.
 */
abstract contract Ownable is Context {
    /*//////////////////////////////////////////////////////////////
                            STATE VARIABLES
    //////////////////////////////////////////////////////////////*/
    /// @notice Address of the current owner
    address private _owner;
    /*//////////////////////////////////////////////////////////////
                                EVENTS
    //////////////////////////////////////////////////////////////*/
    /// @notice Emitted when ownership is transferred
    event OwnershipTransferred(
        address indexed previousOwner,
        address indexed newOwner
    );
    /*//////////////////////////////////////////////////////////////
                            CUSTOM ERRORS
    //////////////////////////////////////////////////////////////*/
    /// @notice Thrown when non-owner tries to call owner-only function
    error UnauthorizedAccount(address account);
    /// @notice Thrown when trying to transfer ownership to invalid address
    error InvalidOwner(address owner);
    /*//////////////////////////////////////////////////////////////
                                MODIFIERS
    //////////////////////////////////////////////////////////////*/
    /**
     * @dev Throws if called by any account other than the owner
     */
    modifier onlyOwner() {
        _checkOwner();
        _;
    }

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

    /*//////////////////////////////////////////////////////////////
                            PUBLIC FUNCTIONS
    //////////////////////////////////////////////////////////////*/
    /**
     * @notice Leaves the contract without owner
     * @dev 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));
    }

    /**
     * @notice Transfers ownership of the contract to a new account
     * @dev The new owner cannot be the zero address
     * @param newOwner The address that will become the new owner
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        if (newOwner == address(0)) {
            revert InvalidOwner(address(0));
        }
        _transferOwnership(newOwner);
    }

    /*//////////////////////////////////////////////////////////////
                            VIEW FUNCTIONS
    //////////////////////////////////////////////////////////////*/
    /**
     * @notice Returns the address of the current owner
     * @return Current owner address
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /*//////////////////////////////////////////////////////////////
                            INTERNAL FUNCTIONS
    //////////////////////////////////////////////////////////////*/
    /**
     * @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);
    }

    /**
     * @dev Throws if the sender is not the owner
     */
    function _checkOwner() internal view virtual {
        if (owner() != _msgSender()) {
            revert UnauthorizedAccount(_msgSender());
        }
    }
}

File 16 of 19 : IERC20Custom.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.24 <0.9.0;

/**
 * @title IERC20Custom
 * @dev Interface for the ERC20 fungible token standard (EIP-20)
 * @notice Defines functionality for:
 * 1. Token transfers
 * 2. Allowance management
 * 3. Balance tracking
 * 4. Token metadata
 */
interface IERC20Custom {
    /*//////////////////////////////////////////////////////////////
                                EVENTS
    //////////////////////////////////////////////////////////////*/
    /**
     * @dev Emitted on token transfer between addresses
     * @param from Source address (0x0 for mints)
     * @param to Destination address (0x0 for burns)
     * @param value Amount of tokens transferred
     * @notice Tracks:
     * · Regular transfers
     * · Minting operations
     * · Burning operations
     */
    event Transfer(address indexed from, address indexed to, uint256 value);
    /**
     * @dev Emitted when spending allowance is granted
     * @param owner Address granting permission
     * @param spender Address receiving permission
     * @param value Amount of tokens approved
     * @notice Records:
     * · New approvals
     * · Updated allowances
     * · Revoked permissions
     */
    event Approval(
        address indexed owner,
        address indexed spender,
        uint256 value
    );

    /*//////////////////////////////////////////////////////////////
                        TRANSFER OPERATIONS
    //////////////////////////////////////////////////////////////*/
    /**
     * @notice Transfers tokens to specified recipient
     * @param to Recipient address
     * @param value Amount to transfer in base units
     * @return bool True if transfer succeeds
     * @dev Requirements:
     * · Caller has sufficient balance
     * · Recipient is valid
     * · Amount > 0
     *
     * Effects:
     * · Decreases caller balance
     * · Increases recipient balance
     * · Emits Transfer event
     */
    function transfer(address to, uint256 value) external returns (bool);

    /**
     * @notice Executes transfer on behalf of token owner
     * @param from Source address
     * @param to Destination address
     * @param value Amount to transfer in base units
     * @return bool True if transfer succeeds
     * @dev Requirements:
     * · Caller has sufficient allowance
     * · Source has sufficient balance
     * · Valid addresses
     *
     * Effects:
     * · Decreases allowance
     * · Updates balances
     * · Emits Transfer event
     */
    function transferFrom(
        address from,
        address to,
        uint256 value
    ) external returns (bool);

    /*//////////////////////////////////////////////////////////////
                        APPROVAL OPERATIONS
    //////////////////////////////////////////////////////////////*/
    /**
     * @notice Authorizes address to spend tokens
     * @param spender Address to authorize
     * @param value Amount to authorize in base units
     * @return bool True if approval succeeds
     * @dev Controls:
     * · Spending permissions
     * · Delegation limits
     * · Authorization levels
     *
     * Security:
     * · Overwrites previous allowance
     * · Requires explicit value
     * · Emits Approval event
     */
    function approve(address spender, uint256 value) external returns (bool);

    /*//////////////////////////////////////////////////////////////
                            TOKEN METADATA
    //////////////////////////////////////////////////////////////*/
    /**
     * @notice Retrieves human-readable token name
     * @return string Full token name
     */
    function name() external view returns (string memory);

    /**
     * @notice Retrieves token trading symbol
     * @return string Short token identifier
     */
    function symbol() external view returns (string memory);

    /**
     * @notice Retrieves token decimal precision
     * @return uint8 Number of decimal places
     * @dev Standard:
     * · 18 for most tokens
     * · Used for display formatting
     */
    function decimals() external view returns (uint8);

    /*//////////////////////////////////////////////////////////////
                            BALANCE QUERIES
    //////////////////////////////////////////////////////////////*/
    /**
     * @notice Retrieves total token supply
     * @return uint256 Current total supply
     * @dev Reflects:
     * · All minted tokens
     * · Minus burned tokens
     * · In base units
     */
    function totalSupply() external view returns (uint256);

    /**
     * @notice Retrieves account token balance
     * @param account Address to query
     * @return uint256 Current balance in base units
     * @dev Returns:
     * · Available balance
     * · Includes pending rewards
     * · Excludes locked tokens
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @notice Retrieves remaining spending allowance
     * @param owner Token owner address
     * @param spender Authorized spender address
     * @return uint256 Current allowance in base units
     * @dev Shows:
     * · Approved amount
     * · Remaining limit
     * · Delegation status
     */
    function allowance(
        address owner,
        address spender
    ) external view returns (uint256);
}

File 17 of 19 : IOracle.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.24 <0.9.0;

/**
 * @title IOracle
 * @dev Interface for basic price feed operations
 * @notice Defines functionality for:
 * 1. Asset price retrieval
 * 2. Price precision handling
 */
interface IOracle {
    /*//////////////////////////////////////////////////////////////
                            PRICE QUERIES
    //////////////////////////////////////////////////////////////*/
    /**
     * @notice Retrieves current asset price
     * @param asset Address of the asset to price
     * @return uint256 Current price in base units with precision
     * @dev Provides:
     * · Latest price data
     * · Standardized precision
     * · Asset valuation
     *
     * Note: Check implementation for specific precision details
     */
    function getPrice(address asset) external view returns (uint256);
}

/**
 * @title ITwapOracle
 * @dev Interface for time-weighted average price calculations
 * @notice Defines functionality for:
 * 1. TWAP updates
 * 2. Time-weighted calculations
 * 3. Price smoothing
 */
interface ITwapOracle {
    /*//////////////////////////////////////////////////////////////
                            TWAP OPERATIONS
    //////////////////////////////////////////////////////////////*/
    /**
     * @notice Updates time-weighted average price
     * @param asset Address of the asset to update
     * @return uint256 New TWAP value in base units
     * @dev Calculates:
     * · Time-weighted price
     * · Cumulative values
     * · Price averages
     *
     * Features:
     * · Manipulation resistance
     * · Smoothing effect
     * · Historical tracking
     */
    function updateTwap(address asset) external returns (uint256);
}

File 18 of 19 : IOracleApi3Reader.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.24 <0.9.0;

/// @title IOracleApi3Reader Interface
/// @notice Interface for interacting with Api3 Network's Chainlink price feed adapter
interface IOracleApi3Reader {
    /// @notice Get the latest price data from the Chainlink oracle
    /// @return roundId The round ID from the underlying price feed
    /// @return answer The price answer from the oracle
    /// @return startedAt Timestamp of when the round started
    /// @return updatedAt Timestamp of when the round was updated
    /// @return answeredInRound The round ID in which the answer was computed
    function latestRoundData()
        external
        view
        returns (
            uint80 roundId,
            int256 answer,
            uint256 startedAt,
            uint256 updatedAt,
            uint80 answeredInRound
        );

    /// @notice Get the number of decimals in the price feed's response
    /// @return The number of decimals used in the price feed
    function decimals() external view returns (uint8);
}

File 19 of 19 : OracleChainlink.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.24 <0.9.0;

import {Ownable} from "../abstract/Ownable.sol";
import {IERC20Custom} from "../interface/IERC20Custom.sol";
import {IOracle} from "../interface/IOracle.sol";
import {IOracleApi3Reader} from "../interface/IOracleApi3Reader.sol";

/**
 * @title OracleChainlink
 * @dev Oracle implementation using Chainlink price feeds with fallback direct prices
 * @notice This contract manages price feeds and provides asset prices
 */
contract OracleChainlink is Ownable, IOracle {
    /*//////////////////////////////////////////////////////////////
                                 TYPES
    //////////////////////////////////////////////////////////////*/
    /**
     * @dev Configuration for token price feeds
     * @param asset Token address to get price for
     * @param feed Chainlink aggregator address
     */
    struct TokenConfig {
        address asset;
        address feed;
    }
    /*//////////////////////////////////////////////////////////////
                            STATE VARIABLES
    //////////////////////////////////////////////////////////////*/
    /// @notice Maps assets to their direct price overrides (in 18 decimals)
    mapping(address => uint256) public prices;
    /// @notice Maps assets to their Chainlink feed configurations
    mapping(address => TokenConfig) public tokenConfigs;
    /// @notice Maximum time (in seconds) before price is considered stale
    uint256 public constant MAX_STALE_PERIOD = 24 hours;
    /*//////////////////////////////////////////////////////////////
                                EVENTS
    //////////////////////////////////////////////////////////////*/
    /// @notice Emitted when a token's price feed configuration is set
    event TokenConfigAdded(address indexed asset, address feed);
    /*//////////////////////////////////////////////////////////////
                             CUSTOM ERRORS
    //////////////////////////////////////////////////////////////*/
    /// @dev Thrown when an address parameter is zero
    error ZeroAddress();
    /// @dev Thrown when empty array is provided
    error NegativePrice();
    /// @dev Thrown when token decimals are invalid
    error InvalidDecimals();
    /// @dev Thrown when price is stale or timestamp is invalid
    error InvalidTime();
    /*//////////////////////////////////////////////////////////////
                              MODIFIERS
    //////////////////////////////////////////////////////////////*/
    /**
     * @dev Ensures an address parameter is not zero
     * @param addr Address to validate
     */
    modifier notNullAddress(address addr) {
        if (addr == address(0)) revert ZeroAddress();
        _;
    }

    /*//////////////////////////////////////////////////////////////
                            EXTERNAL FUNCTIONS
    //////////////////////////////////////////////////////////////*/
    /**
     * @notice Sets configuration for a single token price feed
     * @param tokenConfig Token configuration to set
     */
    function setTokenConfig(
        TokenConfig memory tokenConfig
    )
        external
        notNullAddress(tokenConfig.asset)
        notNullAddress(tokenConfig.feed)
        onlyOwner
    {
        IERC20Custom token = IERC20Custom(tokenConfig.asset);
        uint8 tokenDecimals = token.decimals();
        IOracleApi3Reader feed = IOracleApi3Reader(tokenConfig.feed);
        uint8 feedDecimals = feed.decimals();
        if (tokenDecimals > 18 || feedDecimals > 18) revert InvalidDecimals();
        tokenConfigs[tokenConfig.asset] = tokenConfig;
        emit TokenConfigAdded(tokenConfig.asset, tokenConfig.feed);
    }

    /**
     * @notice Gets the current price for an asset
     * @param asset Asset address to get price for
     * @return uint256 Current price in 18 decimals
     */
    function getPrice(address asset) public view virtual returns (uint256) {
        IERC20Custom token = IERC20Custom(asset);
        uint8 decimals = token.decimals();
        return _getPrice(asset, decimals);
    }

    /*//////////////////////////////////////////////////////////////
                           PRIVATE FUNCTIONS
    //////////////////////////////////////////////////////////////*/
    /**
     * @dev Gets price with decimal adjustment
     * @param asset Asset address to get price for
     * @param decimals Token decimals for normalization
     * @return price Price in 18 decimals
     */
    function _getPrice(
        address asset,
        uint8 decimals
    ) private view returns (uint256 price) {
        uint256 tokenPrice = prices[asset];
        if (tokenPrice != 0) {
            // Direct price override exists, normalize to 18 decimals
            uint8 decimalDelta = 18 - decimals;
            price = tokenPrice * (10 ** decimalDelta);
        } else {
            // No override, get from Chainlink
            price = _getChainlinkPrice(asset);
        }
        return price;
    }

    /**
     * @dev Fetches and validates price from Chainlink feed
     * @param asset Asset address to get price for
     * @return uint256 Normalized price in 18 decimals
     */
    function _getChainlinkPrice(
        address asset
    ) private view notNullAddress(tokenConfigs[asset].asset) returns (uint256) {
        TokenConfig memory tokenConfig = tokenConfigs[asset];
        IOracleApi3Reader feed = IOracleApi3Reader(tokenConfig.feed);
        uint8 decimalDelta = 18 - feed.decimals();
        (, int256 answer, , uint256 updatedAt, ) = feed.latestRoundData();
        // Validate price and timestamp
        if (answer <= 0) revert NegativePrice();
        if (block.timestamp < updatedAt) revert InvalidTime();
        uint256 deltaTime;
        unchecked {
            deltaTime = block.timestamp - updatedAt;
        }
        if (deltaTime > MAX_STALE_PERIOD) revert InvalidTime();
        // Normalize to 18 decimals
        return uint256(answer) * (10 ** decimalDelta);
    }
}

Settings
{
  "viaIR": true,
  "evmVersion": "paris",
  "optimizer": {
    "enabled": false,
    "runs": 200
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "metadata": {
    "useLiteralContent": true
  },
  "libraries": {}
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"address","name":"vault_","type":"address"},{"internalType":"address","name":"oracle_","type":"address"},{"internalType":"address[]","name":"proposers","type":"address[]"},{"internalType":"address[]","name":"executors","type":"address[]"},{"internalType":"address","name":"admin","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AccessControlBadConfirmation","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"neededRole","type":"bytes32"}],"name":"AccessControlUnauthorizedAccount","type":"error"},{"inputs":[],"name":"FailedCall","type":"error"},{"inputs":[],"name":"InvalidAddress","type":"error"},{"inputs":[],"name":"SchedulingFailed","type":"error"},{"inputs":[{"internalType":"uint256","name":"delay","type":"uint256"},{"internalType":"uint256","name":"minDelay","type":"uint256"}],"name":"TimelockInsufficientDelay","type":"error"},{"inputs":[{"internalType":"uint256","name":"targets","type":"uint256"},{"internalType":"uint256","name":"payloads","type":"uint256"},{"internalType":"uint256","name":"values","type":"uint256"}],"name":"TimelockInvalidOperationLength","type":"error"},{"inputs":[{"internalType":"address","name":"caller","type":"address"}],"name":"TimelockUnauthorizedCaller","type":"error"},{"inputs":[{"internalType":"bytes32","name":"predecessorId","type":"bytes32"}],"name":"TimelockUnexecutedPredecessor","type":"error"},{"inputs":[{"internalType":"bytes32","name":"operationId","type":"bytes32"},{"internalType":"bytes32","name":"expectedStates","type":"bytes32"}],"name":"TimelockUnexpectedOperationState","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"id","type":"bytes32"},{"indexed":true,"internalType":"uint256","name":"index","type":"uint256"},{"indexed":false,"internalType":"address","name":"target","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"}],"name":"CallExecuted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"id","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"salt","type":"bytes32"}],"name":"CallSalt","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"id","type":"bytes32"},{"indexed":true,"internalType":"uint256","name":"index","type":"uint256"},{"indexed":false,"internalType":"address","name":"target","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"},{"indexed":false,"internalType":"bytes","name":"data","type":"bytes"},{"indexed":false,"internalType":"bytes32","name":"predecessor","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"delay","type":"uint256"}],"name":"CallScheduled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"id","type":"bytes32"}],"name":"Cancelled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"oldDuration","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newDuration","type":"uint256"}],"name":"MinDelayChange","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"inputs":[],"name":"CANCELLER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DELAY","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"EXECUTOR_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PROPOSER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"id","type":"bytes32"}],"name":"cancel","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"target","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bytes","name":"payload","type":"bytes"},{"internalType":"bytes32","name":"predecessor","type":"bytes32"},{"internalType":"bytes32","name":"salt","type":"bytes32"}],"name":"execute","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address[]","name":"targets","type":"address[]"},{"internalType":"uint256[]","name":"values","type":"uint256[]"},{"internalType":"bytes[]","name":"payloads","type":"bytes[]"},{"internalType":"bytes32","name":"predecessor","type":"bytes32"},{"internalType":"bytes32","name":"salt","type":"bytes32"}],"name":"executeBatch","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"getMinDelay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"id","type":"bytes32"}],"name":"getOperationState","outputs":[{"internalType":"enum TimelockController.OperationState","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"id","type":"bytes32"}],"name":"getTimestamp","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"target","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"bytes32","name":"predecessor","type":"bytes32"},{"internalType":"bytes32","name":"salt","type":"bytes32"}],"name":"hashOperation","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address[]","name":"targets","type":"address[]"},{"internalType":"uint256[]","name":"values","type":"uint256[]"},{"internalType":"bytes[]","name":"payloads","type":"bytes[]"},{"internalType":"bytes32","name":"predecessor","type":"bytes32"},{"internalType":"bytes32","name":"salt","type":"bytes32"}],"name":"hashOperationBatch","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes32","name":"id","type":"bytes32"}],"name":"isOperation","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"id","type":"bytes32"}],"name":"isOperationDone","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"id","type":"bytes32"}],"name":"isOperationPending","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"id","type":"bytes32"}],"name":"isOperationReady","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC1155BatchReceived","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC1155Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC721Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"oracleChainlink","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"callerConfirmation","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"target","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"bytes32","name":"predecessor","type":"bytes32"},{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"uint256","name":"delay","type":"uint256"}],"name":"schedule","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"controller","type":"address"}],"name":"scheduleAddController","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"targets","type":"address[]"},{"internalType":"uint256[]","name":"values","type":"uint256[]"},{"internalType":"bytes[]","name":"payloads","type":"bytes[]"},{"internalType":"bytes32","name":"predecessor","type":"bytes32"},{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"uint256","name":"delay","type":"uint256"}],"name":"scheduleBatch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"address","name":"feed","type":"address"}],"name":"scheduleSetTokenConfig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stoutVault","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"newDelay","type":"uint256"}],"name":"updateDelay","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]

60c0604052346200005b5762000022620000186200025f565b93929092620002fe565b6200002c62000061565b6130fe620009718239608051818181610a8c015261228e015260a0518181816108f501526125e201526130fe90f35b62000067565b60405190565b600080fd5b601f801991011690565b634e487b7160e01b600052604160045260246000fd5b9062000098906200006c565b810190811060018060401b03821117620000b157604052565b62000076565b90620000ce620000c662000061565b92836200008c565b565b600080fd5b600080fd5b60018060a01b031690565b620000f090620000da565b90565b620000fe81620000e5565b036200010657565b600080fd5b905051906200011a82620000f3565b565b600080fd5b60018060401b038111620001385760208091020190565b62000076565b600080fd5b909291926200015c620001568262000121565b620000b7565b93818552602080860192028301928184116200019e57915b838310620001825750505050565b602080916200019284866200010b565b81520192019162000174565b6200013e565b9080601f83011215620001c557816020620001c29351910162000143565b90565b6200011c565b919060a0838203126200025957620001e781600085016200010b565b92620001f782602083016200010b565b92604082015160018060401b03811162000253578362000219918401620001a4565b9260608301519060018060401b0382116200024d5762000240816200024a938601620001a4565b936080016200010b565b90565b620000d5565b620000d5565b620000d0565b6200028262003a6f803803806200027681620000b7565b928339810190620001cb565b9091929394565b90565b90565b90565b620002ab620002a5620002b19262000289565b6200028f565b6200028c565b90565b620002c26202a30062000292565b90565b90565b620002e1620002db620002e792620002c5565b6200028f565b620000da565b90565b620002f590620002c8565b90565b60000190565b92936200031b92919462000311620002b4565b92909192620005b2565b806200033d62000336620003306000620002ea565b620000e5565b91620000e5565b1480156200037a575b620003535760805260a052565b6200035d62000061565b63e6c4247b60e01b8152806200037660048201620002f8565b0390fd5b50816200039d62000396620003906000620002ea565b620000e5565b91620000e5565b1462000346565b90565b60001b90565b620003c6620003c0620003cc92620002c5565b620003a7565b620003a4565b90565b620003db6000620003ad565b90565b620003f7620003f1620003fd92620000da565b6200028f565b620000da565b90565b6200040b90620003de565b90565b620004199062000400565b90565b620004356200042f6200043b92620002c5565b6200028f565b6200028c565b90565b60016200044c91016200028c565b90565b5190565b7fb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc190565b634e487b7160e01b600052603260045260246000fd5b9062000499826200044f565b811015620004ab576020809102010190565b62000477565b620004bd9051620000e5565b90565b7ffd643c72710c63c0180259aba6b2d05451e3591a24e58b62239378085726f78390565b7fd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e6390565b906200051760001991620003a7565b9181191691161790565b6200053a6200053462000540926200028c565b6200028f565b6200028c565b90565b90565b90620005606200055a620005689262000521565b62000543565b825462000508565b9055565b62000577906200041c565b9052565b62000586906200028c565b9052565b916020620005b0929493620005a8604082019660008301906200056c565b01906200057b565b565b909392620005d5620005c3620003cf565b620005ce306200040e565b9062000830565b5080620005f8620005f1620005eb6000620002ea565b620000e5565b91620000e5565b036200076a575b506200060c60006200041c565b5b806200062e6200062762000621886200044f565b6200028c565b916200028c565b1015620006a0576200069a90620006666200064862000453565b6200065f620006598985906200048d565b620004b1565b9062000830565b506200069362000675620004c0565b6200068c620006868985906200048d565b620004b1565b9062000830565b506200043e565b6200060d565b5091909250620006b160006200041c565b5b80620006d3620006cc620006c6876200044f565b6200028c565b916200028c565b1015620007185762000712906200070b620006ed620004e4565b62000704620006fe8885906200048d565b620004b1565b9062000830565b506200043e565b620006b2565b5091506200072881600262000546565b6000907f11c24f4ead16507c69ac467fbd5e4eed5fb5c699626d2cc6d66421df253886d591620007656200075b62000061565b928392836200058a565b0390a1565b6200077f9062000779620003cf565b62000830565b5038620005ff565b600090565b151590565b6200079c90620003a4565b90565b90620007ab9062000791565b600052602052604060002090565b620007c49062000400565b90565b90620007d390620007b9565b600052602052604060002090565b90620007ef60ff91620003a7565b9181191691161790565b62000804906200078c565b90565b90565b90620008246200081e6200082c92620007f9565b62000807565b8254620007e1565b9055565b6200083a62000787565b50620008536200084c8284906200092a565b156200078c565b600014620008f0576200088360016200087d6000620008748186906200079f565b018590620007c7565b6200080a565b906200088e62000961565b90620008d1620008ca620008c37f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d9562000791565b92620007b9565b92620007b9565b92620008dc62000061565b80620008e881620002f8565b0390a4600190565b5050600090565b60001c90565b60ff1690565b620009126200091891620008f7565b620008fd565b90565b62000927905462000903565b90565b620009599160006200094c62000953936200094462000787565b50826200079f565b01620007c7565b6200091b565b90565b600090565b6200096b6200095c565b50339056fe60806040526004361015610015575b3661138757005b61002060003561022f565b806301d5062a1461022a57806301ffc9a71461022557806307bd026514610220578063134008d31461021b57806313bc9f2014610216578063150b7a0214610211578063248a9ca31461020c5780632ab0f529146102075780632f2ff15d1461020257806331d50750146101fd57806336568abe146101f85780634f7b02ee146101f3578063584b153e146101ee57806364d62353146101e957806369b41170146101e45780636cc10283146101df5780637958004c146101da5780638065657f146101d55780638f2a0bb0146101d05780638f61f4f5146101cb57806391d14854146101c6578063a217fddf146101c1578063b08e51c0146101bc578063b1c5f427146101b7578063bc197c81146101b2578063bdb73034146101ad578063c4d252f5146101a8578063d45c4435146101a3578063d547741f1461019e578063dfc6fe9914610199578063e38335e514610194578063f23a6e611461018f5763f27a0c920361000e57611352565b611319565b611276565b611242565b6111e0565b6111ab565b611178565b611145565b6110ed565b610f77565b610e9b565b610e37565b610dc4565b610d8f565b610d23565b610b78565b610b43565b610aae565b610a55565b6109c3565b61096f565b61093a565b6108bf565b61088a565b610856565b6107f3565b6107be565b610785565b6105e2565b610593565b6104ed565b610456565b6103a5565b60e01c90565b60405190565b600080fd5b600080fd5b600080fd5b60018060a01b031690565b61025e9061024a565b90565b61026a81610255565b0361027157565b600080fd5b9050359061028382610261565b565b90565b61029181610285565b0361029857565b600080fd5b905035906102aa82610288565b565b600080fd5b600080fd5b600080fd5b909182601f830112156102f55781359167ffffffffffffffff83116102f05760200192600183028401116102eb57565b6102b6565b6102b1565b6102ac565b90565b610306816102fa565b0361030d57565b600080fd5b9050359061031f826102fd565b565b9160c08383031261039a576103398260008501610276565b92610347836020830161029d565b92604082013567ffffffffffffffff811161039557816103689184016102bb565b92909361039261037b8460608501610312565b936103898160808601610312565b9360a00161029d565b90565b610245565b610240565b60000190565b346103da576103c46103b8366004610321565b9594909493919361153c565b6103cc610235565b806103d68161039f565b0390f35b61023b565b63ffffffff60e01b1690565b6103f4816103df565b036103fb57565b600080fd5b9050359061040d826103eb565b565b906020828203126104295761042691600001610400565b90565b610240565b151590565b61043c9061042e565b9052565b919061045490600060208501940190610433565b565b346104865761048261047161046c36600461040f565b611552565b610479610235565b91829182610440565b0390f35b61023b565b600091031261049657565b610240565b7fd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e6390565b6104c761049b565b90565b6104d3906102fa565b9052565b91906104eb906000602085019401906104ca565b565b3461051d576104fd36600461048b565b6105196105086104bf565b610510610235565b918291826104d7565b0390f35b61023b565b9060a08282031261058e5761053a8160008401610276565b92610548826020850161029d565b9260408101359167ffffffffffffffff83116105895761056d846105869484016102bb565b93909461057d8160608601610312565b93608001610312565b90565b610245565b610240565b6105ad6105a1366004610522565b949390939291926116a1565b6105b5610235565b806105bf8161039f565b0390f35b906020828203126105dd576105da91600001610312565b90565b610240565b346106125761060e6105fd6105f83660046105c3565b6116b1565b610605610235565b91829182610440565b0390f35b61023b565b600080fd5b601f801991011690565b634e487b7160e01b600052604160045260246000fd5b906106469061061c565b810190811067ffffffffffffffff82111761066057604052565b610626565b90610678610671610235565b928361063c565b565b67ffffffffffffffff81116106985761069460209161061c565b0190565b610626565b90826000939282370152565b909291926106be6106b98261067a565b610665565b938185526020850190828401116106da576106d89261069d565b565b610617565b9080601f830112156106fd578160206106fa933591016106a9565b90565b6102ac565b9060808282031261075d5761071a8160008401610276565b926107288260208501610276565b92610736836040830161029d565b92606082013567ffffffffffffffff81116107585761075592016106df565b90565b610245565b610240565b61076b906103df565b9052565b919061078390600060208501940190610762565b565b346107b9576107b56107a461079b366004610702565b92919091611732565b6107ac610235565b9182918261076f565b0390f35b61023b565b346107ee576107ea6107d96107d43660046105c3565b611796565b6107e1610235565b918291826104d7565b0390f35b61023b565b346108235761081f61080e6108093660046105c3565b6117b8565b610816610235565b91829182610440565b0390f35b61023b565b9190604083820312610851578061084561084e9260008601610312565b93602001610276565b90565b610240565b346108855761086f610869366004610828565b9061180b565b610877610235565b806108818161039f565b0390f35b61023b565b346108ba576108b66108a56108a03660046105c3565b611817565b6108ad610235565b91829182610440565b0390f35b61023b565b346108ee576108d86108d2366004610828565b90611841565b6108e0610235565b806108ea8161039f565b0390f35b61023b565b7f000000000000000000000000000000000000000000000000000000000000000090565b61092090610255565b9052565b919061093890600060208501940190610917565b565b3461096a5761094a36600461048b565b6109666109556108f3565b61095d610235565b91829182610924565b0390f35b61023b565b3461099f5761099b61098a6109853660046105c3565b611890565b610992610235565b91829182610440565b0390f35b61023b565b906020828203126109be576109bb9160000161029d565b90565b610240565b346109f1576109db6109d63660046109a4565b611989565b6109e3610235565b806109ed8161039f565b0390f35b61023b565b90565b90565b610a10610a0b610a15926109f6565b6109f9565b610285565b90565b610a246202a3006109fc565b90565b610a2f610a18565b90565b610a3b90610285565b9052565b9190610a5390600060208501940190610a32565b565b34610a8557610a6536600461048b565b610a81610a70610a27565b610a78610235565b91829182610a3f565b0390f35b61023b565b7f000000000000000000000000000000000000000000000000000000000000000090565b34610ade57610abe36600461048b565b610ada610ac9610a8a565b610ad1610235565b91829182610924565b0390f35b61023b565b634e487b7160e01b600052602160045260246000fd5b60041115610b0357565b610ae3565b90610b1282610af9565b565b610b1d90610b08565b90565b610b2990610b14565b9052565b9190610b4190600060208501940190610b20565b565b34610b7357610b6f610b5e610b593660046105c3565b611a5a565b610b66610235565b91829182610b2d565b0390f35b61023b565b34610baf57610bab610b9a610b8e366004610522565b94939093929192611b37565b610ba2610235565b918291826104d7565b0390f35b61023b565b909182601f83011215610bee5781359167ffffffffffffffff8311610be9576020019260208302840111610be457565b6102b6565b6102b1565b6102ac565b909182601f83011215610c2d5781359167ffffffffffffffff8311610c28576020019260208302840111610c2357565b6102b6565b6102b1565b6102ac565b909182601f83011215610c6c5781359167ffffffffffffffff8311610c67576020019260208302840111610c6257565b6102b6565b6102b1565b6102ac565b9060c082820312610d1e57600082013567ffffffffffffffff8111610d195781610c9c918401610bb4565b929093602082013567ffffffffffffffff8111610d145783610cbf918401610bf3565b929093604082013567ffffffffffffffff8111610d0f5781610ce2918401610c32565b929093610d0c610cf58460608501610312565b93610d038160808601610312565b9360a00161029d565b90565b610245565b610245565b610245565b610240565b34610d5b57610d45610d36366004610c71565b97969096959195949294611ee9565b610d4d610235565b80610d578161039f565b0390f35b61023b565b7fb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc190565b610d8c610d60565b90565b34610dbf57610d9f36600461048b565b610dbb610daa610d84565b610db2610235565b918291826104d7565b0390f35b61023b565b34610df557610df1610de0610dda366004610828565b90611f47565b610de8610235565b91829182610440565b0390f35b61023b565b90565b60001b90565b610e17610e12610e1c92610dfa565b610dfd565b6102fa565b90565b610e296000610e03565b90565b610e34610e1f565b90565b34610e6757610e4736600461048b565b610e63610e52610e2c565b610e5a610235565b918291826104d7565b0390f35b61023b565b7ffd643c72710c63c0180259aba6b2d05451e3591a24e58b62239378085726f78390565b610e98610e6c565b90565b34610ecb57610eab36600461048b565b610ec7610eb6610e90565b610ebe610235565b918291826104d7565b0390f35b61023b565b91909160a081840312610f7257600081013567ffffffffffffffff8111610f6d5783610efd918301610bb4565b929093602083013567ffffffffffffffff8111610f685781610f20918501610bf3565b92909360408101359167ffffffffffffffff8311610f6357610f4784610f60948401610c32565b939094610f578160608601610312565b93608001610312565b90565b610245565b610245565b610245565b610240565b34610fb157610fad610f9c610f8d366004610ed0565b969590959491949392936121b8565b610fa4610235565b918291826104d7565b0390f35b61023b565b67ffffffffffffffff8111610fce5760208091020190565b610626565b90929192610fe8610fe382610fb6565b610665565b938185526020808601920283019281841161102557915b83831061100c5750505050565b6020809161101a848661029d565b815201920191610fff565b6102b6565b9080601f830112156110485781602061104593359101610fd3565b90565b6102ac565b91909160a0818403126110e8576110678360008301610276565b926110758160208401610276565b92604083013567ffffffffffffffff81116110e3578261109691850161102a565b92606081013567ffffffffffffffff81116110de57836110b791830161102a565b92608082013567ffffffffffffffff81116110d9576110d692016106df565b90565b610245565b610245565b610245565b610240565b346111215761111d61110c61110336600461104d565b93929092612210565b611114610235565b9182918261076f565b0390f35b61023b565b906020828203126111405761113d91600001610276565b90565b610240565b346111735761115d611158366004611126565b6122ed565b611165610235565b8061116f8161039f565b0390f35b61023b565b346111a65761119061118b3660046105c3565b61245d565b611198610235565b806111a28161039f565b0390f35b61023b565b346111db576111d76111c66111c13660046105c3565b612468565b6111ce610235565b91829182610a3f565b0390f35b61023b565b3461120f576111f96111f3366004610828565b906124b1565b611201610235565b8061120b8161039f565b0390f35b61023b565b919060408382031261123d578061123161123a9260008601610276565b93602001610276565b90565b610240565b346112715761125b611255366004611214565b9061268a565b611263610235565b8061126d8161039f565b0390f35b61023b565b611293611284366004610ed0565b9695909594919493929361289d565b61129b610235565b806112a58161039f565b0390f35b91909160a081840312611314576112c38360008301610276565b926112d18160208401610276565b926112df826040850161029d565b926112ed836060830161029d565b92608082013567ffffffffffffffff811161130f5761130c92016106df565b90565b610245565b610240565b3461134d5761134961133861132f3660046112a9565b939290926128af565b611340610235565b9182918261076f565b0390f35b61023b565b346113825761136236600461048b565b61137e61136d6128cd565b611375610235565b91829182610a3f565b0390f35b61023b565b600080fd5b906113ab9695949392916113a66113a1610d60565b6128e3565b611454565b565b6113b6906102fa565b90565b6113cd6113c86113d292610dfa565b6109f9565b610285565b90565b60209181520190565b91906113f8816113f1816113fd956113d5565b809561069d565b61061c565b0190565b9161144b91611452969897956080956114336114409461142960a089019560008a0190610917565b6020880190610a32565b85830360408701526113de565b9660608301906104ca565b0190610a32565b565b9293949591906114ca61146e85838589908b928d94611b37565b9661147a888690612932565b87946000969394979190916114b86114b27f4cf4410cc57040e44862ef0f45f3dd5a5e02db8eb8add648d4b0e236f1d07dca986113ad565b986113b9565b986114c1610235565b96879687611401565b0390a3816114e96114e36114de6000610e03565b6102fa565b916102fa565b036114f3575b5050565b6115326115207f20fda5fd27a1ea7bf5b9567f143ac5470bb059374a27e8f67cb44f946f6d0387926113ad565b92611529610235565b918291826104d7565b0390a238806114ef565b9061154b96959493929161138c565b565b600090565b6115649061155e61154d565b506129d8565b90565b61157b61157661158092610dfa565b6109f9565b61024a565b90565b61158c90611567565b90565b906115c895949392916115a061049b565b6115bd6115b7826115b16000611583565b90611f47565b1561042e565b6115ca575b50611619565b565b6115dc906115d6612a1d565b90612a4e565b386115c2565b61160961161695939492946115ff60608401966000850190610917565b6020830190610a32565b60408185039101526113de565b90565b9161163961163261169f978590858589918b9394611b37565b9586612a90565b611647838383908792612bb5565b849161169760009491929561168561167f7fc2617efa69bab66782fa219543714338489c4e9e178271560a91b82c3f612b58966113ad565b966113b9565b9661168e610235565b948594856115e2565b0390a3612bea565b565b906116af959493929161158f565b565b6116c3906116bd61154d565b50611a5a565b6116d66116d06002610b08565b91610b08565b1490565b600090565b6116f36116ee6116f89261024a565b6109f9565b61024a565b90565b611704906116df565b90565b63ffffffff1690565b60e01b90565b61172a61172561172f92611707565b611710565b6103df565b90565b5050505061173e6116da565b5061174c63150b7a02611716565b90565b600090565b9061175e906113ad565b600052602052604060002090565b60001c90565b90565b6117816117869161176c565b611772565b90565b6117939054611775565b90565b60016117af6117b5926117a761174f565b506000611754565b01611789565b90565b6117ca906117c461154d565b50611a5a565b6117dd6117d76003610b08565b91610b08565b1490565b906117fc916117f76117f282611796565b6128e3565b6117fe565b565b9061180891612c93565b50565b90611815916117e1565b565b6118299061182361154d565b50611a5a565b61183c6118366000610b08565b91610b08565b141590565b908061185c611856611851612a1d565b610255565b91610255565b0361186d5761186a91612d41565b50565b611875610235565b63334bd91960e11b81528061188c6004820161039f565b0390fd5b6118a29061189c61154d565b50611a5a565b806118b66118b06001610b08565b91610b08565b149081156118c3575b5090565b90506118d86118d26002610b08565b91610b08565b14386118bf565b6118e8906116fb565b90565b90565b6118fa6118ff9161176c565b6118eb565b90565b61190c90546118ee565b90565b91602061193192949361192a60408201966000830190610a32565b0190610a32565b565b9061194060001991610dfd565b9181191691161790565b61195e61195961196392610285565b6109f9565b610285565b90565b90565b9061197e6119796119859261194a565b611966565b8254611933565b9055565b611991612a1d565b806119ac6119a66119a1306118df565b610255565b91610255565b03611a035750611a01906119c06002611902565b817f11c24f4ead16507c69ac467fbd5e4eed5fb5c699626d2cc6d66421df253886d5916119f76119ee610235565b9283928361190f565b0390a16002611969565b565b611a2590611a0f610235565b91829163e2850c5960e01b835260048301610924565b0390fd5b600090565b90565b611a45611a40611a4a92611a2e565b6109f9565b610285565b90565b611a576001611a31565b90565b611a6c90611a66611a29565b50612468565b80611a80611a7a60006113b9565b91610285565b14600014611a8e5750600090565b80611aa8611aa2611a9d611a4d565b610285565b91610285565b14600014611ab65750600390565b611ac8611ac242610285565b91610285565b11600014611ad557600190565b600290565b91611b2491611b2b96989795608095611b0c611b1994611b0260a089019560008a0190610917565b6020880190610a32565b85830360408701526113de565b9660608301906104ca565b01906104ca565b565b60200190565b5190565b94611b7694611b679396949294611b4c61174f565b50949692909192611b5b610235565b97889660208801611ada565b6020820181038252038261063c565b611b88611b8282611b33565b91611b2d565b2090565b90611bad9897969594939291611ba8611ba3610d60565b6128e3565b611ccd565b565b5090565b5090565b5090565b604090611be5611bec9496959396611bdb60608401986000850190610a32565b6020830190610a32565b0190610a32565b565b6001611bfa9101610285565b90565b634e487b7160e01b600052603260045260246000fd5b9190811015611c23576020020190565b611bfd565b35611c3281610261565b90565b9190811015611c45576020020190565b611bfd565b35611c5481610288565b90565b600080fd5b600080fd5b600080fd5b903590600160200381360303821215611ca8570180359067ffffffffffffffff8211611ca357602001916001820236038313611c9e57565b611c61565b611c5c565b611c57565b90821015611cc8576020611cc49202810190611c66565b9091565b611bfd565b959697939894929194611ce1878390611baf565b611cfd611cf7611cf2898790611bb3565b610285565b91610285565b14158015611eba575b611e7557611d20878a8a8d86908b8991928b9495966121b8565b90611d2c828790612932565b611d3660006113b9565b5b80611d54611d4e611d498c8890611baf565b610285565b91610285565b1015611dfb57808a8a611df6938f8c611dee8d611da48e611d9b8f8f908f611d88611d9693611d8d929c809e919091611c13565b611c28565b97908d91611c35565b611c4a565b95908a91611cad565b9190979091611ddc611dd67f4cf4410cc57040e44862ef0f45f3dd5a5e02db8eb8add648d4b0e236f1d07dca986113ad565b9861194a565b98611de5610235565b96879687611401565b0390a3611bee565b611d37565b509950965050505050505081611e22611e1c611e176000610e03565b6102fa565b916102fa565b03611e2c575b5050565b611e6b611e597f20fda5fd27a1ea7bf5b9567f143ac5470bb059374a27e8f67cb44f946f6d0387926113ad565b92611e62610235565b918291826104d7565b0390a23880611e28565b858a611eb6611e9886611e9289611e8c898f611baf565b95611bb7565b94611bb3565b611ea0610235565b93849363ffb0321160e01b855260048501611bbb565b0390fd5b50611ec6878390611baf565b611ee2611edc611ed78d8890611bb7565b610285565b91610285565b1415611d06565b90611efa9897969594939291611b8c565b565b611f05906116fb565b90565b90611f1290611efc565b600052602052604060002090565b60ff1690565b611f32611f379161176c565b611f20565b90565b611f449054611f26565b90565b611f6e916000611f63611f6993611f5c61154d565b5082611754565b01611f08565b611f3a565b90565b60209181520190565b90565b611f8690610255565b9052565b90611f9781602093611f7d565b0190565b50611faa906020810190610276565b90565b60200190565b91611fc182611fc792611f71565b92611f7a565b90816000905b828210611fdb575050505090565b90919293611ffd611ff7600192611ff28886611f9b565b611f8a565b95611fad565b920190929192611fcd565b60209181520190565b600080fd5b9037565b90918261202691612008565b9160018060fb1b03811161204957829160206120459202938491612016565b0190565b612011565b60209181520190565b90565b60209181520190565b919061207d81612076816120829561205a565b809561069d565b61061c565b0190565b906120919291612063565b90565b600080fd5b600080fd5b600080fd5b90356001602003823603038112156120e457016020813591019167ffffffffffffffff82116120df5760018202360383136120da57565b612099565b612094565b61209e565b60200190565b91816120fa9161204e565b908161210b60208302840194612057565b92836000925b8484106121215750505050505090565b909192939495602061214d61214783856001950388526121418b886120a3565b90612086565b986120e9565b940194019294939190612111565b93956121966121af946121b6999b9a98612188608099956121a49760a08b01918b830360008d0152611fb3565b9188830360208a015261201a565b9185830360408701526120ef565b9660608301906104ca565b01906104ca565b565b946121eb946121fa9792969893986121ce61174f565b5096989490919293946121df610235565b998a9860208a0161215b565b6020820181038252038261063c565b61220c61220682611b33565b91611b2d565b2090565b505050505061221d6116da565b5061222b63bc197c81611716565b90565b6122479061224261223d610d60565b6128e3565b612249565b565b6122eb90600461228563a7fc7a0760e01b61227684612266610235565b9485936020850190815201610924565b6020820181038252038261063c565b906122c36122d27f000000000000000000000000000000000000000000000000000000000000000093926122b7610235565b92839160208301610924565b6020820181038252038261063c565b6122e46122de82611b33565b91611b2d565b2091612ed8565b565b6122f69061222e565b565b6123119061230c612307610e6c565b6128e3565b6123b4565b565b91602061233592949361232e604082019660008301906104ca565b01906104ca565b565b90612341906113ad565b600052602052604060002090565b1b90565b9190600861236f9102916123696000198461234f565b9261234f565b9181191691161790565b919061238f61238a6123979361194a565b611966565b908354612353565b9055565b600090565b6123b2916123ac61239b565b91612379565b565b6123c66123c082611890565b1561042e565b612422576123e060006123db60018490612337565b6123a0565b61240a7fbaa1eb22f2a492ba1a5fea61b8df4d27c6c8b5f3971e63bb58fa14ff72eedb70916113ad565b90612413610235565b8061241d8161039f565b0390a2565b61242c6001612fbd565b6124366002612fbd565b1790612459612443610235565b928392635ead8eb560e01b845260048401612313565b0390fd5b612466906122f8565b565b61247f6124849161247761239b565b506001612337565b611902565b90565b906124a29161249d61249882611796565b6128e3565b6124a4565b565b906124ae91612d41565b50565b906124bb91612487565b565b906124d7916124d26124cd610d60565b6128e3565b612554565b565b6124e36040610665565b90565b906124f090610255565b9052565b906020806125189361250e60008201516000860190611f7d565b0151910190611f7d565b565b919061252e906000604085019401906124f4565b565b91602061255292949361254b60408201966000830190610917565b0190610917565b565b908161257161256b6125666000611583565b610255565b91610255565b148015612667575b612644578160046125dc612642946125a9856125a06125966124d9565b93600085016124e6565b602083016124e6565b6125cd6308be5f7160e21b916125bd610235565b948593602085019081520161251a565b6020820181038252038261063c565b916126297f0000000000000000000000000000000000000000000000000000000000000000939261261a61260e610235565b93849260208401612530565b6020820181038252038261063c565b61263b61263582611b33565b91611b2d565b2091612ed8565b565b61264c610235565b63e6c4247b60e01b8152806126636004820161039f565b0390fd5b508061268461267e6126796000611583565b610255565b91610255565b14612579565b90612694916124bd565b565b906126d1979695949392916126a961049b565b6126c66126c0826126ba6000611583565b90611f47565b1561042e565b6126d3575b506126eb565b565b6126e5906126df612a1d565b90612a4e565b386126cb565b90919497966126fb828490611baf565b61271761271161270c898890611bb3565b610285565b91610285565b1415801561286e575b61282a5761273d612744918390898c878b8a918c939495966121b8565b9687612a90565b61274e60006113b9565b5b8061276c612766612761858790611baf565b610285565b91610285565b1015612817576128129061278a61278584868491611c13565b611c28565b61279e61279989888591611c35565b611c4a565b906127ab888d8591611cad565b92906127bb838383908792612bb5565b8b9161280a86949192956127f86127f27fc2617efa69bab66782fa219543714338489c4e9e178271560a91b82c3f612b58966113ad565b9661194a565b96612801610235565b948594856115e2565b0390a3611bee565b61274f565b505050505050612828919250612bea565b565b50916128468861284061284c9461286a96611baf565b95611bb7565b94611bb3565b612854610235565b93849363ffb0321160e01b855260048501611bbb565b0390fd5b5061287a828490611baf565b61289661289061288b888d90611bb7565b610285565b91610285565b1415612720565b906128ad97969594939291612696565b565b50505050506128bc6116da565b506128ca63f23a6e61611716565b90565b6128d561239b565b506128e06002611902565b90565b6128f5906128ef612a1d565b90612a4e565b565b634e487b7160e01b600052601160045260246000fd5b61291c61292291939293610285565b92610285565b820180921161292d57565b6128f7565b9061293c82611817565b6129a7576129486128cd565b8161295b61295583610285565b91610285565b1061298157509061297a61297261297f934261290d565b916001612337565b611969565b565b906129a361298d610235565b928392635433660960e01b84526004840161190f565b0390fd5b506129b26000612fbd565b906129d46129be610235565b928392635ead8eb560e01b845260048401612313565b0390fd5b6129e061154d565b50806129fb6129f5630271189760e51b6103df565b916103df565b14908115612a08575b5090565b612a129150612fee565b38612a04565b600090565b612a25612a18565b503390565b916020612a4c929493612a4560408201966000830190610917565b01906104ca565b565b90612a63612a5d838390611f47565b1561042e565b612a6b575050565b612a8c612a76610235565b92839263e2517d3f60e01b845260048401612a2a565b0390fd5b612aa2612a9c826116b1565b1561042e565b612b10575080612ac3612abd612ab86000610e03565b6102fa565b916102fa565b141580612af8575b612ad25750565b612af490612ade610235565b91829163121534c360e31b8352600483016104d7565b0390fd5b50612b0b612b05826117b8565b1561042e565b612acb565b612b1a6002612fbd565b90612b3c612b26610235565b928392635ead8eb560e01b845260048401612313565b0390fd5b905090565b909182612b5581612b5c93612b40565b809361069d565b0190565b9091612b6b92612b45565b90565b90612b80612b7b8361067a565b610665565b918252565b606090565b3d600014612ba757612b9b3d612b6e565b903d6000602084013e5b565b612baf612b85565b90612ba5565b90612be79360009384939290612bd5612bcc610235565b93849283612b60565b03925af1612be1612b8a565b9061302e565b50565b612bfc612bf6826116b1565b1561042e565b612c1e57612c1c90612c17612c0f611a4d565b916001612337565b611969565b565b612c286002612fbd565b90612c4a612c34610235565b928392635ead8eb560e01b845260048401612313565b0390fd5b90612c5a60ff91610dfd565b9181191691161790565b612c6d9061042e565b90565b90565b90612c88612c83612c8f92612c64565b612c70565b8254612c4e565b9055565b612c9b61154d565b50612cb0612caa828490611f47565b1561042e565b600014612d3a57612cd96001612cd46000612ccc818690611754565b018590611f08565b612c73565b90612ce2612a1d565b90612d1f612d19612d137f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d956113ad565b92611efc565b92611efc565b92612d28610235565b80612d328161039f565b0390a4600190565b5050600090565b612d4961154d565b50612d55818390611f47565b600014612ddf57612d7e6000612d796000612d71818690611754565b018590611f08565b612c73565b90612d87612a1d565b90612dc4612dbe612db87ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b956113ad565b92611efc565b92611efc565b92612dcd610235565b80612dd78161039f565b0390a4600190565b5050600090565b612def906116fb565b90565b60ff1690565b612e0c612e07612e1192610dfa565b6109f9565b612df2565b90565b612e1d90612df8565b9052565b60005b838110612e35575050906000910152565b806020918301518185015201612e24565b612e65612e6e602093612e7393612e5c81611b33565b938480936113d5565b95869101612e21565b61061c565b0190565b9194612ec5612eba612ecf9360a096612ead612ed69a9c9b999c612ea360c08a019460008b0190610917565b6020890190612e14565b8682036040880152612e46565b9860608501906104ca565b60808301906104ca565b0190610a32565b565b6000916004612f398493612f2a612f5197612ef230612de6565b9562ea831560e11b93918891612f078a610e03565b9192612f11610a18565b94612f1a610235565b998a9860208a0190815201612e77565b6020820181038252038261063c565b602081019051915af4612f4a612b8a565b501561042e565b612f5757565b612f5f610235565b63e94735af60e01b815280612f766004820161039f565b0390fd5b612f9990612f93612f8d612f9e94612df2565b91610285565b9061234f565b610285565b90565b612fb5612fb0612fba92610285565b610dfd565b6102fa565b90565b612fe6612feb91612fcc61174f565b50612fe1612fdb600192610b14565b91611a31565b612f7a565b612fa1565b90565b612ff661154d565b508061301161300b637965db0b60e01b6103df565b916103df565b1490811561301e575b5090565b6130289150613053565b3861301a565b6130449092919261303d612b85565b501561042e565b6000146130515750613079565b565b61305b61154d565b5061307561306f6301ffc9a760e01b6103df565b916103df565b1490565b61308281611b33565b61309561308f60006113b9565b91610285565b116000146130a557805190602001fd5b6130ad610235565b63d6bda27560e01b8152806130c46004820161039f565b0390fdfea264697066735822122053156fbeab9fe6cfa288f14f6d400cc83a7473fc919c8445fba54bf8fb2ada2364736f6c6343000818003300000000000000000000000088d6d8547bcbd5366538cedccf424776f3f7cabf0000000000000000000000002a7d5d7d71332bbea18fb72ba335eaf4857a1b4500000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000008fe51e349d47e58ca5c94fc6bdd474480ea3f24a00000000000000000000000000000000000000000000000000000000000000010000000000000000000000008fe51e349d47e58ca5c94fc6bdd474480ea3f24a00000000000000000000000000000000000000000000000000000000000000010000000000000000000000008fe51e349d47e58ca5c94fc6bdd474480ea3f24a

Deployed Bytecode

0x60806040526004361015610015575b3661138757005b61002060003561022f565b806301d5062a1461022a57806301ffc9a71461022557806307bd026514610220578063134008d31461021b57806313bc9f2014610216578063150b7a0214610211578063248a9ca31461020c5780632ab0f529146102075780632f2ff15d1461020257806331d50750146101fd57806336568abe146101f85780634f7b02ee146101f3578063584b153e146101ee57806364d62353146101e957806369b41170146101e45780636cc10283146101df5780637958004c146101da5780638065657f146101d55780638f2a0bb0146101d05780638f61f4f5146101cb57806391d14854146101c6578063a217fddf146101c1578063b08e51c0146101bc578063b1c5f427146101b7578063bc197c81146101b2578063bdb73034146101ad578063c4d252f5146101a8578063d45c4435146101a3578063d547741f1461019e578063dfc6fe9914610199578063e38335e514610194578063f23a6e611461018f5763f27a0c920361000e57611352565b611319565b611276565b611242565b6111e0565b6111ab565b611178565b611145565b6110ed565b610f77565b610e9b565b610e37565b610dc4565b610d8f565b610d23565b610b78565b610b43565b610aae565b610a55565b6109c3565b61096f565b61093a565b6108bf565b61088a565b610856565b6107f3565b6107be565b610785565b6105e2565b610593565b6104ed565b610456565b6103a5565b60e01c90565b60405190565b600080fd5b600080fd5b600080fd5b60018060a01b031690565b61025e9061024a565b90565b61026a81610255565b0361027157565b600080fd5b9050359061028382610261565b565b90565b61029181610285565b0361029857565b600080fd5b905035906102aa82610288565b565b600080fd5b600080fd5b600080fd5b909182601f830112156102f55781359167ffffffffffffffff83116102f05760200192600183028401116102eb57565b6102b6565b6102b1565b6102ac565b90565b610306816102fa565b0361030d57565b600080fd5b9050359061031f826102fd565b565b9160c08383031261039a576103398260008501610276565b92610347836020830161029d565b92604082013567ffffffffffffffff811161039557816103689184016102bb565b92909361039261037b8460608501610312565b936103898160808601610312565b9360a00161029d565b90565b610245565b610240565b60000190565b346103da576103c46103b8366004610321565b9594909493919361153c565b6103cc610235565b806103d68161039f565b0390f35b61023b565b63ffffffff60e01b1690565b6103f4816103df565b036103fb57565b600080fd5b9050359061040d826103eb565b565b906020828203126104295761042691600001610400565b90565b610240565b151590565b61043c9061042e565b9052565b919061045490600060208501940190610433565b565b346104865761048261047161046c36600461040f565b611552565b610479610235565b91829182610440565b0390f35b61023b565b600091031261049657565b610240565b7fd8aa0f3194971a2a116679f7c2090f6939c8d4e01a2a8d7e41d55e5351469e6390565b6104c761049b565b90565b6104d3906102fa565b9052565b91906104eb906000602085019401906104ca565b565b3461051d576104fd36600461048b565b6105196105086104bf565b610510610235565b918291826104d7565b0390f35b61023b565b9060a08282031261058e5761053a8160008401610276565b92610548826020850161029d565b9260408101359167ffffffffffffffff83116105895761056d846105869484016102bb565b93909461057d8160608601610312565b93608001610312565b90565b610245565b610240565b6105ad6105a1366004610522565b949390939291926116a1565b6105b5610235565b806105bf8161039f565b0390f35b906020828203126105dd576105da91600001610312565b90565b610240565b346106125761060e6105fd6105f83660046105c3565b6116b1565b610605610235565b91829182610440565b0390f35b61023b565b600080fd5b601f801991011690565b634e487b7160e01b600052604160045260246000fd5b906106469061061c565b810190811067ffffffffffffffff82111761066057604052565b610626565b90610678610671610235565b928361063c565b565b67ffffffffffffffff81116106985761069460209161061c565b0190565b610626565b90826000939282370152565b909291926106be6106b98261067a565b610665565b938185526020850190828401116106da576106d89261069d565b565b610617565b9080601f830112156106fd578160206106fa933591016106a9565b90565b6102ac565b9060808282031261075d5761071a8160008401610276565b926107288260208501610276565b92610736836040830161029d565b92606082013567ffffffffffffffff81116107585761075592016106df565b90565b610245565b610240565b61076b906103df565b9052565b919061078390600060208501940190610762565b565b346107b9576107b56107a461079b366004610702565b92919091611732565b6107ac610235565b9182918261076f565b0390f35b61023b565b346107ee576107ea6107d96107d43660046105c3565b611796565b6107e1610235565b918291826104d7565b0390f35b61023b565b346108235761081f61080e6108093660046105c3565b6117b8565b610816610235565b91829182610440565b0390f35b61023b565b9190604083820312610851578061084561084e9260008601610312565b93602001610276565b90565b610240565b346108855761086f610869366004610828565b9061180b565b610877610235565b806108818161039f565b0390f35b61023b565b346108ba576108b66108a56108a03660046105c3565b611817565b6108ad610235565b91829182610440565b0390f35b61023b565b346108ee576108d86108d2366004610828565b90611841565b6108e0610235565b806108ea8161039f565b0390f35b61023b565b7f0000000000000000000000002a7d5d7d71332bbea18fb72ba335eaf4857a1b4590565b61092090610255565b9052565b919061093890600060208501940190610917565b565b3461096a5761094a36600461048b565b6109666109556108f3565b61095d610235565b91829182610924565b0390f35b61023b565b3461099f5761099b61098a6109853660046105c3565b611890565b610992610235565b91829182610440565b0390f35b61023b565b906020828203126109be576109bb9160000161029d565b90565b610240565b346109f1576109db6109d63660046109a4565b611989565b6109e3610235565b806109ed8161039f565b0390f35b61023b565b90565b90565b610a10610a0b610a15926109f6565b6109f9565b610285565b90565b610a246202a3006109fc565b90565b610a2f610a18565b90565b610a3b90610285565b9052565b9190610a5390600060208501940190610a32565b565b34610a8557610a6536600461048b565b610a81610a70610a27565b610a78610235565b91829182610a3f565b0390f35b61023b565b7f00000000000000000000000088d6d8547bcbd5366538cedccf424776f3f7cabf90565b34610ade57610abe36600461048b565b610ada610ac9610a8a565b610ad1610235565b91829182610924565b0390f35b61023b565b634e487b7160e01b600052602160045260246000fd5b60041115610b0357565b610ae3565b90610b1282610af9565b565b610b1d90610b08565b90565b610b2990610b14565b9052565b9190610b4190600060208501940190610b20565b565b34610b7357610b6f610b5e610b593660046105c3565b611a5a565b610b66610235565b91829182610b2d565b0390f35b61023b565b34610baf57610bab610b9a610b8e366004610522565b94939093929192611b37565b610ba2610235565b918291826104d7565b0390f35b61023b565b909182601f83011215610bee5781359167ffffffffffffffff8311610be9576020019260208302840111610be457565b6102b6565b6102b1565b6102ac565b909182601f83011215610c2d5781359167ffffffffffffffff8311610c28576020019260208302840111610c2357565b6102b6565b6102b1565b6102ac565b909182601f83011215610c6c5781359167ffffffffffffffff8311610c67576020019260208302840111610c6257565b6102b6565b6102b1565b6102ac565b9060c082820312610d1e57600082013567ffffffffffffffff8111610d195781610c9c918401610bb4565b929093602082013567ffffffffffffffff8111610d145783610cbf918401610bf3565b929093604082013567ffffffffffffffff8111610d0f5781610ce2918401610c32565b929093610d0c610cf58460608501610312565b93610d038160808601610312565b9360a00161029d565b90565b610245565b610245565b610245565b610240565b34610d5b57610d45610d36366004610c71565b97969096959195949294611ee9565b610d4d610235565b80610d578161039f565b0390f35b61023b565b7fb09aa5aeb3702cfd50b6b62bc4532604938f21248a27a1d5ca736082b6819cc190565b610d8c610d60565b90565b34610dbf57610d9f36600461048b565b610dbb610daa610d84565b610db2610235565b918291826104d7565b0390f35b61023b565b34610df557610df1610de0610dda366004610828565b90611f47565b610de8610235565b91829182610440565b0390f35b61023b565b90565b60001b90565b610e17610e12610e1c92610dfa565b610dfd565b6102fa565b90565b610e296000610e03565b90565b610e34610e1f565b90565b34610e6757610e4736600461048b565b610e63610e52610e2c565b610e5a610235565b918291826104d7565b0390f35b61023b565b7ffd643c72710c63c0180259aba6b2d05451e3591a24e58b62239378085726f78390565b610e98610e6c565b90565b34610ecb57610eab36600461048b565b610ec7610eb6610e90565b610ebe610235565b918291826104d7565b0390f35b61023b565b91909160a081840312610f7257600081013567ffffffffffffffff8111610f6d5783610efd918301610bb4565b929093602083013567ffffffffffffffff8111610f685781610f20918501610bf3565b92909360408101359167ffffffffffffffff8311610f6357610f4784610f60948401610c32565b939094610f578160608601610312565b93608001610312565b90565b610245565b610245565b610245565b610240565b34610fb157610fad610f9c610f8d366004610ed0565b969590959491949392936121b8565b610fa4610235565b918291826104d7565b0390f35b61023b565b67ffffffffffffffff8111610fce5760208091020190565b610626565b90929192610fe8610fe382610fb6565b610665565b938185526020808601920283019281841161102557915b83831061100c5750505050565b6020809161101a848661029d565b815201920191610fff565b6102b6565b9080601f830112156110485781602061104593359101610fd3565b90565b6102ac565b91909160a0818403126110e8576110678360008301610276565b926110758160208401610276565b92604083013567ffffffffffffffff81116110e3578261109691850161102a565b92606081013567ffffffffffffffff81116110de57836110b791830161102a565b92608082013567ffffffffffffffff81116110d9576110d692016106df565b90565b610245565b610245565b610245565b610240565b346111215761111d61110c61110336600461104d565b93929092612210565b611114610235565b9182918261076f565b0390f35b61023b565b906020828203126111405761113d91600001610276565b90565b610240565b346111735761115d611158366004611126565b6122ed565b611165610235565b8061116f8161039f565b0390f35b61023b565b346111a65761119061118b3660046105c3565b61245d565b611198610235565b806111a28161039f565b0390f35b61023b565b346111db576111d76111c66111c13660046105c3565b612468565b6111ce610235565b91829182610a3f565b0390f35b61023b565b3461120f576111f96111f3366004610828565b906124b1565b611201610235565b8061120b8161039f565b0390f35b61023b565b919060408382031261123d578061123161123a9260008601610276565b93602001610276565b90565b610240565b346112715761125b611255366004611214565b9061268a565b611263610235565b8061126d8161039f565b0390f35b61023b565b611293611284366004610ed0565b9695909594919493929361289d565b61129b610235565b806112a58161039f565b0390f35b91909160a081840312611314576112c38360008301610276565b926112d18160208401610276565b926112df826040850161029d565b926112ed836060830161029d565b92608082013567ffffffffffffffff811161130f5761130c92016106df565b90565b610245565b610240565b3461134d5761134961133861132f3660046112a9565b939290926128af565b611340610235565b9182918261076f565b0390f35b61023b565b346113825761136236600461048b565b61137e61136d6128cd565b611375610235565b91829182610a3f565b0390f35b61023b565b600080fd5b906113ab9695949392916113a66113a1610d60565b6128e3565b611454565b565b6113b6906102fa565b90565b6113cd6113c86113d292610dfa565b6109f9565b610285565b90565b60209181520190565b91906113f8816113f1816113fd956113d5565b809561069d565b61061c565b0190565b9161144b91611452969897956080956114336114409461142960a089019560008a0190610917565b6020880190610a32565b85830360408701526113de565b9660608301906104ca565b0190610a32565b565b9293949591906114ca61146e85838589908b928d94611b37565b9661147a888690612932565b87946000969394979190916114b86114b27f4cf4410cc57040e44862ef0f45f3dd5a5e02db8eb8add648d4b0e236f1d07dca986113ad565b986113b9565b986114c1610235565b96879687611401565b0390a3816114e96114e36114de6000610e03565b6102fa565b916102fa565b036114f3575b5050565b6115326115207f20fda5fd27a1ea7bf5b9567f143ac5470bb059374a27e8f67cb44f946f6d0387926113ad565b92611529610235565b918291826104d7565b0390a238806114ef565b9061154b96959493929161138c565b565b600090565b6115649061155e61154d565b506129d8565b90565b61157b61157661158092610dfa565b6109f9565b61024a565b90565b61158c90611567565b90565b906115c895949392916115a061049b565b6115bd6115b7826115b16000611583565b90611f47565b1561042e565b6115ca575b50611619565b565b6115dc906115d6612a1d565b90612a4e565b386115c2565b61160961161695939492946115ff60608401966000850190610917565b6020830190610a32565b60408185039101526113de565b90565b9161163961163261169f978590858589918b9394611b37565b9586612a90565b611647838383908792612bb5565b849161169760009491929561168561167f7fc2617efa69bab66782fa219543714338489c4e9e178271560a91b82c3f612b58966113ad565b966113b9565b9661168e610235565b948594856115e2565b0390a3612bea565b565b906116af959493929161158f565b565b6116c3906116bd61154d565b50611a5a565b6116d66116d06002610b08565b91610b08565b1490565b600090565b6116f36116ee6116f89261024a565b6109f9565b61024a565b90565b611704906116df565b90565b63ffffffff1690565b60e01b90565b61172a61172561172f92611707565b611710565b6103df565b90565b5050505061173e6116da565b5061174c63150b7a02611716565b90565b600090565b9061175e906113ad565b600052602052604060002090565b60001c90565b90565b6117816117869161176c565b611772565b90565b6117939054611775565b90565b60016117af6117b5926117a761174f565b506000611754565b01611789565b90565b6117ca906117c461154d565b50611a5a565b6117dd6117d76003610b08565b91610b08565b1490565b906117fc916117f76117f282611796565b6128e3565b6117fe565b565b9061180891612c93565b50565b90611815916117e1565b565b6118299061182361154d565b50611a5a565b61183c6118366000610b08565b91610b08565b141590565b908061185c611856611851612a1d565b610255565b91610255565b0361186d5761186a91612d41565b50565b611875610235565b63334bd91960e11b81528061188c6004820161039f565b0390fd5b6118a29061189c61154d565b50611a5a565b806118b66118b06001610b08565b91610b08565b149081156118c3575b5090565b90506118d86118d26002610b08565b91610b08565b14386118bf565b6118e8906116fb565b90565b90565b6118fa6118ff9161176c565b6118eb565b90565b61190c90546118ee565b90565b91602061193192949361192a60408201966000830190610a32565b0190610a32565b565b9061194060001991610dfd565b9181191691161790565b61195e61195961196392610285565b6109f9565b610285565b90565b90565b9061197e6119796119859261194a565b611966565b8254611933565b9055565b611991612a1d565b806119ac6119a66119a1306118df565b610255565b91610255565b03611a035750611a01906119c06002611902565b817f11c24f4ead16507c69ac467fbd5e4eed5fb5c699626d2cc6d66421df253886d5916119f76119ee610235565b9283928361190f565b0390a16002611969565b565b611a2590611a0f610235565b91829163e2850c5960e01b835260048301610924565b0390fd5b600090565b90565b611a45611a40611a4a92611a2e565b6109f9565b610285565b90565b611a576001611a31565b90565b611a6c90611a66611a29565b50612468565b80611a80611a7a60006113b9565b91610285565b14600014611a8e5750600090565b80611aa8611aa2611a9d611a4d565b610285565b91610285565b14600014611ab65750600390565b611ac8611ac242610285565b91610285565b11600014611ad557600190565b600290565b91611b2491611b2b96989795608095611b0c611b1994611b0260a089019560008a0190610917565b6020880190610a32565b85830360408701526113de565b9660608301906104ca565b01906104ca565b565b60200190565b5190565b94611b7694611b679396949294611b4c61174f565b50949692909192611b5b610235565b97889660208801611ada565b6020820181038252038261063c565b611b88611b8282611b33565b91611b2d565b2090565b90611bad9897969594939291611ba8611ba3610d60565b6128e3565b611ccd565b565b5090565b5090565b5090565b604090611be5611bec9496959396611bdb60608401986000850190610a32565b6020830190610a32565b0190610a32565b565b6001611bfa9101610285565b90565b634e487b7160e01b600052603260045260246000fd5b9190811015611c23576020020190565b611bfd565b35611c3281610261565b90565b9190811015611c45576020020190565b611bfd565b35611c5481610288565b90565b600080fd5b600080fd5b600080fd5b903590600160200381360303821215611ca8570180359067ffffffffffffffff8211611ca357602001916001820236038313611c9e57565b611c61565b611c5c565b611c57565b90821015611cc8576020611cc49202810190611c66565b9091565b611bfd565b959697939894929194611ce1878390611baf565b611cfd611cf7611cf2898790611bb3565b610285565b91610285565b14158015611eba575b611e7557611d20878a8a8d86908b8991928b9495966121b8565b90611d2c828790612932565b611d3660006113b9565b5b80611d54611d4e611d498c8890611baf565b610285565b91610285565b1015611dfb57808a8a611df6938f8c611dee8d611da48e611d9b8f8f908f611d88611d9693611d8d929c809e919091611c13565b611c28565b97908d91611c35565b611c4a565b95908a91611cad565b9190979091611ddc611dd67f4cf4410cc57040e44862ef0f45f3dd5a5e02db8eb8add648d4b0e236f1d07dca986113ad565b9861194a565b98611de5610235565b96879687611401565b0390a3611bee565b611d37565b509950965050505050505081611e22611e1c611e176000610e03565b6102fa565b916102fa565b03611e2c575b5050565b611e6b611e597f20fda5fd27a1ea7bf5b9567f143ac5470bb059374a27e8f67cb44f946f6d0387926113ad565b92611e62610235565b918291826104d7565b0390a23880611e28565b858a611eb6611e9886611e9289611e8c898f611baf565b95611bb7565b94611bb3565b611ea0610235565b93849363ffb0321160e01b855260048501611bbb565b0390fd5b50611ec6878390611baf565b611ee2611edc611ed78d8890611bb7565b610285565b91610285565b1415611d06565b90611efa9897969594939291611b8c565b565b611f05906116fb565b90565b90611f1290611efc565b600052602052604060002090565b60ff1690565b611f32611f379161176c565b611f20565b90565b611f449054611f26565b90565b611f6e916000611f63611f6993611f5c61154d565b5082611754565b01611f08565b611f3a565b90565b60209181520190565b90565b611f8690610255565b9052565b90611f9781602093611f7d565b0190565b50611faa906020810190610276565b90565b60200190565b91611fc182611fc792611f71565b92611f7a565b90816000905b828210611fdb575050505090565b90919293611ffd611ff7600192611ff28886611f9b565b611f8a565b95611fad565b920190929192611fcd565b60209181520190565b600080fd5b9037565b90918261202691612008565b9160018060fb1b03811161204957829160206120459202938491612016565b0190565b612011565b60209181520190565b90565b60209181520190565b919061207d81612076816120829561205a565b809561069d565b61061c565b0190565b906120919291612063565b90565b600080fd5b600080fd5b600080fd5b90356001602003823603038112156120e457016020813591019167ffffffffffffffff82116120df5760018202360383136120da57565b612099565b612094565b61209e565b60200190565b91816120fa9161204e565b908161210b60208302840194612057565b92836000925b8484106121215750505050505090565b909192939495602061214d61214783856001950388526121418b886120a3565b90612086565b986120e9565b940194019294939190612111565b93956121966121af946121b6999b9a98612188608099956121a49760a08b01918b830360008d0152611fb3565b9188830360208a015261201a565b9185830360408701526120ef565b9660608301906104ca565b01906104ca565b565b946121eb946121fa9792969893986121ce61174f565b5096989490919293946121df610235565b998a9860208a0161215b565b6020820181038252038261063c565b61220c61220682611b33565b91611b2d565b2090565b505050505061221d6116da565b5061222b63bc197c81611716565b90565b6122479061224261223d610d60565b6128e3565b612249565b565b6122eb90600461228563a7fc7a0760e01b61227684612266610235565b9485936020850190815201610924565b6020820181038252038261063c565b906122c36122d27f00000000000000000000000088d6d8547bcbd5366538cedccf424776f3f7cabf93926122b7610235565b92839160208301610924565b6020820181038252038261063c565b6122e46122de82611b33565b91611b2d565b2091612ed8565b565b6122f69061222e565b565b6123119061230c612307610e6c565b6128e3565b6123b4565b565b91602061233592949361232e604082019660008301906104ca565b01906104ca565b565b90612341906113ad565b600052602052604060002090565b1b90565b9190600861236f9102916123696000198461234f565b9261234f565b9181191691161790565b919061238f61238a6123979361194a565b611966565b908354612353565b9055565b600090565b6123b2916123ac61239b565b91612379565b565b6123c66123c082611890565b1561042e565b612422576123e060006123db60018490612337565b6123a0565b61240a7fbaa1eb22f2a492ba1a5fea61b8df4d27c6c8b5f3971e63bb58fa14ff72eedb70916113ad565b90612413610235565b8061241d8161039f565b0390a2565b61242c6001612fbd565b6124366002612fbd565b1790612459612443610235565b928392635ead8eb560e01b845260048401612313565b0390fd5b612466906122f8565b565b61247f6124849161247761239b565b506001612337565b611902565b90565b906124a29161249d61249882611796565b6128e3565b6124a4565b565b906124ae91612d41565b50565b906124bb91612487565b565b906124d7916124d26124cd610d60565b6128e3565b612554565b565b6124e36040610665565b90565b906124f090610255565b9052565b906020806125189361250e60008201516000860190611f7d565b0151910190611f7d565b565b919061252e906000604085019401906124f4565b565b91602061255292949361254b60408201966000830190610917565b0190610917565b565b908161257161256b6125666000611583565b610255565b91610255565b148015612667575b612644578160046125dc612642946125a9856125a06125966124d9565b93600085016124e6565b602083016124e6565b6125cd6308be5f7160e21b916125bd610235565b948593602085019081520161251a565b6020820181038252038261063c565b916126297f0000000000000000000000002a7d5d7d71332bbea18fb72ba335eaf4857a1b45939261261a61260e610235565b93849260208401612530565b6020820181038252038261063c565b61263b61263582611b33565b91611b2d565b2091612ed8565b565b61264c610235565b63e6c4247b60e01b8152806126636004820161039f565b0390fd5b508061268461267e6126796000611583565b610255565b91610255565b14612579565b90612694916124bd565b565b906126d1979695949392916126a961049b565b6126c66126c0826126ba6000611583565b90611f47565b1561042e565b6126d3575b506126eb565b565b6126e5906126df612a1d565b90612a4e565b386126cb565b90919497966126fb828490611baf565b61271761271161270c898890611bb3565b610285565b91610285565b1415801561286e575b61282a5761273d612744918390898c878b8a918c939495966121b8565b9687612a90565b61274e60006113b9565b5b8061276c612766612761858790611baf565b610285565b91610285565b1015612817576128129061278a61278584868491611c13565b611c28565b61279e61279989888591611c35565b611c4a565b906127ab888d8591611cad565b92906127bb838383908792612bb5565b8b9161280a86949192956127f86127f27fc2617efa69bab66782fa219543714338489c4e9e178271560a91b82c3f612b58966113ad565b9661194a565b96612801610235565b948594856115e2565b0390a3611bee565b61274f565b505050505050612828919250612bea565b565b50916128468861284061284c9461286a96611baf565b95611bb7565b94611bb3565b612854610235565b93849363ffb0321160e01b855260048501611bbb565b0390fd5b5061287a828490611baf565b61289661289061288b888d90611bb7565b610285565b91610285565b1415612720565b906128ad97969594939291612696565b565b50505050506128bc6116da565b506128ca63f23a6e61611716565b90565b6128d561239b565b506128e06002611902565b90565b6128f5906128ef612a1d565b90612a4e565b565b634e487b7160e01b600052601160045260246000fd5b61291c61292291939293610285565b92610285565b820180921161292d57565b6128f7565b9061293c82611817565b6129a7576129486128cd565b8161295b61295583610285565b91610285565b1061298157509061297a61297261297f934261290d565b916001612337565b611969565b565b906129a361298d610235565b928392635433660960e01b84526004840161190f565b0390fd5b506129b26000612fbd565b906129d46129be610235565b928392635ead8eb560e01b845260048401612313565b0390fd5b6129e061154d565b50806129fb6129f5630271189760e51b6103df565b916103df565b14908115612a08575b5090565b612a129150612fee565b38612a04565b600090565b612a25612a18565b503390565b916020612a4c929493612a4560408201966000830190610917565b01906104ca565b565b90612a63612a5d838390611f47565b1561042e565b612a6b575050565b612a8c612a76610235565b92839263e2517d3f60e01b845260048401612a2a565b0390fd5b612aa2612a9c826116b1565b1561042e565b612b10575080612ac3612abd612ab86000610e03565b6102fa565b916102fa565b141580612af8575b612ad25750565b612af490612ade610235565b91829163121534c360e31b8352600483016104d7565b0390fd5b50612b0b612b05826117b8565b1561042e565b612acb565b612b1a6002612fbd565b90612b3c612b26610235565b928392635ead8eb560e01b845260048401612313565b0390fd5b905090565b909182612b5581612b5c93612b40565b809361069d565b0190565b9091612b6b92612b45565b90565b90612b80612b7b8361067a565b610665565b918252565b606090565b3d600014612ba757612b9b3d612b6e565b903d6000602084013e5b565b612baf612b85565b90612ba5565b90612be79360009384939290612bd5612bcc610235565b93849283612b60565b03925af1612be1612b8a565b9061302e565b50565b612bfc612bf6826116b1565b1561042e565b612c1e57612c1c90612c17612c0f611a4d565b916001612337565b611969565b565b612c286002612fbd565b90612c4a612c34610235565b928392635ead8eb560e01b845260048401612313565b0390fd5b90612c5a60ff91610dfd565b9181191691161790565b612c6d9061042e565b90565b90565b90612c88612c83612c8f92612c64565b612c70565b8254612c4e565b9055565b612c9b61154d565b50612cb0612caa828490611f47565b1561042e565b600014612d3a57612cd96001612cd46000612ccc818690611754565b018590611f08565b612c73565b90612ce2612a1d565b90612d1f612d19612d137f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d956113ad565b92611efc565b92611efc565b92612d28610235565b80612d328161039f565b0390a4600190565b5050600090565b612d4961154d565b50612d55818390611f47565b600014612ddf57612d7e6000612d796000612d71818690611754565b018590611f08565b612c73565b90612d87612a1d565b90612dc4612dbe612db87ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b956113ad565b92611efc565b92611efc565b92612dcd610235565b80612dd78161039f565b0390a4600190565b5050600090565b612def906116fb565b90565b60ff1690565b612e0c612e07612e1192610dfa565b6109f9565b612df2565b90565b612e1d90612df8565b9052565b60005b838110612e35575050906000910152565b806020918301518185015201612e24565b612e65612e6e602093612e7393612e5c81611b33565b938480936113d5565b95869101612e21565b61061c565b0190565b9194612ec5612eba612ecf9360a096612ead612ed69a9c9b999c612ea360c08a019460008b0190610917565b6020890190612e14565b8682036040880152612e46565b9860608501906104ca565b60808301906104ca565b0190610a32565b565b6000916004612f398493612f2a612f5197612ef230612de6565b9562ea831560e11b93918891612f078a610e03565b9192612f11610a18565b94612f1a610235565b998a9860208a0190815201612e77565b6020820181038252038261063c565b602081019051915af4612f4a612b8a565b501561042e565b612f5757565b612f5f610235565b63e94735af60e01b815280612f766004820161039f565b0390fd5b612f9990612f93612f8d612f9e94612df2565b91610285565b9061234f565b610285565b90565b612fb5612fb0612fba92610285565b610dfd565b6102fa565b90565b612fe6612feb91612fcc61174f565b50612fe1612fdb600192610b14565b91611a31565b612f7a565b612fa1565b90565b612ff661154d565b508061301161300b637965db0b60e01b6103df565b916103df565b1490811561301e575b5090565b6130289150613053565b3861301a565b6130449092919261303d612b85565b501561042e565b6000146130515750613079565b565b61305b61154d565b5061307561306f6301ffc9a760e01b6103df565b916103df565b1490565b61308281611b33565b61309561308f60006113b9565b91610285565b116000146130a557805190602001fd5b6130ad610235565b63d6bda27560e01b8152806130c46004820161039f565b0390fdfea264697066735822122053156fbeab9fe6cfa288f14f6d400cc83a7473fc919c8445fba54bf8fb2ada2364736f6c63430008180033

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

00000000000000000000000088d6d8547bcbd5366538cedccf424776f3f7cabf0000000000000000000000002a7d5d7d71332bbea18fb72ba335eaf4857a1b4500000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000e00000000000000000000000008fe51e349d47e58ca5c94fc6bdd474480ea3f24a00000000000000000000000000000000000000000000000000000000000000010000000000000000000000008fe51e349d47e58ca5c94fc6bdd474480ea3f24a00000000000000000000000000000000000000000000000000000000000000010000000000000000000000008fe51e349d47e58ca5c94fc6bdd474480ea3f24a

-----Decoded View---------------
Arg [0] : vault_ (address): 0x88d6D8547Bcbd5366538cEdCCF424776f3f7CABF
Arg [1] : oracle_ (address): 0x2a7d5d7D71332bbeA18fb72Ba335EaF4857A1b45
Arg [2] : proposers (address[]): 0x8fE51e349d47E58cA5C94FC6BDD474480eA3F24A
Arg [3] : executors (address[]): 0x8fE51e349d47E58cA5C94FC6BDD474480eA3F24A
Arg [4] : admin (address): 0x8fE51e349d47E58cA5C94FC6BDD474480eA3F24A

-----Encoded View---------------
9 Constructor Arguments found :
Arg [0] : 00000000000000000000000088d6d8547bcbd5366538cedccf424776f3f7cabf
Arg [1] : 0000000000000000000000002a7d5d7d71332bbea18fb72ba335eaf4857a1b45
Arg [2] : 00000000000000000000000000000000000000000000000000000000000000a0
Arg [3] : 00000000000000000000000000000000000000000000000000000000000000e0
Arg [4] : 0000000000000000000000008fe51e349d47e58ca5c94fc6bdd474480ea3f24a
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [6] : 0000000000000000000000008fe51e349d47e58ca5c94fc6bdd474480ea3f24a
Arg [7] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [8] : 0000000000000000000000008fe51e349d47e58ca5c94fc6bdd474480ea3f24a


Block Transaction 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
[ 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.