Overview
S Balance
S Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 12 from a total of 12 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Execute | 13462080 | 1 hr ago | IN | 0 S | 0.00595941 | ||||
Execute | 13462034 | 1 hr ago | IN | 0 S | 0.00595941 | ||||
Schedule Set Tok... | 13349068 | 14 hrs ago | IN | 0 S | 0.00365502 | ||||
Schedule Set Tok... | 13349063 | 14 hrs ago | IN | 0 S | 0.00365502 | ||||
Schedule Set Tok... | 13216315 | 29 hrs ago | IN | 0 S | 0.00365502 | ||||
Schedule Set Tok... | 13126461 | 41 hrs ago | IN | 0 S | 0.00365502 | ||||
Schedule Add Con... | 13011585 | 2 days ago | IN | 0 S | 0.00351928 | ||||
Schedule Add Con... | 13011581 | 2 days ago | IN | 0 S | 0.00351928 | ||||
Execute | 12944467 | 2 days ago | IN | 0 S | 0.00631631 | ||||
Execute | 12944465 | 2 days ago | IN | 0 S | 0.00593241 | ||||
Schedule Set Tok... | 12547667 | 4 days ago | IN | 0 S | 0.00365502 | ||||
Schedule Set Tok... | 12547663 | 4 days ago | IN | 0 S | 0.00365502 |
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
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
Contract Source Code (Solidity Standard Json-Input format)
// 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(); } }
// 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; } } }
// 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; }
// 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)); } }
// 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); }
// 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; } }
// 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); }
// 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; } }
// 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(); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol) pragma solidity ^0.8.20; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.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); }
// 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; } }
// 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); }
// 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; } }
// 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()); } } }
// 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); }
// 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); }
// 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); }
// 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); } }
{ "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
- No Contract Security Audit Submitted- Submit Audit Here
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"}]
Contract Creation Code
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
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 35 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
[ 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.