{"file_path":"src/core/coins/YieldCoin.sol","creation_status":"success","source_code":"/**\n * Copyright 2025 Circle Internet Group, Inc. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npragma solidity ^0.8.0;\n\n// imported contracts and libraries\nimport {Access} from \"../entitlements/Access.sol\";\nimport {ERC20} from \"./ERC20.sol\";\nimport {Initializable} from \"openzeppelin-upgradeable/proxy/utils/Initializable.sol\";\nimport {Ownable} from \"../entitlements/Ownable.sol\";\nimport {SafeERC20} from \"openzeppelin/token/ERC20/utils/SafeERC20.sol\";\nimport {UUPSUpgradeable} from \"openzeppelin/proxy/utils/UUPSUpgradeable.sol\";\n\n// interfaces\nimport {IToken} from \"../../interfaces/IToken.sol\";\nimport {Teller} from \"../tellers/Teller.sol\";\n\nimport \"../../config/constants.sol\";\nimport \"../../config/errors.sol\";\n\n/**\n * @title   YieldCoin\n * @author  dsshap\n * @dev     Represent the shares of a tokenized Fund\n *             The value of the token should always be positive.\n */\ncontract YieldCoin is ERC20, Initializable, Access, Ownable, UUPSUpgradeable {\n    /*///////////////////////////////////////////////////////////////\n                                Events\n    //////////////////////////////////////////////////////////////*/\n\n    event TellerSet(address teller, address newTeller);\n    event UnderlyingSet(address token);\n    event Sweep(address indexed recipient, address token, uint256 amount);\n    event MinterConfigured(address minter, uint256 amount);\n\n    /// @notice ***DEPRECATED***\n    event FeeRecipientSet(address recipient, address newRecipient);\n    event ManagementFeeSet(uint256 managementFee, uint256 newManagementFee);\n    event OracleSet(address oracle, address newOracle);\n    event TradeToFiat(address indexed recipient, address token, uint256 amount);\n    event Deposit(address indexed from, uint256 amount);\n    event Withdrawal(address indexed to, uint256 amount);\n    event FeeProcessed(address indexed recipient, uint256 fee);\n\n    /*///////////////////////////////////////////////////////////////\n                         State Variables V1 & V2\n    //////////////////////////////////////////////////////////////*/\n\n    uint256[7] private __deprecatedGap0;\n\n    /*///////////////////////////////////////////////////////////////\n                         State Variables V3\n    //////////////////////////////////////////////////////////////*/\n\n    /// @notice the addresses that are able to mint new tokens\n    mapping(address => uint256) public minterAllowance;\n\n    /*///////////////////////////////////////////////////////////////\n                         State Variables V4\n    //////////////////////////////////////////////////////////////*/\n\n    uint256 internal _decimals;\n\n    uint256 internal immutable _initialChainId;\n\n    bytes32 internal _initialDomainSeparator;\n\n    uint256[1] private __deprecatedGap1;\n\n    /*///////////////////////////////////////////////////////////////\n                Constructor for implementation Contract\n    //////////////////////////////////////////////////////////////*/\n\n    constructor(address _authority) ERC20() Access(_authority) {\n        _initialChainId = block.chainid;\n\n        _disableInitializers();\n    }\n\n    /*///////////////////////////////////////////////////////////////\n                            Initializer\n    //////////////////////////////////////////////////////////////*/\n\n    function initialize(string memory _name, string memory _symbol, uint8 _dec, address _owner, address _minter)\n        external\n        initializer\n    {\n        if (_owner == address(0)) revert BadAddress();\n        if (_minter == address(0)) revert BadAddress();\n\n        _transferOwnership(_owner);\n\n        name = _name;\n        symbol = _symbol;\n        _decimals = _dec;\n\n        minterAllowance[_minter] = type(uint256).max;\n\n        _initialDomainSeparator = _computeDomainSeparator();\n    }\n\n    /*///////////////////////////////////////////////////////////////\n                        ERC20 Functions\n    //////////////////////////////////////////////////////////////*/\n\n    function transfer(address _to, uint256 _amount) public virtual override returns (bool) {\n        _assertPermission(msg.sender);\n        _assertCanReceive(address(this), _to);\n\n        return super.transfer(_to, _amount);\n    }\n\n    function transferFrom(address _from, address _to, uint256 _amount) public virtual override returns (bool) {\n        if (_isFundAdmin()) {\n            balanceOf[_from] -= _amount;\n\n            // Cannot overflow because the sum of all user\n            // balances can't exceed the max uint256 value.\n            unchecked {\n                balanceOf[_to] += _amount;\n            }\n\n            emit Transfer(_from, _to, _amount);\n\n            return true;\n        } else {\n            _assertPermission(msg.sender);\n            _assertCanReceive(address(this), _from, _to);\n\n            return super.transferFrom(_from, _to, _amount);\n        }\n    }\n\n    function mint(address _to, uint256 _amount) external returns (bool) {\n        uint256 allowed = minterAllowance[msg.sender]; // Saves gas for limited approvals.\n        if (allowed != type(uint256).max) minterAllowance[msg.sender] = allowed - _amount;\n\n        // checking that recipient has permissions to hold/transfer token\n        _assertCanReceive(address(this), _to);\n\n        _mint(_to, _amount);\n\n        return true;\n    }\n\n    /**\n     * @notice burns for sender\n     * @param _amount The amount to burn\n     */\n    function burn(uint256 _amount) external {\n        _assertPermission(msg.sender);\n\n        _burn(msg.sender, _amount);\n    }\n\n    /**\n     * @notice burns tokens for a user\n     * @dev only callable by minter\n     * @param _from The address to burn tokens for\n     * @param _amount The amount of tokens to burn\n     */\n    function burn(address _from, uint256 _amount) public {\n        if (minterAllowance[msg.sender] == 0) revert NoAccess();\n\n        // checking that recipient has permissions to hold/transfer token\n        _assertCanReceive(address(this), _from);\n\n        _burn(_from, _amount);\n    }\n\n    /**\n     * @notice burns tokens for a user\n     * @dev only callable by minter\n     * @param _from The address to burn tokens for\n     * @param _amount The amount of tokens to burn\n     */\n    function burnFor(address _from, uint256 _amount) external {\n        burn(_from, _amount);\n    }\n\n    function decimals() public view returns (uint8) {\n        return uint8(_decimals);\n    }\n\n    /**\n     * @notice Sends token to be converted to fiat\n     * @param _token address of token\n     * @param _amount is the amount\n     * @param _recipient the destination\n     */\n    function sweep(address _token, uint256 _amount, address _recipient) external virtual {\n        _assertFundAdmin();\n\n        if (!authority.doesUserHaveRole(_recipient, ROLE_RESERVES)) revert NotPermissioned();\n\n        emit Sweep(_recipient, _token, _amount);\n\n        SafeERC20.safeTransfer(IToken(_token), _recipient, _amount);\n    }\n\n    /*///////////////////////////////////////////////////////////////\n                        Management Functions\n    //////////////////////////////////////////////////////////////*/\n\n    /**\n     * @notice Sets the minter role and the amount of tokens the minter is allowed to mint\n     * @param _minter is the address of the new minter\n     * @param _amount is the amount of tokens the minter is allowed to mint\n     */\n    function setMinterAllowance(address _minter, uint256 _amount) public {\n        _assertPermission(msg.sender);\n\n        if (_minter == address(0)) revert BadAddress();\n\n        emit MinterConfigured(_minter, _amount);\n\n        minterAllowance[_minter] = _amount;\n    }\n\n    /**\n     * @notice Increments the amount of token a minter is allowed to mint\n     * @param _minter is the address of the new minter\n     * @param _amount is the amount of tokens to increase the allowance by\n     */\n    function incrementMinterAllowance(address _minter, uint256 _amount) external {\n        uint256 current = minterAllowance[_minter];\n\n        setMinterAllowance(_minter, current + _amount);\n    }\n\n    /**\n     * @notice Decrements the amount of tokens a minter is allowed to mint\n     * @param _minter is the address of the new minter\n     * @param _amount is the amount of tokens to decrease the allowance by\n     */\n    function decrementMinterAllowance(address _minter, uint256 _amount) external {\n        uint256 current = minterAllowance[_minter];\n        uint256 decrement = current > _amount ? _amount : current;\n\n        setMinterAllowance(_minter, current - decrement);\n    }\n\n    /*//////////////////////////////////////////////////////////////\n                             EIP-2612 LOGIC\n    //////////////////////////////////////////////////////////////*/\n\n    function DOMAIN_SEPARATOR() public view override returns (bytes32) {\n        return block.chainid == _initialChainId ? _initialDomainSeparator : _computeDomainSeparator();\n    }\n\n    /*///////////////////////////////////////////////////////////////\n                    Override Upgrade Permission\n    //////////////////////////////////////////////////////////////*/\n\n    /**\n     * @dev Upgradable by the owner.\n     *\n     */\n    function _authorizeUpgrade(\n        address /*newImplementation*/\n    )\n        internal\n        virtual\n        override\n    {\n        _assertOwner();\n    }\n}\n","deployed_bytecode":"0x6080604052600436106101d0575f3560e01c806379ba5097116100fd578063bf7e214f11610092578063dc2c256f11610062578063dc2c256f14610563578063dd62ed3e14610582578063e30c3978146105b8578063f2fde38b146105e4575f80fd5b8063bf7e214f146104d3578063c5c0db6214610506578063c820f14614610525578063d505accf14610544575f80fd5b806395d89b41116100cd57806395d89b41146104625780639dc29fac14610476578063a327039a14610495578063a9059cbb146104b4575f80fd5b806379ba5097146103a75780637ecebe00146103bb5780638a6db9c3146103e65780638da5cb5b14610411575f80fd5b80633659cfe61161017357806352d1902d1161014357806352d1902d1461033557806370a0823114610349578063715018a614610374578063782ec77914610388575f80fd5b80633659cfe6146102c557806340c10f19146102e457806342966c68146103035780634f1ef28614610322575f80fd5b80631dd319cb116101ae5780631dd319cb1461025057806323b872dd14610271578063313ce567146102905780633644e515146102b1575f80fd5b806306fdde03146101d4578063095ea7b3146101fe57806318160ddd1461022d575b5f80fd5b3480156101df575f80fd5b506101e8610603565b6040516101f59190612799565b60405180910390f35b348015610209575f80fd5b5061021d610218366004612814565b61068e565b60405190151581526020016101f5565b348015610238575f80fd5b5061024260025481565b6040519081526020016101f5565b34801561025b575f80fd5b5061026f61026a366004612814565b610707565b005b34801561027c575f80fd5b5061021d61028b36600461283c565b610715565b34801561029b575f80fd5b5060735460405160ff90911681526020016101f5565b3480156102bc575f80fd5b506102426107f7565b3480156102d0575f80fd5b5061026f6102df366004612876565b610833565b3480156102ef575f80fd5b5061021d6102fe366004612814565b610a3c565b34801561030e575f80fd5b5061026f61031d36600461288f565b610aaa565b61026f610330366004612968565b610abd565b348015610340575f80fd5b50610242610caf565b348015610354575f80fd5b50610242610363366004612876565b60036020525f908152604090205481565b34801561037f575f80fd5b5061026f610d9a565b348015610393575f80fd5b5061026f6103a2366004612814565b610dad565b3480156103b2575f80fd5b5061026f610df8565b3480156103c6575f80fd5b506102426103d5366004612876565b60056020525f908152604090205481565b3480156103f1575f80fd5b50610242610400366004612876565b60726020525f908152604090205481565b34801561041c575f80fd5b5060395461043d9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101f5565b34801561046d575f80fd5b506101e8610e6b565b348015610481575f80fd5b5061026f610490366004612814565b610e78565b3480156104a0575f80fd5b5061026f6104af366004612814565b610ed3565b3480156104bf575f80fd5b5061021d6104ce366004612814565b610f0b565b3480156104de575f80fd5b5061043d7f000000000000000000000000902d906b8d988092213be799b18bd2cbd64f808c81565b348015610511575f80fd5b5061026f610520366004612814565b610f29565b348015610530575f80fd5b5061026f61053f3660046129f4565b610ff6565b34801561054f575f80fd5b5061026f61055e366004612a89565b61129a565b34801561056e575f80fd5b5061026f61057d366004612aef565b6115b3565b34801561058d575f80fd5b5061024261059c366004612b28565b600460209081525f928352604080842090915290825290205481565b3480156105c3575f80fd5b50603a5461043d9073ffffffffffffffffffffffffffffffffffffffff1681565b3480156105ef575f80fd5b5061026f6105fe366004612876565b611704565b5f805461060f90612b59565b80601f016020809104026020016040519081016040528092919081815260200182805461063b90612b59565b80156106865780601f1061065d57610100808354040283529160200191610686565b820191905f5260205f20905b81548152906001019060200180831161066957829003601f168201915b505050505081565b335f81815260046020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906106f59086815260200190565b60405180910390a35060015b92915050565b6107118282610e78565b5050565b5f61071e6117cf565b156107ce5773ffffffffffffffffffffffffffffffffffffffff84165f9081526003602052604081208054849290610757908490612bd7565b909155505073ffffffffffffffffffffffffffffffffffffffff8084165f81815260036020526040908190208054860190555190918616907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906107be9086815260200190565b60405180910390a35060016107f0565b6107d733611884565b6107e23085856118b2565b6107ed8484846118de565b90505b9392505050565b5f7f0000000000000000000000000000000000000000000000000000000000000001461461082c57610827611a1e565b905090565b5060745490565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000bf0f2f3aad6b99893d80c550fbacec915545eb921630036108fd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f64656c656761746563616c6c000000000000000000000000000000000000000060648201526084015b60405180910390fd5b7f000000000000000000000000bf0f2f3aad6b99893d80c550fbacec915545eb9273ffffffffffffffffffffffffffffffffffffffff166109727f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff1614610a15576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f6163746976652070726f7879000000000000000000000000000000000000000060648201526084016108f4565b610a1e81611ab6565b604080515f80825260208201909252610a3991839190611abe565b50565b335f908152607260205260408120547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610a8c57610a7c8382612bd7565b335f908152607260205260409020555b610a963085611cbd565b610aa08484611ce8565b5060019392505050565b610ab333611884565b610a393382611d5f565b73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000bf0f2f3aad6b99893d80c550fbacec915545eb92163003610b82576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f64656c656761746563616c6c000000000000000000000000000000000000000060648201526084016108f4565b7f000000000000000000000000bf0f2f3aad6b99893d80c550fbacec915545eb9273ffffffffffffffffffffffffffffffffffffffff16610bf77f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff1614610c9a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f6163746976652070726f7879000000000000000000000000000000000000000060648201526084016108f4565b610ca382611ab6565b61071182826001611abe565b5f3073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000bf0f2f3aad6b99893d80c550fbacec915545eb921614610d75576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c000000000000000060648201526084016108f4565b507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc90565b610da2611deb565b610dab5f611e3c565b565b73ffffffffffffffffffffffffffffffffffffffff82165f9081526072602052604081205490828211610de05781610de2565b825b9050610df2846105208385612bd7565b50505050565b603a5473ffffffffffffffffffffffffffffffffffffffff163314610e49576040517f2c1a75e200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b603a54610dab9073ffffffffffffffffffffffffffffffffffffffff16611e3c565b6001805461060f90612b59565b335f908152607260205260408120549003610ebf576040517f2c1a75e200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610ec93083611cbd565b6107118282611d5f565b73ffffffffffffffffffffffffffffffffffffffff82165f90815260726020526040902054610f06836105208484612bea565b505050565b5f610f1533611884565b610f1f3084611cbd565b6107f08383611ef1565b610f3233611884565b73ffffffffffffffffffffffffffffffffffffffff8216610f7f576040517f32691b5700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805173ffffffffffffffffffffffffffffffffffffffff84168152602081018390527f46980fca912ef9bcdbd36877427b6b90e860769f604e89c0e67720cece530d20910160405180910390a173ffffffffffffffffffffffffffffffffffffffff9091165f90815260726020526040902055565b600654610100900460ff16158080156110165750600654600160ff909116105b806110305750303b158015611030575060065460ff166001145b6110bc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016108f4565b600680547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561111a57600680547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b73ffffffffffffffffffffffffffffffffffffffff8316611167576040517f32691b5700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff82166111b4576040517f32691b5700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6111bd83611e3c565b5f6111c88782612c48565b5060016111d58682612c48565b5060ff841660735573ffffffffffffffffffffffffffffffffffffffff82165f9081526072602052604090207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff905561122c611a1e565b607455801561129257600680547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050565b42841015611304576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f5045524d49545f444541444c494e455f4558504952454400000000000000000060448201526064016108f4565b5f600161130f6107f7565b73ffffffffffffffffffffffffffffffffffffffff8a81165f8181526005602090815260409182902080546001810190915582517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98184015280840194909452938d166060840152608083018c905260a083019390935260c08083018b90528151808403909101815260e0830190915280519201919091207f190100000000000000000000000000000000000000000000000000000000000061010083015261010282019290925261012281019190915261014201604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201205f84529083018083525260ff871690820152606081018590526080810184905260a0016020604051602081039080840390855afa15801561145d573d5f803e3d5ffd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff8116158015906114d857508773ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16145b61153e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f494e56414c49445f5349474e455200000000000000000000000000000000000060448201526064016108f4565b73ffffffffffffffffffffffffffffffffffffffff9081165f9081526004602090815260408083208a8516808552908352928190208990555188815291928a16917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a350505050505050565b6115bb611f74565b6040517fea7ca27600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8281166004830152600760248301527f000000000000000000000000902d906b8d988092213be799b18bd2cbd64f808c169063ea7ca27690604401602060405180830381865afa15801561164c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906116709190612d5f565b6116a6576040517f7f63bd0f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805173ffffffffffffffffffffffffffffffffffffffff8581168252602082018590528316917fed679328aebf74ede77ae09efcf36e90244f83643dadac1c2d9f0b21a46f6ab7910160405180910390a2610f06838284611fb2565b61170c611deb565b73ffffffffffffffffffffffffffffffffffffffff8116611759576040517f32691b5700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b603a80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116918217909255603954604051919216907f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e22700905f90a350565b6040517fea7ca27600000000000000000000000000000000000000000000000000000000815233600482015260ff60248201525f907f000000000000000000000000902d906b8d988092213be799b18bd2cbd64f808c73ffffffffffffffffffffffffffffffffffffffff169063ea7ca27690604401602060405180830381865afa158015611860573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108279190612d5f565b610a3981305f357fffffffff000000000000000000000000000000000000000000000000000000001661203f565b610f068282857fa9059cbb2ab09eb219583f4a59a5d0623ade346d962bcd4e46b11da047c9049b612153565b73ffffffffffffffffffffffffffffffffffffffff83165f9081526004602090815260408083203384529091528120547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81146119705761193f8382612bd7565b73ffffffffffffffffffffffffffffffffffffffff86165f9081526004602090815260408083203384529091529020555b73ffffffffffffffffffffffffffffffffffffffff85165f90815260036020526040812080548592906119a4908490612bd7565b909155505073ffffffffffffffffffffffffffffffffffffffff8085165f81815260036020526040908190208054870190555190918716907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90611a0b9087815260200190565b60405180910390a3506001949350505050565b5f7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f5f604051611a4e9190612d7e565b6040805191829003822060208301939093528101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160405160208183030381529060405280519060200120905090565b610a39611deb565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff1615611af157610f068361226f565b8273ffffffffffffffffffffffffffffffffffffffff166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015611b76575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201909252611b7391810190612e0d565b60015b611c02576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201527f6f6e206973206e6f74205555505300000000000000000000000000000000000060648201526084016108f4565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8114611cb1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f7860448201527f6961626c6555554944000000000000000000000000000000000000000000000060648201526084016108f4565b50610f06838383612379565b61071181837fa9059cbb2ab09eb219583f4a59a5d0623ade346d962bcd4e46b11da047c9049b61203f565b8060025f828254611cf99190612bea565b909155505073ffffffffffffffffffffffffffffffffffffffff82165f818152600360209081526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91015b60405180910390a35050565b73ffffffffffffffffffffffffffffffffffffffff82165f9081526003602052604081208054839290611d93908490612bd7565b90915550506002805482900390556040518181525f9073ffffffffffffffffffffffffffffffffffffffff8416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001611d53565b60395473ffffffffffffffffffffffffffffffffffffffff163314610dab576040517f2c1a75e200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b603a80547fffffffffffffffffffffffff000000000000000000000000000000000000000016905560395460405173ffffffffffffffffffffffffffffffffffffffff8381169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a3603980547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b335f90815260036020526040812080548391908390611f11908490612bd7565b909155505073ffffffffffffffffffffffffffffffffffffffff83165f81815260036020526040908190208054850190555133907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906106f59086815260200190565b611f7c6117cf565b610dab576040517f7f63bd0f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052610f0690849061239d565b6040517fb700961300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff848116600483015283811660248301527fffffffff00000000000000000000000000000000000000000000000000000000831660448301527f000000000000000000000000902d906b8d988092213be799b18bd2cbd64f808c169063b700961390606401602060405180830381865afa1580156120f9573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061211d9190612d5f565b610f06576040517f7f63bd0f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517fdf595cb800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152848116602483015283811660448301527fffffffff00000000000000000000000000000000000000000000000000000000831660648301527f000000000000000000000000902d906b8d988092213be799b18bd2cbd64f808c169063df595cb890608401602060405180830381865afa158015612215573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906122399190612d5f565b610df2576040517f7f63bd0f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff81163b612313576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201527f6f74206120636f6e74726163740000000000000000000000000000000000000060648201526084016108f4565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b612382836124a8565b5f8251118061238e5750805b15610f0657610df283836124f4565b5f6123fe826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166125199092919063ffffffff16565b805190915015610f06578080602001905181019061241c9190612d5f565b610f06576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016108f4565b6124b18161226f565b60405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a250565b60606107f08383604051806060016040528060278152602001612e3b60279139612527565b60606107ed84845f856125a8565b60605f808573ffffffffffffffffffffffffffffffffffffffff16856040516125509190612e24565b5f60405180830381855af49150503d805f8114612588576040519150601f19603f3d011682016040523d82523d5f602084013e61258d565b606091505b509150915061259e868383876126bf565b9695505050505050565b60608247101561263a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016108f4565b5f808673ffffffffffffffffffffffffffffffffffffffff1685876040516126629190612e24565b5f6040518083038185875af1925050503d805f811461269c576040519150601f19603f3d011682016040523d82523d5f602084013e6126a1565b606091505b50915091506126b2878383876126bf565b925050505b949350505050565b606083156127545782515f0361274d5773ffffffffffffffffffffffffffffffffffffffff85163b61274d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016108f4565b50816126b7565b6126b783838151156127695781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108f491905b602081525f82518060208401528060208501604085015e5f6040828501015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011684010191505092915050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461280f575f80fd5b919050565b5f8060408385031215612825575f80fd5b61282e836127ec565b946020939093013593505050565b5f805f6060848603121561284e575f80fd5b612857846127ec565b9250612865602085016127ec565b929592945050506040919091013590565b5f60208284031215612886575f80fd5b6107f0826127ec565b5f6020828403121561289f575f80fd5b5035919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f8067ffffffffffffffff8411156128ed576128ed6128a6565b506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f85018116603f0116810181811067ffffffffffffffff8211171561293a5761293a6128a6565b604052838152905080828401851015612951575f80fd5b838360208301375f60208583010152509392505050565b5f8060408385031215612979575f80fd5b612982836127ec565b9150602083013567ffffffffffffffff81111561299d575f80fd5b8301601f810185136129ad575f80fd5b6129bc858235602084016128d3565b9150509250929050565b5f82601f8301126129d5575f80fd5b6107f0838335602085016128d3565b803560ff8116811461280f575f80fd5b5f805f805f60a08688031215612a08575f80fd5b853567ffffffffffffffff811115612a1e575f80fd5b612a2a888289016129c6565b955050602086013567ffffffffffffffff811115612a46575f80fd5b612a52888289016129c6565b945050612a61604087016129e4565b9250612a6f606087016127ec565b9150612a7d608087016127ec565b90509295509295909350565b5f805f805f805f60e0888a031215612a9f575f80fd5b612aa8886127ec565b9650612ab6602089016127ec565b95506040880135945060608801359350612ad2608089016129e4565b9699959850939692959460a0840135945060c09093013592915050565b5f805f60608486031215612b01575f80fd5b612b0a846127ec565b925060208401359150612b1f604085016127ec565b90509250925092565b5f8060408385031215612b39575f80fd5b612b42836127ec565b9150612b50602084016127ec565b90509250929050565b600181811c90821680612b6d57607f821691505b602082108103612ba4577f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b50919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b8181038181111561070157610701612baa565b8082018082111561070157610701612baa565b601f821115610f0657805f5260205f20601f840160051c81016020851015612c225750805b601f840160051c820191505b81811015612c41575f8155600101612c2e565b5050505050565b815167ffffffffffffffff811115612c6257612c626128a6565b612c7681612c708454612b59565b84612bfd565b6020601f821160018114612cc7575f8315612c915750848201515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600385901b1c1916600184901b178455612c41565b5f848152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08516915b82811015612d145787850151825560209485019460019092019101612cf4565b5084821015612d5057868401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b60f8161c191681555b50505050600190811b01905550565b5f60208284031215612d6f575f80fd5b815180151581146107f0575f80fd5b5f808354612d8b81612b59565b600182168015612da25760018114612dd557612e02565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0083168652811515820286019350612e02565b865f5260205f205f5b83811015612dfa57815488820152600190910190602001612dde565b505081860193505b509195945050505050565b5f60208284031215612e1d575f80fd5b5051919050565b5f82518060208501845e5f92019182525091905056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a264697066735822122087c7296345f6aa55b07f6d8800b45cb98435591098a66aac2f72b5b0bdf5cba564736f6c634300081a0033","optimization_enabled":true,"verified_twin_address_hash":null,"is_verified":true,"compiler_settings":{"evmVersion":"cancun","libraries":{},"metadata":{"bytecodeHash":"ipfs"},"optimizer":{"enabled":true,"runs":100000},"remappings":[":BokkyPooBahsDateTimeLibrary/=lib/BokkyPooBahsDateTimeLibrary/",":bpb-dateTime/=lib/BokkyPooBahsDateTimeLibrary/contracts/",":ds-test/=lib/solmate/lib/ds-test/src/",":forge-std/=lib/forge-std/src/",":openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/",":openzeppelin-contracts/=lib/openzeppelin-contracts/",":openzeppelin-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/",":openzeppelin/=lib/openzeppelin-contracts/contracts/",":solmate/=lib/solmate/src/"]},"optimization_runs":100000,"sourcify_repo_url":"https://repo.sourcify.dev/contracts/full_match/1/0xBF0f2F3aad6b99893D80c550fbAcEc915545eb92/","decoded_constructor_args":[["0x902D906b8d988092213bE799B18Bd2cbd64F808C",{"internalType":"address","name":"_authority","type":"address"}]],"compiler_version":"0.8.26+commit.8a97fa7a","is_verified_via_verifier_alliance":false,"verified_at":"2025-11-20T22:48:00.942301Z","implementations":[],"proxy_type":null,"external_libraries":[],"creation_bytecode":"0x60e06040523060a052348015610013575f80fd5b5060405161305e38038061305e83398101604081905261003291610138565b806001600160a01b03811661005a576040516332691b5760e01b815260040160405180910390fd5b6001600160a01b03166080524660c052610072610078565b50610165565b600654610100900460ff16156100e45760405162461bcd60e51b815260206004820152602760248201527f496e697469616c697a61626c653a20636f6e747261637420697320696e697469604482015266616c697a696e6760c81b606482015260840160405180910390fd5b60065460ff9081161015610136576006805460ff191660ff9081179091556040519081527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b565b5f60208284031215610148575f80fd5b81516001600160a01b038116811461015e575f80fd5b9392505050565b60805160a05160c051612e976101c75f395f6107fa01525f818161084a015281816108ff01528181610ad401528181610b840152610cc801525f81816104e40152818161160701528181611806015281816120b401526121d00152612e975ff3fe6080604052600436106101d0575f3560e01c806379ba5097116100fd578063bf7e214f11610092578063dc2c256f11610062578063dc2c256f14610563578063dd62ed3e14610582578063e30c3978146105b8578063f2fde38b146105e4575f80fd5b8063bf7e214f146104d3578063c5c0db6214610506578063c820f14614610525578063d505accf14610544575f80fd5b806395d89b41116100cd57806395d89b41146104625780639dc29fac14610476578063a327039a14610495578063a9059cbb146104b4575f80fd5b806379ba5097146103a75780637ecebe00146103bb5780638a6db9c3146103e65780638da5cb5b14610411575f80fd5b80633659cfe61161017357806352d1902d1161014357806352d1902d1461033557806370a0823114610349578063715018a614610374578063782ec77914610388575f80fd5b80633659cfe6146102c557806340c10f19146102e457806342966c68146103035780634f1ef28614610322575f80fd5b80631dd319cb116101ae5780631dd319cb1461025057806323b872dd14610271578063313ce567146102905780633644e515146102b1575f80fd5b806306fdde03146101d4578063095ea7b3146101fe57806318160ddd1461022d575b5f80fd5b3480156101df575f80fd5b506101e8610603565b6040516101f59190612799565b60405180910390f35b348015610209575f80fd5b5061021d610218366004612814565b61068e565b60405190151581526020016101f5565b348015610238575f80fd5b5061024260025481565b6040519081526020016101f5565b34801561025b575f80fd5b5061026f61026a366004612814565b610707565b005b34801561027c575f80fd5b5061021d61028b36600461283c565b610715565b34801561029b575f80fd5b5060735460405160ff90911681526020016101f5565b3480156102bc575f80fd5b506102426107f7565b3480156102d0575f80fd5b5061026f6102df366004612876565b610833565b3480156102ef575f80fd5b5061021d6102fe366004612814565b610a3c565b34801561030e575f80fd5b5061026f61031d36600461288f565b610aaa565b61026f610330366004612968565b610abd565b348015610340575f80fd5b50610242610caf565b348015610354575f80fd5b50610242610363366004612876565b60036020525f908152604090205481565b34801561037f575f80fd5b5061026f610d9a565b348015610393575f80fd5b5061026f6103a2366004612814565b610dad565b3480156103b2575f80fd5b5061026f610df8565b3480156103c6575f80fd5b506102426103d5366004612876565b60056020525f908152604090205481565b3480156103f1575f80fd5b50610242610400366004612876565b60726020525f908152604090205481565b34801561041c575f80fd5b5060395461043d9073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020016101f5565b34801561046d575f80fd5b506101e8610e6b565b348015610481575f80fd5b5061026f610490366004612814565b610e78565b3480156104a0575f80fd5b5061026f6104af366004612814565b610ed3565b3480156104bf575f80fd5b5061021d6104ce366004612814565b610f0b565b3480156104de575f80fd5b5061043d7f000000000000000000000000000000000000000000000000000000000000000081565b348015610511575f80fd5b5061026f610520366004612814565b610f29565b348015610530575f80fd5b5061026f61053f3660046129f4565b610ff6565b34801561054f575f80fd5b5061026f61055e366004612a89565b61129a565b34801561056e575f80fd5b5061026f61057d366004612aef565b6115b3565b34801561058d575f80fd5b5061024261059c366004612b28565b600460209081525f928352604080842090915290825290205481565b3480156105c3575f80fd5b50603a5461043d9073ffffffffffffffffffffffffffffffffffffffff1681565b3480156105ef575f80fd5b5061026f6105fe366004612876565b611704565b5f805461060f90612b59565b80601f016020809104026020016040519081016040528092919081815260200182805461063b90612b59565b80156106865780601f1061065d57610100808354040283529160200191610686565b820191905f5260205f20905b81548152906001019060200180831161066957829003601f168201915b505050505081565b335f81815260046020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925906106f59086815260200190565b60405180910390a35060015b92915050565b6107118282610e78565b5050565b5f61071e6117cf565b156107ce5773ffffffffffffffffffffffffffffffffffffffff84165f9081526003602052604081208054849290610757908490612bd7565b909155505073ffffffffffffffffffffffffffffffffffffffff8084165f81815260036020526040908190208054860190555190918616907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906107be9086815260200190565b60405180910390a35060016107f0565b6107d733611884565b6107e23085856118b2565b6107ed8484846118de565b90505b9392505050565b5f7f0000000000000000000000000000000000000000000000000000000000000000461461082c57610827611a1e565b905090565b5060745490565b73ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001630036108fd576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f64656c656761746563616c6c000000000000000000000000000000000000000060648201526084015b60405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166109727f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff1614610a15576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f6163746976652070726f7879000000000000000000000000000000000000000060648201526084016108f4565b610a1e81611ab6565b604080515f80825260208201909252610a3991839190611abe565b50565b335f908152607260205260408120547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610a8c57610a7c8382612bd7565b335f908152607260205260409020555b610a963085611cbd565b610aa08484611ce8565b5060019392505050565b610ab333611884565b610a393382611d5f565b73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000163003610b82576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f64656c656761746563616c6c000000000000000000000000000000000000000060648201526084016108f4565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16610bf77f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff1614610c9a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602c60248201527f46756e6374696f6e206d7573742062652063616c6c6564207468726f7567682060448201527f6163746976652070726f7879000000000000000000000000000000000000000060648201526084016108f4565b610ca382611ab6565b61071182826001611abe565b5f3073ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001614610d75576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f555550535570677261646561626c653a206d757374206e6f742062652063616c60448201527f6c6564207468726f7567682064656c656761746563616c6c000000000000000060648201526084016108f4565b507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc90565b610da2611deb565b610dab5f611e3c565b565b73ffffffffffffffffffffffffffffffffffffffff82165f9081526072602052604081205490828211610de05781610de2565b825b9050610df2846105208385612bd7565b50505050565b603a5473ffffffffffffffffffffffffffffffffffffffff163314610e49576040517f2c1a75e200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b603a54610dab9073ffffffffffffffffffffffffffffffffffffffff16611e3c565b6001805461060f90612b59565b335f908152607260205260408120549003610ebf576040517f2c1a75e200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610ec93083611cbd565b6107118282611d5f565b73ffffffffffffffffffffffffffffffffffffffff82165f90815260726020526040902054610f06836105208484612bea565b505050565b5f610f1533611884565b610f1f3084611cbd565b6107f08383611ef1565b610f3233611884565b73ffffffffffffffffffffffffffffffffffffffff8216610f7f576040517f32691b5700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805173ffffffffffffffffffffffffffffffffffffffff84168152602081018390527f46980fca912ef9bcdbd36877427b6b90e860769f604e89c0e67720cece530d20910160405180910390a173ffffffffffffffffffffffffffffffffffffffff9091165f90815260726020526040902055565b600654610100900460ff16158080156110165750600654600160ff909116105b806110305750303b158015611030575060065460ff166001145b6110bc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201527f647920696e697469616c697a656400000000000000000000000000000000000060648201526084016108f4565b600680547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055801561111a57600680547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff166101001790555b73ffffffffffffffffffffffffffffffffffffffff8316611167576040517f32691b5700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff82166111b4576040517f32691b5700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6111bd83611e3c565b5f6111c88782612c48565b5060016111d58682612c48565b5060ff841660735573ffffffffffffffffffffffffffffffffffffffff82165f9081526072602052604090207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff905561122c611a1e565b607455801561129257600680547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ff169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a15b505050505050565b42841015611304576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601760248201527f5045524d49545f444541444c494e455f4558504952454400000000000000000060448201526064016108f4565b5f600161130f6107f7565b73ffffffffffffffffffffffffffffffffffffffff8a81165f8181526005602090815260409182902080546001810190915582517f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98184015280840194909452938d166060840152608083018c905260a083019390935260c08083018b90528151808403909101815260e0830190915280519201919091207f190100000000000000000000000000000000000000000000000000000000000061010083015261010282019290925261012281019190915261014201604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe081840301815282825280516020918201205f84529083018083525260ff871690820152606081018590526080810184905260a0016020604051602081039080840390855afa15801561145d573d5f803e3d5ffd5b50506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0015191505073ffffffffffffffffffffffffffffffffffffffff8116158015906114d857508773ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16145b61153e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600e60248201527f494e56414c49445f5349474e455200000000000000000000000000000000000060448201526064016108f4565b73ffffffffffffffffffffffffffffffffffffffff9081165f9081526004602090815260408083208a8516808552908352928190208990555188815291928a16917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a350505050505050565b6115bb611f74565b6040517fea7ca27600000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8281166004830152600760248301527f0000000000000000000000000000000000000000000000000000000000000000169063ea7ca27690604401602060405180830381865afa15801561164c573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906116709190612d5f565b6116a6576040517f7f63bd0f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805173ffffffffffffffffffffffffffffffffffffffff8581168252602082018590528316917fed679328aebf74ede77ae09efcf36e90244f83643dadac1c2d9f0b21a46f6ab7910160405180910390a2610f06838284611fb2565b61170c611deb565b73ffffffffffffffffffffffffffffffffffffffff8116611759576040517f32691b5700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b603a80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff838116918217909255603954604051919216907f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e22700905f90a350565b6040517fea7ca27600000000000000000000000000000000000000000000000000000000815233600482015260ff60248201525f907f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff169063ea7ca27690604401602060405180830381865afa158015611860573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906108279190612d5f565b610a3981305f357fffffffff000000000000000000000000000000000000000000000000000000001661203f565b610f068282857fa9059cbb2ab09eb219583f4a59a5d0623ade346d962bcd4e46b11da047c9049b612153565b73ffffffffffffffffffffffffffffffffffffffff83165f9081526004602090815260408083203384529091528120547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81146119705761193f8382612bd7565b73ffffffffffffffffffffffffffffffffffffffff86165f9081526004602090815260408083203384529091529020555b73ffffffffffffffffffffffffffffffffffffffff85165f90815260036020526040812080548592906119a4908490612bd7565b909155505073ffffffffffffffffffffffffffffffffffffffff8085165f81815260036020526040908190208054870190555190918716907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90611a0b9087815260200190565b60405180910390a3506001949350505050565b5f7f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f5f604051611a4e9190612d7e565b6040805191829003822060208301939093528101919091527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608201524660808201523060a082015260c00160405160208183030381529060405280519060200120905090565b610a39611deb565b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd91435460ff1615611af157610f068361226f565b8273ffffffffffffffffffffffffffffffffffffffff166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015611b76575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168201909252611b7391810190612e0d565b60015b611c02576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f45524331393637557067726164653a206e657720696d706c656d656e7461746960448201527f6f6e206973206e6f74205555505300000000000000000000000000000000000060648201526084016108f4565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8114611cb1576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f45524331393637557067726164653a20756e737570706f727465642070726f7860448201527f6961626c6555554944000000000000000000000000000000000000000000000060648201526084016108f4565b50610f06838383612379565b61071181837fa9059cbb2ab09eb219583f4a59a5d0623ade346d962bcd4e46b11da047c9049b61203f565b8060025f828254611cf99190612bea565b909155505073ffffffffffffffffffffffffffffffffffffffff82165f818152600360209081526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91015b60405180910390a35050565b73ffffffffffffffffffffffffffffffffffffffff82165f9081526003602052604081208054839290611d93908490612bd7565b90915550506002805482900390556040518181525f9073ffffffffffffffffffffffffffffffffffffffff8416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001611d53565b60395473ffffffffffffffffffffffffffffffffffffffff163314610dab576040517f2c1a75e200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b603a80547fffffffffffffffffffffffff000000000000000000000000000000000000000016905560395460405173ffffffffffffffffffffffffffffffffffffffff8381169216907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a3603980547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b335f90815260036020526040812080548391908390611f11908490612bd7565b909155505073ffffffffffffffffffffffffffffffffffffffff83165f81815260036020526040908190208054850190555133907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906106f59086815260200190565b611f7c6117cf565b610dab576040517f7f63bd0f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040805173ffffffffffffffffffffffffffffffffffffffff8416602482015260448082018490528251808303909101815260649091019091526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fa9059cbb00000000000000000000000000000000000000000000000000000000179052610f0690849061239d565b6040517fb700961300000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff848116600483015283811660248301527fffffffff00000000000000000000000000000000000000000000000000000000831660448301527f0000000000000000000000000000000000000000000000000000000000000000169063b700961390606401602060405180830381865afa1580156120f9573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061211d9190612d5f565b610f06576040517f7f63bd0f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6040517fdf595cb800000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff8581166004830152848116602483015283811660448301527fffffffff00000000000000000000000000000000000000000000000000000000831660648301527f0000000000000000000000000000000000000000000000000000000000000000169063df595cb890608401602060405180830381865afa158015612215573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906122399190612d5f565b610df2576040517f7f63bd0f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff81163b612313576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201527f6f74206120636f6e74726163740000000000000000000000000000000000000060648201526084016108f4565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b612382836124a8565b5f8251118061238e5750805b15610f0657610df283836124f4565b5f6123fe826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff166125199092919063ffffffff16565b805190915015610f06578080602001905181019061241c9190612d5f565b610f06576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602a60248201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60448201527f6f7420737563636565640000000000000000000000000000000000000000000060648201526084016108f4565b6124b18161226f565b60405173ffffffffffffffffffffffffffffffffffffffff8216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b905f90a250565b60606107f08383604051806060016040528060278152602001612e3b60279139612527565b60606107ed84845f856125a8565b60605f808573ffffffffffffffffffffffffffffffffffffffff16856040516125509190612e24565b5f60405180830381855af49150503d805f8114612588576040519150601f19603f3d011682016040523d82523d5f602084013e61258d565b606091505b509150915061259e868383876126bf565b9695505050505050565b60608247101561263a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60448201527f722063616c6c000000000000000000000000000000000000000000000000000060648201526084016108f4565b5f808673ffffffffffffffffffffffffffffffffffffffff1685876040516126629190612e24565b5f6040518083038185875af1925050503d805f811461269c576040519150601f19603f3d011682016040523d82523d5f602084013e6126a1565b606091505b50915091506126b2878383876126bf565b925050505b949350505050565b606083156127545782515f0361274d5773ffffffffffffffffffffffffffffffffffffffff85163b61274d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000060448201526064016108f4565b50816126b7565b6126b783838151156127695781518083602001fd5b806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016108f491905b602081525f82518060208401528060208501604085015e5f6040828501015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f83011684010191505092915050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461280f575f80fd5b919050565b5f8060408385031215612825575f80fd5b61282e836127ec565b946020939093013593505050565b5f805f6060848603121561284e575f80fd5b612857846127ec565b9250612865602085016127ec565b929592945050506040919091013590565b5f60208284031215612886575f80fd5b6107f0826127ec565b5f6020828403121561289f575f80fd5b5035919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b5f8067ffffffffffffffff8411156128ed576128ed6128a6565b506040517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f85018116603f0116810181811067ffffffffffffffff8211171561293a5761293a6128a6565b604052838152905080828401851015612951575f80fd5b838360208301375f60208583010152509392505050565b5f8060408385031215612979575f80fd5b612982836127ec565b9150602083013567ffffffffffffffff81111561299d575f80fd5b8301601f810185136129ad575f80fd5b6129bc858235602084016128d3565b9150509250929050565b5f82601f8301126129d5575f80fd5b6107f0838335602085016128d3565b803560ff8116811461280f575f80fd5b5f805f805f60a08688031215612a08575f80fd5b853567ffffffffffffffff811115612a1e575f80fd5b612a2a888289016129c6565b955050602086013567ffffffffffffffff811115612a46575f80fd5b612a52888289016129c6565b945050612a61604087016129e4565b9250612a6f606087016127ec565b9150612a7d608087016127ec565b90509295509295909350565b5f805f805f805f60e0888a031215612a9f575f80fd5b612aa8886127ec565b9650612ab6602089016127ec565b95506040880135945060608801359350612ad2608089016129e4565b9699959850939692959460a0840135945060c09093013592915050565b5f805f60608486031215612b01575f80fd5b612b0a846127ec565b925060208401359150612b1f604085016127ec565b90509250925092565b5f8060408385031215612b39575f80fd5b612b42836127ec565b9150612b50602084016127ec565b90509250929050565b600181811c90821680612b6d57607f821691505b602082108103612ba4577f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b50919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b8181038181111561070157610701612baa565b8082018082111561070157610701612baa565b601f821115610f0657805f5260205f20601f840160051c81016020851015612c225750805b601f840160051c820191505b81811015612c41575f8155600101612c2e565b5050505050565b815167ffffffffffffffff811115612c6257612c626128a6565b612c7681612c708454612b59565b84612bfd565b6020601f821160018114612cc7575f8315612c915750848201515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600385901b1c1916600184901b178455612c41565b5f848152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08516915b82811015612d145787850151825560209485019460019092019101612cf4565b5084821015612d5057868401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b60f8161c191681555b50505050600190811b01905550565b5f60208284031215612d6f575f80fd5b815180151581146107f0575f80fd5b5f808354612d8b81612b59565b600182168015612da25760018114612dd557612e02565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0083168652811515820286019350612e02565b865f5260205f205f5b83811015612dfa57815488820152600190910190602001612dde565b505081860193505b509195945050505050565b5f60208284031215612e1d575f80fd5b5051919050565b5f82518060208501845e5f92019182525091905056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a264697066735822122087c7296345f6aa55b07f6d8800b45cb98435591098a66aac2f72b5b0bdf5cba564736f6c634300081a0033000000000000000000000000902d906b8d988092213be799b18bd2cbd64f808c","name":"YieldCoin","is_blueprint":false,"license_type":"none","is_fully_verified":true,"is_verified_via_eth_bytecode_db":true,"language":"solidity","evm_version":"cancun","can_be_visualized_via_sol2uml":true,"is_verified_via_sourcify":true,"additional_sources":[{"file_path":"lib/BokkyPooBahsDateTimeLibrary/contracts/BokkyPooBahsDateTimeLibrary.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity >=0.6.0 <0.9.0;\n\n// ----------------------------------------------------------------------------\n// BokkyPooBah's DateTime Library v1.01\n//\n// A gas-efficient Solidity date and time library\n//\n// https://github.com/bokkypoobah/BokkyPooBahsDateTimeLibrary\n//\n// Tested date range 1970/01/01 to 2345/12/31\n//\n// Conventions:\n// Unit      | Range         | Notes\n// :-------- |:-------------:|:-----\n// timestamp | >= 0          | Unix timestamp, number of seconds since 1970/01/01 00:00:00 UTC\n// year      | 1970 ... 2345 |\n// month     | 1 ... 12      |\n// day       | 1 ... 31      |\n// hour      | 0 ... 23      |\n// minute    | 0 ... 59      |\n// second    | 0 ... 59      |\n// dayOfWeek | 1 ... 7       | 1 = Monday, ..., 7 = Sunday\n//\n//\n// Enjoy. (c) BokkyPooBah / Bok Consulting Pty Ltd 2018-2019. The MIT Licence.\n// ----------------------------------------------------------------------------\n\nlibrary BokkyPooBahsDateTimeLibrary {\n\n    uint constant SECONDS_PER_DAY = 24 * 60 * 60;\n    uint constant SECONDS_PER_HOUR = 60 * 60;\n    uint constant SECONDS_PER_MINUTE = 60;\n    int constant OFFSET19700101 = 2440588;\n\n    uint constant DOW_MON = 1;\n    uint constant DOW_TUE = 2;\n    uint constant DOW_WED = 3;\n    uint constant DOW_THU = 4;\n    uint constant DOW_FRI = 5;\n    uint constant DOW_SAT = 6;\n    uint constant DOW_SUN = 7;\n\n    // ------------------------------------------------------------------------\n    // Calculate the number of days from 1970/01/01 to year/month/day using\n    // the date conversion algorithm from\n    //   https://aa.usno.navy.mil/faq/JD_formula.html\n    // and subtracting the offset 2440588 so that 1970/01/01 is day 0\n    //\n    // days = day\n    //      - 32075\n    //      + 1461 * (year + 4800 + (month - 14) / 12) / 4\n    //      + 367 * (month - 2 - (month - 14) / 12 * 12) / 12\n    //      - 3 * ((year + 4900 + (month - 14) / 12) / 100) / 4\n    //      - offset\n    // ------------------------------------------------------------------------\n    function _daysFromDate(uint year, uint month, uint day) internal pure returns (uint _days) {\n        require(year >= 1970);\n        int _year = int(year);\n        int _month = int(month);\n        int _day = int(day);\n\n        int __days = _day\n          - 32075\n          + 1461 * (_year + 4800 + (_month - 14) / 12) / 4\n          + 367 * (_month - 2 - (_month - 14) / 12 * 12) / 12\n          - 3 * ((_year + 4900 + (_month - 14) / 12) / 100) / 4\n          - OFFSET19700101;\n\n        _days = uint(__days);\n    }\n\n    // ------------------------------------------------------------------------\n    // Calculate year/month/day from the number of days since 1970/01/01 using\n    // the date conversion algorithm from\n    //   http://aa.usno.navy.mil/faq/docs/JD_Formula.php\n    // and adding the offset 2440588 so that 1970/01/01 is day 0\n    //\n    // int L = days + 68569 + offset\n    // int N = 4 * L / 146097\n    // L = L - (146097 * N + 3) / 4\n    // year = 4000 * (L + 1) / 1461001\n    // L = L - 1461 * year / 4 + 31\n    // month = 80 * L / 2447\n    // dd = L - 2447 * month / 80\n    // L = month / 11\n    // month = month + 2 - 12 * L\n    // year = 100 * (N - 49) + year + L\n    // ------------------------------------------------------------------------\n    function _daysToDate(uint _days) internal pure returns (uint year, uint month, uint day) {\n        int __days = int(_days);\n\n        int L = __days + 68569 + OFFSET19700101;\n        int N = 4 * L / 146097;\n        L = L - (146097 * N + 3) / 4;\n        int _year = 4000 * (L + 1) / 1461001;\n        L = L - 1461 * _year / 4 + 31;\n        int _month = 80 * L / 2447;\n        int _day = L - 2447 * _month / 80;\n        L = _month / 11;\n        _month = _month + 2 - 12 * L;\n        _year = 100 * (N - 49) + _year + L;\n\n        year = uint(_year);\n        month = uint(_month);\n        day = uint(_day);\n    }\n\n    function timestampFromDate(uint year, uint month, uint day) internal pure returns (uint timestamp) {\n        timestamp = _daysFromDate(year, month, day) * SECONDS_PER_DAY;\n    }\n    function timestampFromDateTime(uint year, uint month, uint day, uint hour, uint minute, uint second) internal pure returns (uint timestamp) {\n        timestamp = _daysFromDate(year, month, day) * SECONDS_PER_DAY + hour * SECONDS_PER_HOUR + minute * SECONDS_PER_MINUTE + second;\n    }\n    function timestampToDate(uint timestamp) internal pure returns (uint year, uint month, uint day) {\n        (year, month, day) = _daysToDate(timestamp / SECONDS_PER_DAY);\n    }\n    function timestampToDateTime(uint timestamp) internal pure returns (uint year, uint month, uint day, uint hour, uint minute, uint second) {\n        (year, month, day) = _daysToDate(timestamp / SECONDS_PER_DAY);\n        uint secs = timestamp % SECONDS_PER_DAY;\n        hour = secs / SECONDS_PER_HOUR;\n        secs = secs % SECONDS_PER_HOUR;\n        minute = secs / SECONDS_PER_MINUTE;\n        second = secs % SECONDS_PER_MINUTE;\n    }\n\n    function isValidDate(uint year, uint month, uint day) internal pure returns (bool valid) {\n        if (year >= 1970 && month > 0 && month <= 12) {\n            uint daysInMonth = _getDaysInMonth(year, month);\n            if (day > 0 && day <= daysInMonth) {\n                valid = true;\n            }\n        }\n    }\n    function isValidDateTime(uint year, uint month, uint day, uint hour, uint minute, uint second) internal pure returns (bool valid) {\n        if (isValidDate(year, month, day)) {\n            if (hour < 24 && minute < 60 && second < 60) {\n                valid = true;\n            }\n        }\n    }\n    function isLeapYear(uint timestamp) internal pure returns (bool leapYear) {\n        (uint year,,) = _daysToDate(timestamp / SECONDS_PER_DAY);\n        leapYear = _isLeapYear(year);\n    }\n    function _isLeapYear(uint year) internal pure returns (bool leapYear) {\n        leapYear = ((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0);\n    }\n    function isWeekDay(uint timestamp) internal pure returns (bool weekDay) {\n        weekDay = getDayOfWeek(timestamp) <= DOW_FRI;\n    }\n    function isWeekEnd(uint timestamp) internal pure returns (bool weekEnd) {\n        weekEnd = getDayOfWeek(timestamp) >= DOW_SAT;\n    }\n    function getDaysInMonth(uint timestamp) internal pure returns (uint daysInMonth) {\n        (uint year, uint month,) = _daysToDate(timestamp / SECONDS_PER_DAY);\n        daysInMonth = _getDaysInMonth(year, month);\n    }\n    function _getDaysInMonth(uint year, uint month) internal pure returns (uint daysInMonth) {\n        if (month == 1 || month == 3 || month == 5 || month == 7 || month == 8 || month == 10 || month == 12) {\n            daysInMonth = 31;\n        } else if (month != 2) {\n            daysInMonth = 30;\n        } else {\n            daysInMonth = _isLeapYear(year) ? 29 : 28;\n        }\n    }\n    // 1 = Monday, 7 = Sunday\n    function getDayOfWeek(uint timestamp) internal pure returns (uint dayOfWeek) {\n        uint _days = timestamp / SECONDS_PER_DAY;\n        dayOfWeek = (_days + 3) % 7 + 1;\n    }\n\n    function getYear(uint timestamp) internal pure returns (uint year) {\n        (year,,) = _daysToDate(timestamp / SECONDS_PER_DAY);\n    }\n    function getMonth(uint timestamp) internal pure returns (uint month) {\n        (,month,) = _daysToDate(timestamp / SECONDS_PER_DAY);\n    }\n    function getDay(uint timestamp) internal pure returns (uint day) {\n        (,,day) = _daysToDate(timestamp / SECONDS_PER_DAY);\n    }\n    function getHour(uint timestamp) internal pure returns (uint hour) {\n        uint secs = timestamp % SECONDS_PER_DAY;\n        hour = secs / SECONDS_PER_HOUR;\n    }\n    function getMinute(uint timestamp) internal pure returns (uint minute) {\n        uint secs = timestamp % SECONDS_PER_HOUR;\n        minute = secs / SECONDS_PER_MINUTE;\n    }\n    function getSecond(uint timestamp) internal pure returns (uint second) {\n        second = timestamp % SECONDS_PER_MINUTE;\n    }\n\n    function addYears(uint timestamp, uint _years) internal pure returns (uint newTimestamp) {\n        (uint year, uint month, uint day) = _daysToDate(timestamp / SECONDS_PER_DAY);\n        year += _years;\n        uint daysInMonth = _getDaysInMonth(year, month);\n        if (day > daysInMonth) {\n            day = daysInMonth;\n        }\n        newTimestamp = _daysFromDate(year, month, day) * SECONDS_PER_DAY + timestamp % SECONDS_PER_DAY;\n        require(newTimestamp >= timestamp);\n    }\n    function addMonths(uint timestamp, uint _months) internal pure returns (uint newTimestamp) {\n        (uint year, uint month, uint day) = _daysToDate(timestamp / SECONDS_PER_DAY);\n        month += _months;\n        year += (month - 1) / 12;\n        month = (month - 1) % 12 + 1;\n        uint daysInMonth = _getDaysInMonth(year, month);\n        if (day > daysInMonth) {\n            day = daysInMonth;\n        }\n        newTimestamp = _daysFromDate(year, month, day) * SECONDS_PER_DAY + timestamp % SECONDS_PER_DAY;\n        require(newTimestamp >= timestamp);\n    }\n    function addDays(uint timestamp, uint _days) internal pure returns (uint newTimestamp) {\n        newTimestamp = timestamp + _days * SECONDS_PER_DAY;\n        require(newTimestamp >= timestamp);\n    }\n    function addHours(uint timestamp, uint _hours) internal pure returns (uint newTimestamp) {\n        newTimestamp = timestamp + _hours * SECONDS_PER_HOUR;\n        require(newTimestamp >= timestamp);\n    }\n    function addMinutes(uint timestamp, uint _minutes) internal pure returns (uint newTimestamp) {\n        newTimestamp = timestamp + _minutes * SECONDS_PER_MINUTE;\n        require(newTimestamp >= timestamp);\n    }\n    function addSeconds(uint timestamp, uint _seconds) internal pure returns (uint newTimestamp) {\n        newTimestamp = timestamp + _seconds;\n        require(newTimestamp >= timestamp);\n    }\n\n    function subYears(uint timestamp, uint _years) internal pure returns (uint newTimestamp) {\n        (uint year, uint month, uint day) = _daysToDate(timestamp / SECONDS_PER_DAY);\n        year -= _years;\n        uint daysInMonth = _getDaysInMonth(year, month);\n        if (day > daysInMonth) {\n            day = daysInMonth;\n        }\n        newTimestamp = _daysFromDate(year, month, day) * SECONDS_PER_DAY + timestamp % SECONDS_PER_DAY;\n        require(newTimestamp <= timestamp);\n    }\n    function subMonths(uint timestamp, uint _months) internal pure returns (uint newTimestamp) {\n        (uint year, uint month, uint day) = _daysToDate(timestamp / SECONDS_PER_DAY);\n        uint yearMonth = year * 12 + (month - 1) - _months;\n        year = yearMonth / 12;\n        month = yearMonth % 12 + 1;\n        uint daysInMonth = _getDaysInMonth(year, month);\n        if (day > daysInMonth) {\n            day = daysInMonth;\n        }\n        newTimestamp = _daysFromDate(year, month, day) * SECONDS_PER_DAY + timestamp % SECONDS_PER_DAY;\n        require(newTimestamp <= timestamp);\n    }\n    function subDays(uint timestamp, uint _days) internal pure returns (uint newTimestamp) {\n        newTimestamp = timestamp - _days * SECONDS_PER_DAY;\n        require(newTimestamp <= timestamp);\n    }\n    function subHours(uint timestamp, uint _hours) internal pure returns (uint newTimestamp) {\n        newTimestamp = timestamp - _hours * SECONDS_PER_HOUR;\n        require(newTimestamp <= timestamp);\n    }\n    function subMinutes(uint timestamp, uint _minutes) internal pure returns (uint newTimestamp) {\n        newTimestamp = timestamp - _minutes * SECONDS_PER_MINUTE;\n        require(newTimestamp <= timestamp);\n    }\n    function subSeconds(uint timestamp, uint _seconds) internal pure returns (uint newTimestamp) {\n        newTimestamp = timestamp - _seconds;\n        require(newTimestamp <= timestamp);\n    }\n\n    function diffYears(uint fromTimestamp, uint toTimestamp) internal pure returns (uint _years) {\n        require(fromTimestamp <= toTimestamp);\n        (uint fromYear,,) = _daysToDate(fromTimestamp / SECONDS_PER_DAY);\n        (uint toYear,,) = _daysToDate(toTimestamp / SECONDS_PER_DAY);\n        _years = toYear - fromYear;\n    }\n    function diffMonths(uint fromTimestamp, uint toTimestamp) internal pure returns (uint _months) {\n        require(fromTimestamp <= toTimestamp);\n        (uint fromYear, uint fromMonth,) = _daysToDate(fromTimestamp / SECONDS_PER_DAY);\n        (uint toYear, uint toMonth,) = _daysToDate(toTimestamp / SECONDS_PER_DAY);\n        _months = toYear * 12 + toMonth - fromYear * 12 - fromMonth;\n    }\n    function diffDays(uint fromTimestamp, uint toTimestamp) internal pure returns (uint _days) {\n        require(fromTimestamp <= toTimestamp);\n        _days = (toTimestamp - fromTimestamp) / SECONDS_PER_DAY;\n    }\n    function diffHours(uint fromTimestamp, uint toTimestamp) internal pure returns (uint _hours) {\n        require(fromTimestamp <= toTimestamp);\n        _hours = (toTimestamp - fromTimestamp) / SECONDS_PER_HOUR;\n    }\n    function diffMinutes(uint fromTimestamp, uint toTimestamp) internal pure returns (uint _minutes) {\n        require(fromTimestamp <= toTimestamp);\n        _minutes = (toTimestamp - fromTimestamp) / SECONDS_PER_MINUTE;\n    }\n    function diffSeconds(uint fromTimestamp, uint toTimestamp) internal pure returns (uint _seconds) {\n        require(fromTimestamp <= toTimestamp);\n        _seconds = toTimestamp - fromTimestamp;\n    }\n}\n"},{"file_path":"lib/openzeppelin-contracts-upgradeable/contracts/proxy/utils/Initializable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.1) (proxy/utils/Initializable.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../../utils/AddressUpgradeable.sol\";\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * contract MyToken is ERC20Upgradeable {\n *     function initialize() initializer public {\n *         __ERC20_init(\"MyToken\", \"MTK\");\n *     }\n * }\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n *     function initializeV2() reinitializer(2) public {\n *         __ERC20Permit_init(\"MyToken\");\n *     }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n *     _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n    /**\n     * @dev Indicates that the contract has been initialized.\n     * @custom:oz-retyped-from bool\n     */\n    uint8 private _initialized;\n\n    /**\n     * @dev Indicates that the contract is in the process of being initialized.\n     */\n    bool private _initializing;\n\n    /**\n     * @dev Triggered when the contract has been initialized or reinitialized.\n     */\n    event Initialized(uint8 version);\n\n    /**\n     * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n     * `onlyInitializing` functions can be used to initialize parent contracts.\n     *\n     * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\n     * constructor.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier initializer() {\n        bool isTopLevelCall = !_initializing;\n        require(\n            (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),\n            \"Initializable: contract is already initialized\"\n        );\n        _initialized = 1;\n        if (isTopLevelCall) {\n            _initializing = true;\n        }\n        _;\n        if (isTopLevelCall) {\n            _initializing = false;\n            emit Initialized(1);\n        }\n    }\n\n    /**\n     * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n     * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n     * used to initialize parent contracts.\n     *\n     * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n     * are added through upgrades and that require initialization.\n     *\n     * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n     * cannot be nested. If one is invoked in the context of another, execution will revert.\n     *\n     * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n     * a contract, executing them in the right order is up to the developer or operator.\n     *\n     * WARNING: setting the version to 255 will prevent any future reinitialization.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier reinitializer(uint8 version) {\n        require(!_initializing && _initialized < version, \"Initializable: contract is already initialized\");\n        _initialized = version;\n        _initializing = true;\n        _;\n        _initializing = false;\n        emit Initialized(version);\n    }\n\n    /**\n     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n     * {initializer} and {reinitializer} modifiers, directly or indirectly.\n     */\n    modifier onlyInitializing() {\n        require(_initializing, \"Initializable: contract is not initializing\");\n        _;\n    }\n\n    /**\n     * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n     * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n     * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n     * through proxies.\n     *\n     * Emits an {Initialized} event the first time it is successfully executed.\n     */\n    function _disableInitializers() internal virtual {\n        require(!_initializing, \"Initializable: contract is initializing\");\n        if (_initialized < type(uint8).max) {\n            _initialized = type(uint8).max;\n            emit Initialized(type(uint8).max);\n        }\n    }\n\n    /**\n     * @dev Returns the highest version that has been initialized. See {reinitializer}.\n     */\n    function _getInitializedVersion() internal view returns (uint8) {\n        return _initialized;\n    }\n\n    /**\n     * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n     */\n    function _isInitializing() internal view returns (bool) {\n        return _initializing;\n    }\n}\n"},{"file_path":"lib/openzeppelin-contracts-upgradeable/contracts/utils/AddressUpgradeable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n    /**\n     * @dev Returns true if `account` is a contract.\n     *\n     * [IMPORTANT]\n     * ====\n     * It is unsafe to assume that an address for which this function returns\n     * false is an externally-owned account (EOA) and not a contract.\n     *\n     * Among others, `isContract` will return false for the following\n     * types of addresses:\n     *\n     *  - an externally-owned account\n     *  - a contract in construction\n     *  - an address where a contract will be created\n     *  - an address where a contract lived, but was destroyed\n     * ====\n     *\n     * [IMPORTANT]\n     * ====\n     * You shouldn't rely on `isContract` to protect against flash loan attacks!\n     *\n     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n     * constructor.\n     * ====\n     */\n    function isContract(address account) internal view returns (bool) {\n        // This method relies on extcodesize/address.code.length, which returns 0\n        // for contracts in construction, since the code is only stored at the end\n        // of the constructor execution.\n\n        return account.code.length > 0;\n    }\n\n    /**\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n     * `recipient`, forwarding all available gas and reverting on errors.\n     *\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\n     * imposed by `transfer`, making them unable to receive funds via\n     * `transfer`. {sendValue} removes this limitation.\n     *\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n     *\n     * IMPORTANT: because control is transferred to `recipient`, care must be\n     * taken to not create reentrancy vulnerabilities. Consider using\n     * {ReentrancyGuard} or the\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        require(success, \"Address: unable to send value, recipient may have reverted\");\n    }\n\n    /**\n     * @dev Performs a Solidity function call using a low level `call`. A\n     * plain `call` is an unsafe replacement for a function call: use this\n     * function instead.\n     *\n     * If `target` reverts with a revert reason, it is bubbled up by this\n     * function (like regular Solidity function calls).\n     *\n     * Returns the raw returned data. To convert to the expected return value,\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n     *\n     * Requirements:\n     *\n     * - `target` must be a contract.\n     * - calling `target` with `data` must not revert.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n     * `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but also transferring `value` wei to `target`.\n     *\n     * Requirements:\n     *\n     * - the calling contract must have an ETH balance of at least `value`.\n     * - the called Solidity function must be `payable`.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        require(address(this).balance >= value, \"Address: insufficient balance for call\");\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        return functionStaticCall(target, data, \"Address: low-level static call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n     *\n     * _Available since v4.8._\n     */\n    function verifyCallResultFromTarget(\n        address target,\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        if (success) {\n            if (returndata.length == 0) {\n                // only check isContract if the call was successful and the return data is empty\n                // otherwise we already know that it was a contract\n                require(isContract(target), \"Address: call to non-contract\");\n            }\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    /**\n     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n     * revert reason or using the provided one.\n     *\n     * _Available since v4.3._\n     */\n    function verifyCallResult(\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal pure returns (bytes memory) {\n        if (success) {\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    function _revert(bytes memory returndata, string memory errorMessage) private pure {\n        // Look for revert reason and bubble it up if present\n        if (returndata.length > 0) {\n            // The easiest way to bubble the revert reason is using memory via assembly\n            /// @solidity memory-safe-assembly\n            assembly {\n                let returndata_size := mload(returndata)\n                revert(add(32, returndata), returndata_size)\n            }\n        } else {\n            revert(errorMessage);\n        }\n    }\n}\n"},{"file_path":"lib/openzeppelin-contracts/contracts/interfaces/draft-IERC1822.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified\n * proxy whose upgrades are fully controlled by the current implementation.\n */\ninterface IERC1822Proxiable {\n    /**\n     * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation\n     * address.\n     *\n     * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\n     * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\n     * function revert if invoked through a proxy.\n     */\n    function proxiableUUID() external view returns (bytes32);\n}\n"},{"file_path":"lib/openzeppelin-contracts/contracts/proxy/ERC1967/ERC1967Upgrade.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (proxy/ERC1967/ERC1967Upgrade.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../beacon/IBeacon.sol\";\nimport \"../../interfaces/draft-IERC1822.sol\";\nimport \"../../utils/Address.sol\";\nimport \"../../utils/StorageSlot.sol\";\n\n/**\n * @dev This abstract contract provides getters and event emitting update functions for\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.\n *\n * _Available since v4.1._\n *\n * @custom:oz-upgrades-unsafe-allow delegatecall\n */\nabstract contract ERC1967Upgrade {\n    // This is the keccak-256 hash of \"eip1967.proxy.rollback\" subtracted by 1\n    bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;\n\n    /**\n     * @dev Storage slot with the address of the current implementation.\n     * This is the keccak-256 hash of \"eip1967.proxy.implementation\" subtracted by 1, and is\n     * validated in the constructor.\n     */\n    bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n\n    /**\n     * @dev Emitted when the implementation is upgraded.\n     */\n    event Upgraded(address indexed implementation);\n\n    /**\n     * @dev Returns the current implementation address.\n     */\n    function _getImplementation() internal view returns (address) {\n        return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\n    }\n\n    /**\n     * @dev Stores a new address in the EIP1967 implementation slot.\n     */\n    function _setImplementation(address newImplementation) private {\n        require(Address.isContract(newImplementation), \"ERC1967: new implementation is not a contract\");\n        StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\n    }\n\n    /**\n     * @dev Perform implementation upgrade\n     *\n     * Emits an {Upgraded} event.\n     */\n    function _upgradeTo(address newImplementation) internal {\n        _setImplementation(newImplementation);\n        emit Upgraded(newImplementation);\n    }\n\n    /**\n     * @dev Perform implementation upgrade with additional setup call.\n     *\n     * Emits an {Upgraded} event.\n     */\n    function _upgradeToAndCall(\n        address newImplementation,\n        bytes memory data,\n        bool forceCall\n    ) internal {\n        _upgradeTo(newImplementation);\n        if (data.length > 0 || forceCall) {\n            Address.functionDelegateCall(newImplementation, data);\n        }\n    }\n\n    /**\n     * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.\n     *\n     * Emits an {Upgraded} event.\n     */\n    function _upgradeToAndCallUUPS(\n        address newImplementation,\n        bytes memory data,\n        bool forceCall\n    ) internal {\n        // Upgrades from old implementations will perform a rollback test. This test requires the new\n        // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing\n        // this special case will break upgrade paths from old UUPS implementation to new ones.\n        if (StorageSlot.getBooleanSlot(_ROLLBACK_SLOT).value) {\n            _setImplementation(newImplementation);\n        } else {\n            try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {\n                require(slot == _IMPLEMENTATION_SLOT, \"ERC1967Upgrade: unsupported proxiableUUID\");\n            } catch {\n                revert(\"ERC1967Upgrade: new implementation is not UUPS\");\n            }\n            _upgradeToAndCall(newImplementation, data, forceCall);\n        }\n    }\n\n    /**\n     * @dev Storage slot with the admin of the contract.\n     * This is the keccak-256 hash of \"eip1967.proxy.admin\" subtracted by 1, and is\n     * validated in the constructor.\n     */\n    bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\n\n    /**\n     * @dev Emitted when the admin account has changed.\n     */\n    event AdminChanged(address previousAdmin, address newAdmin);\n\n    /**\n     * @dev Returns the current admin.\n     */\n    function _getAdmin() internal view returns (address) {\n        return StorageSlot.getAddressSlot(_ADMIN_SLOT).value;\n    }\n\n    /**\n     * @dev Stores a new address in the EIP1967 admin slot.\n     */\n    function _setAdmin(address newAdmin) private {\n        require(newAdmin != address(0), \"ERC1967: new admin is the zero address\");\n        StorageSlot.getAddressSlot(_ADMIN_SLOT).value = newAdmin;\n    }\n\n    /**\n     * @dev Changes the admin of the proxy.\n     *\n     * Emits an {AdminChanged} event.\n     */\n    function _changeAdmin(address newAdmin) internal {\n        emit AdminChanged(_getAdmin(), newAdmin);\n        _setAdmin(newAdmin);\n    }\n\n    /**\n     * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.\n     * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.\n     */\n    bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;\n\n    /**\n     * @dev Emitted when the beacon is upgraded.\n     */\n    event BeaconUpgraded(address indexed beacon);\n\n    /**\n     * @dev Returns the current beacon.\n     */\n    function _getBeacon() internal view returns (address) {\n        return StorageSlot.getAddressSlot(_BEACON_SLOT).value;\n    }\n\n    /**\n     * @dev Stores a new beacon in the EIP1967 beacon slot.\n     */\n    function _setBeacon(address newBeacon) private {\n        require(Address.isContract(newBeacon), \"ERC1967: new beacon is not a contract\");\n        require(\n            Address.isContract(IBeacon(newBeacon).implementation()),\n            \"ERC1967: beacon implementation is not a contract\"\n        );\n        StorageSlot.getAddressSlot(_BEACON_SLOT).value = newBeacon;\n    }\n\n    /**\n     * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does\n     * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).\n     *\n     * Emits a {BeaconUpgraded} event.\n     */\n    function _upgradeBeaconToAndCall(\n        address newBeacon,\n        bytes memory data,\n        bool forceCall\n    ) internal {\n        _setBeacon(newBeacon);\n        emit BeaconUpgraded(newBeacon);\n        if (data.length > 0 || forceCall) {\n            Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);\n        }\n    }\n}\n"},{"file_path":"lib/openzeppelin-contracts/contracts/proxy/beacon/IBeacon.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev This is the interface that {BeaconProxy} expects of its beacon.\n */\ninterface IBeacon {\n    /**\n     * @dev Must return an address that can be used as a delegate call target.\n     *\n     * {BeaconProxy} will check that this address is a contract.\n     */\n    function implementation() external view returns (address);\n}\n"},{"file_path":"lib/openzeppelin-contracts/contracts/proxy/utils/Initializable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.1) (proxy/utils/Initializable.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../../utils/Address.sol\";\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * contract MyToken is ERC20Upgradeable {\n *     function initialize() initializer public {\n *         __ERC20_init(\"MyToken\", \"MTK\");\n *     }\n * }\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n *     function initializeV2() reinitializer(2) public {\n *         __ERC20Permit_init(\"MyToken\");\n *     }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n *     _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n    /**\n     * @dev Indicates that the contract has been initialized.\n     * @custom:oz-retyped-from bool\n     */\n    uint8 private _initialized;\n\n    /**\n     * @dev Indicates that the contract is in the process of being initialized.\n     */\n    bool private _initializing;\n\n    /**\n     * @dev Triggered when the contract has been initialized or reinitialized.\n     */\n    event Initialized(uint8 version);\n\n    /**\n     * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n     * `onlyInitializing` functions can be used to initialize parent contracts.\n     *\n     * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\n     * constructor.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier initializer() {\n        bool isTopLevelCall = !_initializing;\n        require(\n            (isTopLevelCall && _initialized < 1) || (!Address.isContract(address(this)) && _initialized == 1),\n            \"Initializable: contract is already initialized\"\n        );\n        _initialized = 1;\n        if (isTopLevelCall) {\n            _initializing = true;\n        }\n        _;\n        if (isTopLevelCall) {\n            _initializing = false;\n            emit Initialized(1);\n        }\n    }\n\n    /**\n     * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n     * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n     * used to initialize parent contracts.\n     *\n     * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n     * are added through upgrades and that require initialization.\n     *\n     * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n     * cannot be nested. If one is invoked in the context of another, execution will revert.\n     *\n     * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n     * a contract, executing them in the right order is up to the developer or operator.\n     *\n     * WARNING: setting the version to 255 will prevent any future reinitialization.\n     *\n     * Emits an {Initialized} event.\n     */\n    modifier reinitializer(uint8 version) {\n        require(!_initializing && _initialized < version, \"Initializable: contract is already initialized\");\n        _initialized = version;\n        _initializing = true;\n        _;\n        _initializing = false;\n        emit Initialized(version);\n    }\n\n    /**\n     * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n     * {initializer} and {reinitializer} modifiers, directly or indirectly.\n     */\n    modifier onlyInitializing() {\n        require(_initializing, \"Initializable: contract is not initializing\");\n        _;\n    }\n\n    /**\n     * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n     * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n     * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n     * through proxies.\n     *\n     * Emits an {Initialized} event the first time it is successfully executed.\n     */\n    function _disableInitializers() internal virtual {\n        require(!_initializing, \"Initializable: contract is initializing\");\n        if (_initialized < type(uint8).max) {\n            _initialized = type(uint8).max;\n            emit Initialized(type(uint8).max);\n        }\n    }\n\n    /**\n     * @dev Returns the highest version that has been initialized. See {reinitializer}.\n     */\n    function _getInitializedVersion() internal view returns (uint8) {\n        return _initialized;\n    }\n\n    /**\n     * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n     */\n    function _isInitializing() internal view returns (bool) {\n        return _initializing;\n    }\n}\n"},{"file_path":"lib/openzeppelin-contracts/contracts/proxy/utils/UUPSUpgradeable.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (proxy/utils/UUPSUpgradeable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../interfaces/draft-IERC1822.sol\";\nimport \"../ERC1967/ERC1967Upgrade.sol\";\n\n/**\n * @dev An upgradeability mechanism designed for UUPS proxies. The functions included here can perform an upgrade of an\n * {ERC1967Proxy}, when this contract is set as the implementation behind such a proxy.\n *\n * A security mechanism ensures that an upgrade does not turn off upgradeability accidentally, although this risk is\n * reinstated if the upgrade retains upgradeability but removes the security mechanism, e.g. by replacing\n * `UUPSUpgradeable` with a custom implementation of upgrades.\n *\n * The {_authorizeUpgrade} function must be overridden to include access restriction to the upgrade mechanism.\n *\n * _Available since v4.1._\n */\nabstract contract UUPSUpgradeable is IERC1822Proxiable, ERC1967Upgrade {\n    /// @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment\n    address private immutable __self = address(this);\n\n    /**\n     * @dev Check that the execution is being performed through a delegatecall call and that the execution context is\n     * a proxy contract with an implementation (as defined in ERC1967) pointing to self. This should only be the case\n     * for UUPS and transparent proxies that are using the current contract as their implementation. Execution of a\n     * function through ERC1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to\n     * fail.\n     */\n    modifier onlyProxy() {\n        require(address(this) != __self, \"Function must be called through delegatecall\");\n        require(_getImplementation() == __self, \"Function must be called through active proxy\");\n        _;\n    }\n\n    /**\n     * @dev Check that the execution is not being performed through a delegate call. This allows a function to be\n     * callable on the implementing contract but not through proxies.\n     */\n    modifier notDelegated() {\n        require(address(this) == __self, \"UUPSUpgradeable: must not be called through delegatecall\");\n        _;\n    }\n\n    /**\n     * @dev Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the\n     * implementation. It is used to validate the implementation's compatibility when performing an upgrade.\n     *\n     * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\n     * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\n     * function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier.\n     */\n    function proxiableUUID() external view virtual override notDelegated returns (bytes32) {\n        return _IMPLEMENTATION_SLOT;\n    }\n\n    /**\n     * @dev Upgrade the implementation of the proxy to `newImplementation`.\n     *\n     * Calls {_authorizeUpgrade}.\n     *\n     * Emits an {Upgraded} event.\n     */\n    function upgradeTo(address newImplementation) external virtual onlyProxy {\n        _authorizeUpgrade(newImplementation);\n        _upgradeToAndCallUUPS(newImplementation, new bytes(0), false);\n    }\n\n    /**\n     * @dev Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call\n     * encoded in `data`.\n     *\n     * Calls {_authorizeUpgrade}.\n     *\n     * Emits an {Upgraded} event.\n     */\n    function upgradeToAndCall(address newImplementation, bytes memory data) external payable virtual onlyProxy {\n        _authorizeUpgrade(newImplementation);\n        _upgradeToAndCallUUPS(newImplementation, data, true);\n    }\n\n    /**\n     * @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by\n     * {upgradeTo} and {upgradeToAndCall}.\n     *\n     * Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}.\n     *\n     * ```solidity\n     * function _authorizeUpgrade(address) internal override onlyOwner {}\n     * ```\n     */\n    function _authorizeUpgrade(address newImplementation) internal virtual;\n}\n"},{"file_path":"lib/openzeppelin-contracts/contracts/token/ERC20/IERC20.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n    /**\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\n     * another (`to`).\n     *\n     * Note that `value` may be zero.\n     */\n    event Transfer(address indexed from, address indexed to, uint256 value);\n\n    /**\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n     * a call to {approve}. `value` is the new allowance.\n     */\n    event Approval(address indexed owner, address indexed spender, uint256 value);\n\n    /**\n     * @dev Returns the amount of tokens in existence.\n     */\n    function totalSupply() external view returns (uint256);\n\n    /**\n     * @dev Returns the amount of tokens owned by `account`.\n     */\n    function balanceOf(address account) external view returns (uint256);\n\n    /**\n     * @dev Moves `amount` tokens from the caller's account to `to`.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transfer(address to, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Returns the remaining number of tokens that `spender` will be\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\n     * zero by default.\n     *\n     * This value changes when {approve} or {transferFrom} are called.\n     */\n    function allowance(address owner, address spender) external view returns (uint256);\n\n    /**\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\n     * that someone may use both the old and the new allowance by unfortunate\n     * transaction ordering. One possible solution to mitigate this race\n     * condition is to first reduce the spender's allowance to 0 and set the\n     * desired value afterwards:\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n     *\n     * Emits an {Approval} event.\n     */\n    function approve(address spender, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Moves `amount` tokens from `from` to `to` using the\n     * allowance mechanism. `amount` is then deducted from the caller's\n     * allowance.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transferFrom(\n        address from,\n        address to,\n        uint256 amount\n    ) external returns (bool);\n}\n"},{"file_path":"lib/openzeppelin-contracts/contracts/token/ERC20/extensions/IERC20Metadata.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC20 standard.\n *\n * _Available since v4.1._\n */\ninterface IERC20Metadata is IERC20 {\n    /**\n     * @dev Returns the name of the token.\n     */\n    function name() external view returns (string memory);\n\n    /**\n     * @dev Returns the symbol of the token.\n     */\n    function symbol() external view returns (string memory);\n\n    /**\n     * @dev Returns the decimals places of the token.\n     */\n    function decimals() external view returns (uint8);\n}\n"},{"file_path":"lib/openzeppelin-contracts/contracts/token/ERC20/extensions/draft-IERC20Permit.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20Permit {\n    /**\n     * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n     * given ``owner``'s signed approval.\n     *\n     * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n     * ordering also apply here.\n     *\n     * Emits an {Approval} event.\n     *\n     * Requirements:\n     *\n     * - `spender` cannot be the zero address.\n     * - `deadline` must be a timestamp in the future.\n     * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n     * over the EIP712-formatted function arguments.\n     * - the signature must use ``owner``'s current nonce (see {nonces}).\n     *\n     * For more information on the signature format, see the\n     * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n     * section].\n     */\n    function permit(\n        address owner,\n        address spender,\n        uint256 value,\n        uint256 deadline,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) external;\n\n    /**\n     * @dev Returns the current nonce for `owner`. This value must be\n     * included whenever a signature is generated for {permit}.\n     *\n     * Every successful call to {permit} increases ``owner``'s nonce by one. This\n     * prevents a signature from being used multiple times.\n     */\n    function nonces(address owner) external view returns (uint256);\n\n    /**\n     * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n     */\n    // solhint-disable-next-line func-name-mixedcase\n    function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n"},{"file_path":"lib/openzeppelin-contracts/contracts/token/ERC20/utils/SafeERC20.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../extensions/draft-IERC20Permit.sol\";\nimport \"../../../utils/Address.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n    using Address for address;\n\n    function safeTransfer(\n        IERC20 token,\n        address to,\n        uint256 value\n    ) internal {\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n    }\n\n    function safeTransferFrom(\n        IERC20 token,\n        address from,\n        address to,\n        uint256 value\n    ) internal {\n        _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n    }\n\n    /**\n     * @dev Deprecated. This function has issues similar to the ones found in\n     * {IERC20-approve}, and its usage is discouraged.\n     *\n     * Whenever possible, use {safeIncreaseAllowance} and\n     * {safeDecreaseAllowance} instead.\n     */\n    function safeApprove(\n        IERC20 token,\n        address spender,\n        uint256 value\n    ) internal {\n        // safeApprove should only be called when setting an initial allowance,\n        // or when resetting it to zero. To increase and decrease it, use\n        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n        require(\n            (value == 0) || (token.allowance(address(this), spender) == 0),\n            \"SafeERC20: approve from non-zero to non-zero allowance\"\n        );\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n    }\n\n    function safeIncreaseAllowance(\n        IERC20 token,\n        address spender,\n        uint256 value\n    ) internal {\n        uint256 newAllowance = token.allowance(address(this), spender) + value;\n        _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n    }\n\n    function safeDecreaseAllowance(\n        IERC20 token,\n        address spender,\n        uint256 value\n    ) internal {\n        unchecked {\n            uint256 oldAllowance = token.allowance(address(this), spender);\n            require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n            uint256 newAllowance = oldAllowance - value;\n            _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n        }\n    }\n\n    function safePermit(\n        IERC20Permit token,\n        address owner,\n        address spender,\n        uint256 value,\n        uint256 deadline,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) internal {\n        uint256 nonceBefore = token.nonces(owner);\n        token.permit(owner, spender, value, deadline, v, r, s);\n        uint256 nonceAfter = token.nonces(owner);\n        require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\n    }\n\n    /**\n     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n     * on the return value: the return value is optional (but if data is returned, it must not be false).\n     * @param token The token targeted by the call.\n     * @param data The call data (encoded using abi.encode or one of its variants).\n     */\n    function _callOptionalReturn(IERC20 token, bytes memory data) private {\n        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n        // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n        // the target address contains contract code and also asserts for success in the low-level call.\n\n        bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n        if (returndata.length > 0) {\n            // Return data is optional\n            require(abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n        }\n    }\n}\n"},{"file_path":"lib/openzeppelin-contracts/contracts/utils/Address.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n    /**\n     * @dev Returns true if `account` is a contract.\n     *\n     * [IMPORTANT]\n     * ====\n     * It is unsafe to assume that an address for which this function returns\n     * false is an externally-owned account (EOA) and not a contract.\n     *\n     * Among others, `isContract` will return false for the following\n     * types of addresses:\n     *\n     *  - an externally-owned account\n     *  - a contract in construction\n     *  - an address where a contract will be created\n     *  - an address where a contract lived, but was destroyed\n     * ====\n     *\n     * [IMPORTANT]\n     * ====\n     * You shouldn't rely on `isContract` to protect against flash loan attacks!\n     *\n     * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n     * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n     * constructor.\n     * ====\n     */\n    function isContract(address account) internal view returns (bool) {\n        // This method relies on extcodesize/address.code.length, which returns 0\n        // for contracts in construction, since the code is only stored at the end\n        // of the constructor execution.\n\n        return account.code.length > 0;\n    }\n\n    /**\n     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n     * `recipient`, forwarding all available gas and reverting on errors.\n     *\n     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n     * of certain opcodes, possibly making contracts go over the 2300 gas limit\n     * imposed by `transfer`, making them unable to receive funds via\n     * `transfer`. {sendValue} removes this limitation.\n     *\n     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n     *\n     * IMPORTANT: because control is transferred to `recipient`, care must be\n     * taken to not create reentrancy vulnerabilities. Consider using\n     * {ReentrancyGuard} or the\n     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n     */\n    function sendValue(address payable recipient, uint256 amount) internal {\n        require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n        (bool success, ) = recipient.call{value: amount}(\"\");\n        require(success, \"Address: unable to send value, recipient may have reverted\");\n    }\n\n    /**\n     * @dev Performs a Solidity function call using a low level `call`. A\n     * plain `call` is an unsafe replacement for a function call: use this\n     * function instead.\n     *\n     * If `target` reverts with a revert reason, it is bubbled up by this\n     * function (like regular Solidity function calls).\n     *\n     * Returns the raw returned data. To convert to the expected return value,\n     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n     *\n     * Requirements:\n     *\n     * - `target` must be a contract.\n     * - calling `target` with `data` must not revert.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n     * `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, 0, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but also transferring `value` wei to `target`.\n     *\n     * Requirements:\n     *\n     * - the calling contract must have an ETH balance of at least `value`.\n     * - the called Solidity function must be `payable`.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value\n    ) internal returns (bytes memory) {\n        return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n     * with `errorMessage` as a fallback revert reason when `target` reverts.\n     *\n     * _Available since v3.1._\n     */\n    function functionCallWithValue(\n        address target,\n        bytes memory data,\n        uint256 value,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        require(address(this).balance >= value, \"Address: insufficient balance for call\");\n        (bool success, bytes memory returndata) = target.call{value: value}(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n        return functionStaticCall(target, data, \"Address: low-level static call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a static call.\n     *\n     * _Available since v3.3._\n     */\n    function functionStaticCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.staticcall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n        return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n    }\n\n    /**\n     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n     * but performing a delegate call.\n     *\n     * _Available since v3.4._\n     */\n    function functionDelegateCall(\n        address target,\n        bytes memory data,\n        string memory errorMessage\n    ) internal returns (bytes memory) {\n        (bool success, bytes memory returndata) = target.delegatecall(data);\n        return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n    }\n\n    /**\n     * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n     * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n     *\n     * _Available since v4.8._\n     */\n    function verifyCallResultFromTarget(\n        address target,\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal view returns (bytes memory) {\n        if (success) {\n            if (returndata.length == 0) {\n                // only check isContract if the call was successful and the return data is empty\n                // otherwise we already know that it was a contract\n                require(isContract(target), \"Address: call to non-contract\");\n            }\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    /**\n     * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n     * revert reason or using the provided one.\n     *\n     * _Available since v4.3._\n     */\n    function verifyCallResult(\n        bool success,\n        bytes memory returndata,\n        string memory errorMessage\n    ) internal pure returns (bytes memory) {\n        if (success) {\n            return returndata;\n        } else {\n            _revert(returndata, errorMessage);\n        }\n    }\n\n    function _revert(bytes memory returndata, string memory errorMessage) private pure {\n        // Look for revert reason and bubble it up if present\n        if (returndata.length > 0) {\n            // The easiest way to bubble the revert reason is using memory via assembly\n            /// @solidity memory-safe-assembly\n            assembly {\n                let returndata_size := mload(returndata)\n                revert(add(32, returndata), returndata_size)\n            }\n        } else {\n            revert(errorMessage);\n        }\n    }\n}\n"},{"file_path":"lib/openzeppelin-contracts/contracts/utils/StorageSlot.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (utils/StorageSlot.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Library for reading and writing primitive types to specific storage slots.\n *\n * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.\n * This library helps with reading and writing to such slots without the need for inline assembly.\n *\n * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.\n *\n * Example usage to set ERC1967 implementation slot:\n * ```\n * contract ERC1967 {\n *     bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n *\n *     function _getImplementation() internal view returns (address) {\n *         return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\n *     }\n *\n *     function _setImplementation(address newImplementation) internal {\n *         require(Address.isContract(newImplementation), \"ERC1967: new implementation is not a contract\");\n *         StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\n *     }\n * }\n * ```\n *\n * _Available since v4.1 for `address`, `bool`, `bytes32`, and `uint256`._\n */\nlibrary StorageSlot {\n    struct AddressSlot {\n        address value;\n    }\n\n    struct BooleanSlot {\n        bool value;\n    }\n\n    struct Bytes32Slot {\n        bytes32 value;\n    }\n\n    struct Uint256Slot {\n        uint256 value;\n    }\n\n    /**\n     * @dev Returns an `AddressSlot` with member `value` located at `slot`.\n     */\n    function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns an `BooleanSlot` with member `value` located at `slot`.\n     */\n    function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.\n     */\n    function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            r.slot := slot\n        }\n    }\n\n    /**\n     * @dev Returns an `Uint256Slot` with member `value` located at `slot`.\n     */\n    function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\n        /// @solidity memory-safe-assembly\n        assembly {\n            r.slot := slot\n        }\n    }\n}\n"},{"file_path":"lib/openzeppelin-contracts/contracts/utils/math/Math.sol","source_code":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n    enum Rounding {\n        Down, // Toward negative infinity\n        Up, // Toward infinity\n        Zero // Toward zero\n    }\n\n    /**\n     * @dev Returns the largest of two numbers.\n     */\n    function max(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a > b ? a : b;\n    }\n\n    /**\n     * @dev Returns the smallest of two numbers.\n     */\n    function min(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a < b ? a : b;\n    }\n\n    /**\n     * @dev Returns the average of two numbers. The result is rounded towards\n     * zero.\n     */\n    function average(uint256 a, uint256 b) internal pure returns (uint256) {\n        // (a + b) / 2 can overflow.\n        return (a & b) + (a ^ b) / 2;\n    }\n\n    /**\n     * @dev Returns the ceiling of the division of two numbers.\n     *\n     * This differs from standard division with `/` in that it rounds up instead\n     * of rounding down.\n     */\n    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n        // (a + b - 1) / b can overflow on addition, so we distribute.\n        return a == 0 ? 0 : (a - 1) / b + 1;\n    }\n\n    /**\n     * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n     * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n     * with further edits by Uniswap Labs also under MIT license.\n     */\n    function mulDiv(\n        uint256 x,\n        uint256 y,\n        uint256 denominator\n    ) internal pure returns (uint256 result) {\n        unchecked {\n            // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n            // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n            // variables such that product = prod1 * 2^256 + prod0.\n            uint256 prod0; // Least significant 256 bits of the product\n            uint256 prod1; // Most significant 256 bits of the product\n            assembly {\n                let mm := mulmod(x, y, not(0))\n                prod0 := mul(x, y)\n                prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n            }\n\n            // Handle non-overflow cases, 256 by 256 division.\n            if (prod1 == 0) {\n                return prod0 / denominator;\n            }\n\n            // Make sure the result is less than 2^256. Also prevents denominator == 0.\n            require(denominator > prod1);\n\n            ///////////////////////////////////////////////\n            // 512 by 256 division.\n            ///////////////////////////////////////////////\n\n            // Make division exact by subtracting the remainder from [prod1 prod0].\n            uint256 remainder;\n            assembly {\n                // Compute remainder using mulmod.\n                remainder := mulmod(x, y, denominator)\n\n                // Subtract 256 bit number from 512 bit number.\n                prod1 := sub(prod1, gt(remainder, prod0))\n                prod0 := sub(prod0, remainder)\n            }\n\n            // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n            // See https://cs.stackexchange.com/q/138556/92363.\n\n            // Does not overflow because the denominator cannot be zero at this stage in the function.\n            uint256 twos = denominator & (~denominator + 1);\n            assembly {\n                // Divide denominator by twos.\n                denominator := div(denominator, twos)\n\n                // Divide [prod1 prod0] by twos.\n                prod0 := div(prod0, twos)\n\n                // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n                twos := add(div(sub(0, twos), twos), 1)\n            }\n\n            // Shift in bits from prod1 into prod0.\n            prod0 |= prod1 * twos;\n\n            // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n            // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n            // four bits. That is, denominator * inv = 1 mod 2^4.\n            uint256 inverse = (3 * denominator) ^ 2;\n\n            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n            // in modular arithmetic, doubling the correct bits in each step.\n            inverse *= 2 - denominator * inverse; // inverse mod 2^8\n            inverse *= 2 - denominator * inverse; // inverse mod 2^16\n            inverse *= 2 - denominator * inverse; // inverse mod 2^32\n            inverse *= 2 - denominator * inverse; // inverse mod 2^64\n            inverse *= 2 - denominator * inverse; // inverse mod 2^128\n            inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n            // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n            // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n            // is no longer required.\n            result = prod0 * inverse;\n            return result;\n        }\n    }\n\n    /**\n     * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n     */\n    function mulDiv(\n        uint256 x,\n        uint256 y,\n        uint256 denominator,\n        Rounding rounding\n    ) internal pure returns (uint256) {\n        uint256 result = mulDiv(x, y, denominator);\n        if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n            result += 1;\n        }\n        return result;\n    }\n\n    /**\n     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n     *\n     * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n     */\n    function sqrt(uint256 a) internal pure returns (uint256) {\n        if (a == 0) {\n            return 0;\n        }\n\n        // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n        //\n        // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n        // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n        //\n        // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n        // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n        // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n        //\n        // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n        uint256 result = 1 << (log2(a) >> 1);\n\n        // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n        // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n        // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n        // into the expected uint128 result.\n        unchecked {\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            result = (result + a / result) >> 1;\n            return min(result, a / result);\n        }\n    }\n\n    /**\n     * @notice Calculates sqrt(a), following the selected rounding direction.\n     */\n    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = sqrt(a);\n            return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 2, rounded down, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log2(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >> 128 > 0) {\n                value >>= 128;\n                result += 128;\n            }\n            if (value >> 64 > 0) {\n                value >>= 64;\n                result += 64;\n            }\n            if (value >> 32 > 0) {\n                value >>= 32;\n                result += 32;\n            }\n            if (value >> 16 > 0) {\n                value >>= 16;\n                result += 16;\n            }\n            if (value >> 8 > 0) {\n                value >>= 8;\n                result += 8;\n            }\n            if (value >> 4 > 0) {\n                value >>= 4;\n                result += 4;\n            }\n            if (value >> 2 > 0) {\n                value >>= 2;\n                result += 2;\n            }\n            if (value >> 1 > 0) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log2(value);\n            return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 10, rounded down, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log10(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >= 10**64) {\n                value /= 10**64;\n                result += 64;\n            }\n            if (value >= 10**32) {\n                value /= 10**32;\n                result += 32;\n            }\n            if (value >= 10**16) {\n                value /= 10**16;\n                result += 16;\n            }\n            if (value >= 10**8) {\n                value /= 10**8;\n                result += 8;\n            }\n            if (value >= 10**4) {\n                value /= 10**4;\n                result += 4;\n            }\n            if (value >= 10**2) {\n                value /= 10**2;\n                result += 2;\n            }\n            if (value >= 10**1) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log10(value);\n            return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0);\n        }\n    }\n\n    /**\n     * @dev Return the log in base 256, rounded down, of a positive value.\n     * Returns 0 if given 0.\n     *\n     * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n     */\n    function log256(uint256 value) internal pure returns (uint256) {\n        uint256 result = 0;\n        unchecked {\n            if (value >> 128 > 0) {\n                value >>= 128;\n                result += 16;\n            }\n            if (value >> 64 > 0) {\n                value >>= 64;\n                result += 8;\n            }\n            if (value >> 32 > 0) {\n                value >>= 32;\n                result += 4;\n            }\n            if (value >> 16 > 0) {\n                value >>= 16;\n                result += 2;\n            }\n            if (value >> 8 > 0) {\n                result += 1;\n            }\n        }\n        return result;\n    }\n\n    /**\n     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n     * Returns 0 if given 0.\n     */\n    function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n        unchecked {\n            uint256 result = log256(value);\n            return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0);\n        }\n    }\n}\n"},{"file_path":"src/config/constants.sol","source_code":"/**\n * Copyright 2025 Circle Internet Group, Inc. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npragma solidity ^0.8.0;\n\n/// @dev Fees are 18-decimal places. For example: 20 * 10**18 = 20%\nuint256 constant FEE_MULTIPLIER = 10 ** 18;\nuint256 constant HUNDRED_PCT = 100 * FEE_MULTIPLIER;\n\nuint256 constant AFTER_HOURS_DISABLED = type(uint256).max;\n\nuint8 constant ROLE_INVESTOR = 0;\nuint8 constant ROLE_INVESTOR_BETA = 1;\nuint8 constant ROLE_RESERVES = 7;\nuint8 constant ROLE_ENTITLEMENTS = 8;\nuint8 constant ROLE_TELLER = 9;\nuint8 constant ROLE_ORACLE = 10;\nuint8 constant ROLE_MESSENGER = 11;\nuint8 constant ROLE_CCTP = 12;\nuint8 constant ROLE_CUSTODIAN_CENTRAL = 18;\nuint8 constant ROLE_CUSTODIAN_DECENTRAL = 19;\nuint8 constant ROLE_TOKEN_MINTER = 20;\nuint8 constant ROLE_FUND_ADMIN = type(uint8).max;\n"},{"file_path":"src/config/errors.sol","source_code":"/**\n * Copyright 2025 Circle Internet Group, Inc. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npragma solidity ^0.8.0;\n\nerror NoAccess();\nerror NotPermissioned();\nerror NotSupported();\nerror BadAddress();\nerror BadAmount();\nerror BadDecimals();\nerror ZeroShares();\nerror ZeroAssets();\nerror BadTime();\nerror BadArrayLength();\nerror CallFailed();\nerror LimitExceeded();\n"},{"file_path":"src/config/types.sol","source_code":"/**\n * Copyright 2025 Circle Internet Group, Inc. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npragma solidity ^0.8.0;\n\nstruct TellerConfig {\n    address owner;\n    address asset;\n    address share;\n    address oracle;\n    address treasury;\n    address feeRecipient;\n    uint64 subscribeFee;\n    uint64 redeemFee;\n    uint256 afterHourTrading;\n    uint56 subscribeLimit;\n    uint56 redeemLimit;\n}\n"},{"file_path":"src/core/coins/ERC20.sol","source_code":"// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity ^0.8.0;\n\n/// @notice Modern and gas efficient ERC20 + EIP-2612 implementation.\n/// @author dsshap (Circle)\n/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol)\n/// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol)\n/// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it.\nabstract contract ERC20 {\n    /*//////////////////////////////////////////////////////////////\n                                 EVENTS\n    //////////////////////////////////////////////////////////////*/\n\n    event Transfer(address indexed from, address indexed to, uint256 amount);\n\n    event Approval(address indexed owner, address indexed spender, uint256 amount);\n\n    /*//////////////////////////////////////////////////////////////\n                            METADATA STORAGE\n    //////////////////////////////////////////////////////////////*/\n\n    string public name;\n\n    string public symbol;\n\n    /*//////////////////////////////////////////////////////////////\n                              ERC20 STORAGE\n    //////////////////////////////////////////////////////////////*/\n\n    uint256 public totalSupply;\n\n    mapping(address => uint256) public balanceOf;\n\n    mapping(address => mapping(address => uint256)) public allowance;\n\n    /*//////////////////////////////////////////////////////////////\n                            EIP-2612 STORAGE\n    //////////////////////////////////////////////////////////////*/\n\n    mapping(address => uint256) public nonces;\n\n    /*//////////////////////////////////////////////////////////////\n                               CONSTRUCTOR\n    //////////////////////////////////////////////////////////////*/\n\n    constructor() {}\n\n    /*//////////////////////////////////////////////////////////////\n                               ERC20 LOGIC\n    //////////////////////////////////////////////////////////////*/\n\n    function approve(address spender, uint256 amount) public virtual returns (bool) {\n        allowance[msg.sender][spender] = amount;\n\n        emit Approval(msg.sender, spender, amount);\n\n        return true;\n    }\n\n    function transfer(address to, uint256 amount) public virtual returns (bool) {\n        balanceOf[msg.sender] -= amount;\n\n        // Cannot overflow because the sum of all user\n        // balances can't exceed the max uint256 value.\n        unchecked {\n            balanceOf[to] += amount;\n        }\n\n        emit Transfer(msg.sender, to, amount);\n\n        return true;\n    }\n\n    function transferFrom(address from, address to, uint256 amount) public virtual returns (bool) {\n        uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals.\n\n        if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount;\n\n        balanceOf[from] -= amount;\n\n        // Cannot overflow because the sum of all user\n        // balances can't exceed the max uint256 value.\n        unchecked {\n            balanceOf[to] += amount;\n        }\n\n        emit Transfer(from, to, amount);\n\n        return true;\n    }\n\n    /*//////////////////////////////////////////////////////////////\n                        INTERNAL MINT/BURN LOGIC\n    //////////////////////////////////////////////////////////////*/\n\n    function _mint(address to, uint256 amount) internal virtual {\n        totalSupply += amount;\n\n        // Cannot overflow because the sum of all user\n        // balances can't exceed the max uint256 value.\n        unchecked {\n            balanceOf[to] += amount;\n        }\n\n        emit Transfer(address(0), to, amount);\n    }\n\n    function _burn(address from, uint256 amount) internal virtual {\n        balanceOf[from] -= amount;\n\n        // Cannot underflow because a user's balance\n        // will never be larger than the total supply.\n        unchecked {\n            totalSupply -= amount;\n        }\n\n        emit Transfer(from, address(0), amount);\n    }\n\n    /*//////////////////////////////////////////////////////////////\n                             EIP-2612 LOGIC\n    //////////////////////////////////////////////////////////////*/\n\n    function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s)\n        public\n        virtual\n    {\n        require(deadline >= block.timestamp, \"PERMIT_DEADLINE_EXPIRED\");\n\n        // Unchecked because the only math done is incrementing\n        // the owner's nonce which cannot realistically overflow.\n        unchecked {\n            address recoveredAddress = ecrecover(\n                keccak256(\n                    abi.encodePacked(\n                        \"\\x19\\x01\",\n                        DOMAIN_SEPARATOR(),\n                        keccak256(\n                            abi.encode(\n                                keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\"),\n                                owner,\n                                spender,\n                                value,\n                                nonces[owner]++,\n                                deadline\n                            )\n                        )\n                    )\n                ),\n                v,\n                r,\n                s\n            );\n\n            require(recoveredAddress != address(0) && recoveredAddress == owner, \"INVALID_SIGNER\");\n\n            allowance[recoveredAddress][spender] = value;\n        }\n\n        emit Approval(owner, spender, value);\n    }\n\n    function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {\n        return _computeDomainSeparator();\n    }\n\n    function _computeDomainSeparator() internal view virtual returns (bytes32) {\n        return keccak256(\n            abi.encode(\n                keccak256(\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"),\n                keccak256(bytes(name)),\n                keccak256(\"1\"),\n                block.chainid,\n                address(this)\n            )\n        );\n    }\n}\n"},{"file_path":"src/core/entitlements/Access.sol","source_code":"/**\n * Copyright 2025 Circle Internet Group, Inc. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npragma solidity ^0.8.0;\n\nimport {RolesAuthority} from \"./RolesAuthority.sol\";\n\nimport \"../../config/constants.sol\";\nimport \"../../config/errors.sol\";\n\n/// @notice Abstract contract that provides a base for role-based access control.\n/// @author dsshap (Circle)\nabstract contract Access {\n    /*///////////////////////////////////////////////////////////////\n                         Immutables & Constants\n    //////////////////////////////////////////////////////////////*/\n\n    /// @notice authority to check entitlements\n    RolesAuthority public immutable authority;\n\n    /*///////////////////////////////////////////////////////////////\n                         Storage Variables\n    //////////////////////////////////////////////////////////////*/\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     */\n    uint256[50] private __gap;\n\n    /// @notice bytes sig for token transfer function\n    bytes4 private constant _TOKEN_TRANSFER_SELECTOR = bytes4(keccak256(\"transfer(address,uint256)\"));\n\n    constructor(address _authority) {\n        if (_authority == address(0)) revert BadAddress();\n\n        authority = RolesAuthority(_authority);\n    }\n\n    /**\n     * @dev queries if msg.sender is fund admin\n     *\n     */\n    function _isFundAdmin() internal view virtual returns (bool) {\n        return authority.doesUserHaveRole(msg.sender, ROLE_FUND_ADMIN);\n    }\n\n    /**\n     * @dev asserts that msg.sender is fund admin\n     *\n     */\n    function _assertFundAdmin() internal view virtual {\n        if (!_isFundAdmin()) revert NotPermissioned();\n    }\n\n    /**\n     * @dev asserts that address is able to call function\n     *\n     */\n    function _assertPermission(address addr) internal view virtual {\n        _assertCanCall(addr, address(this), msg.sig);\n    }\n\n    /**\n     * @dev asserts that address is able to transfer erc20 token\n     *\n     */\n    function _assertCanReceive(address token, address addr) internal view virtual {\n        _assertCanCall(addr, token, _TOKEN_TRANSFER_SELECTOR);\n    }\n\n    /**\n     * @dev asserts that two addresses can transfer erc20 token\n     *\n     */\n    function _assertCanReceive(address token, address addr1, address addr2) internal view virtual {\n        _assertCanCall(addr1, addr2, token, _TOKEN_TRANSFER_SELECTOR);\n    }\n\n    /**\n     * @dev call authority and asserts if address can call function on target\n     *\n     */\n    function _assertCanCall(address addr, address target, bytes4 functionSig) internal view virtual {\n        if (!authority.canCall(addr, target, functionSig)) revert NotPermissioned();\n    }\n\n    /**\n     * @dev call authority and asserts if two addresses can call function on target\n     *\n     */\n    function _assertCanCall(address addr1, address addr2, address target, bytes4 functionSig) internal view virtual {\n        if (!authority.canCall(addr1, addr2, target, functionSig)) revert NotPermissioned();\n    }\n}\n"},{"file_path":"src/core/entitlements/Ownable.sol","source_code":"/**\n * Copyright 2025 Circle Internet Group, Inc. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npragma solidity ^0.8.0;\n\nimport \"../../config/errors.sol\";\n\n/// @notice Slimmed down version of OpenZeppelin's Ownable2Step contract.\n/// @author dsshap (Circle)\nabstract contract Ownable {\n    /*//////////////////////////////////////////////////////////////\n                                 EVENTS\n    //////////////////////////////////////////////////////////////*/\n\n    event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n    /*///////////////////////////////////////////////////////////////\n                          State Variables V1\n    //////////////////////////////////////////////////////////////*/\n\n    address public owner;\n    address public pendingOwner;\n\n    /// @notice gap from OwnableUpgradeable(49) - pendingOwner\n    uint256[48] private __gap;\n\n    /**\n     * @dev Throws if the sender is not the owner.\n     */\n    function _assertOwner() internal view virtual {\n        if (owner != msg.sender) revert NoAccess();\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual {\n        _assertOwner();\n\n        if (newOwner == address(0)) revert BadAddress();\n\n        pendingOwner = newOwner;\n\n        emit OwnershipTransferStarted(owner, newOwner);\n    }\n\n    /**\n     * @dev The new owner accepts the ownership transfer.\n     */\n    function acceptOwnership() external {\n        if (pendingOwner != msg.sender) revert NoAccess();\n\n        _transferOwnership(pendingOwner);\n    }\n\n    /**\n     * @dev Leaves the contract without owner. It will not be possible to call\n     * `onlyOwner` functions anymore. Can only be called by the current owner.\n     *\n     * NOTE: Renouncing ownership will leave the contract without an owner,\n     * thereby removing any functionality that is only available to the owner.\n     */\n    function renounceOwnership() public virtual {\n        _assertOwner();\n        _transferOwnership(address(0));\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual {\n        delete pendingOwner;\n\n        emit OwnershipTransferred(owner, newOwner);\n\n        owner = newOwner;\n    }\n}\n"},{"file_path":"src/core/entitlements/RolesAuthority.sol","source_code":"// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity ^0.8.0;\n\nimport {UUPSUpgradeable} from \"openzeppelin/proxy/utils/UUPSUpgradeable.sol\";\nimport {Initializable} from \"openzeppelin/proxy/utils/Initializable.sol\";\nimport {RolesUtil} from \"./RolesUtil.sol\";\nimport {Ownable} from \"./Ownable.sol\";\n\nimport {IAuthority} from \"../../interfaces/IAuthority.sol\";\n\nimport \"../../config/errors.sol\";\n\n/// @notice Role based Authority that supports up to 256 roles.\n/// @author dsshap (Circle)\n/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/auth/authorities/RolesAuthority.sol)\n/// @author Modified from Dappsys (https://github.com/dapphub/ds-roles/blob/master/src/roles.sol)\ncontract RolesAuthority is IAuthority, Initializable, Ownable, UUPSUpgradeable {\n    using RolesUtil for bytes32;\n\n    /*///////////////////////////////////////////////////////////////\n                         State Variables V1\n    //////////////////////////////////////////////////////////////*/\n\n    bool public paused;\n\n    /*//////////////////////////////////////////////////////////////\n                                 EVENTS\n    //////////////////////////////////////////////////////////////*/\n    event UserRoleUpdated(address indexed user, uint8 indexed role, bool enabled);\n\n    event PublicCapabilityUpdated(address indexed target, bytes4 indexed functionSig, bool enabled);\n\n    event RoleCapabilityUpdated(uint8 indexed role, address indexed target, bytes4 indexed functionSig, bool enabled);\n\n    event Paused(address account);\n\n    event Unpaused(address account);\n\n    /*//////////////////////////////////////////////////////////////\n                               CONSTRUCTOR\n    //////////////////////////////////////////////////////////////*/\n\n    constructor() {\n        _disableInitializers();\n    }\n\n    /*///////////////////////////////////////////////////////////////\n                            Initializer\n    //////////////////////////////////////////////////////////////*/\n\n    function initialize(address _owner) external initializer {\n        if (_owner == address(0)) revert BadAddress();\n\n        owner = _owner;\n    }\n\n    /*//////////////////////////////////////////////////////////////\n                            ROLE/USER STORAGE\n    //////////////////////////////////////////////////////////////*/\n\n    mapping(address => bytes32) public getUserRoles;\n\n    mapping(address => mapping(bytes4 => bool)) public isCapabilityPublic;\n\n    mapping(address => mapping(bytes4 => bytes32)) public getRolesWithCapability;\n\n    function doesUserHaveRole(address user, uint8 role) public view virtual returns (bool) {\n        if (paused) revert NoAccess();\n\n        return getUserRoles[user].doesHaveRole(role);\n    }\n\n    function doesRoleHaveCapability(uint8 role, address target, bytes4 functionSig) public view virtual returns (bool) {\n        if (paused) revert NoAccess();\n\n        return getRolesWithCapability[target][functionSig].doesHaveCapability(role);\n    }\n\n    /*//////////////////////////////////////////////////////////////\n                           AUTHORIZATION LOGIC\n    //////////////////////////////////////////////////////////////*/\n\n    function canCall(address user, address target, bytes4 functionSig) public view virtual returns (bool) {\n        if (paused) revert NoAccess();\n\n        return\n            isCapabilityPublic[target][functionSig]\n                || bytes32(0) != getUserRoles[user] & getRolesWithCapability[target][functionSig];\n    }\n\n    function canCall(address user1, address user2, address target, bytes4 functionSig) public view virtual returns (bool) {\n        return canCall(user1, target, functionSig) && canCall(user2, target, functionSig);\n    }\n\n    /*//////////////////////////////////////////////////////////////\n                   ROLE CAPABILITY CONFIGURATION LOGIC\n    //////////////////////////////////////////////////////////////*/\n\n    function _assertPermissions() internal view {\n        if (!canCall(msg.sender, address(this), msg.sig)) revert NoAccess();\n    }\n\n    function setPublicCapability(address target, bytes4 functionSig, bool enabled) public virtual {\n        _assertPermissions();\n\n        isCapabilityPublic[target][functionSig] = enabled;\n\n        emit PublicCapabilityUpdated(target, functionSig, enabled);\n    }\n\n    function setRoleCapability(uint8 role, address target, bytes4 functionSig, bool enabled) public virtual {\n        role == type(uint8).max ? _assertOwner() : _assertPermissions();\n\n        if (enabled) getRolesWithCapability[target][functionSig] |= bytes32(1 << role);\n        else getRolesWithCapability[target][functionSig] &= ~bytes32(1 << role);\n\n        emit RoleCapabilityUpdated(role, target, functionSig, enabled);\n    }\n\n    /*//////////////////////////////////////////////////////////////\n                       USER ROLE ASSIGNMENT LOGIC\n    //////////////////////////////////////////////////////////////*/\n\n    function _setUserRole(address user, uint8 role, bool enabled) internal virtual {\n        if (enabled) getUserRoles[user] |= bytes32(1 << role);\n        else getUserRoles[user] &= ~bytes32(1 << role);\n\n        emit UserRoleUpdated(user, uint8(role), enabled);\n    }\n\n    function setUserRole(address user, uint8 role, bool enabled) public virtual {\n        if (role == type(uint8).max) _assertOwner();\n        else _assertPermissions();\n\n        _setUserRole(user, role, enabled);\n    }\n\n    function setUserRoleBatch(address[] memory users, uint8[] memory roles, bool[] memory enabled) public virtual {\n        _assertPermissions();\n\n        uint256 length = users.length;\n        if (length == 0 || length != roles.length || length != enabled.length) revert BadArrayLength();\n\n        for (uint256 i; i < length;) {\n            if (roles[i] == type(uint8).max) _assertOwner();\n\n            _setUserRole(users[i], roles[i], enabled[i]);\n\n            unchecked {\n                ++i;\n            }\n        }\n    }\n\n    function revokeRole(uint8 role) external virtual {\n        if (!doesUserHaveRole(msg.sender, role)) revert NoAccess();\n\n        _setUserRole(msg.sender, role, false);\n    }\n\n    /*//////////////////////////////////////////////////////////////\n                            PAUSE LOGIC\n    //////////////////////////////////////////////////////////////*/\n\n    /**\n     * @notice Pauses\n     * @dev reverts on any check of permissions preventing any movement of funds\n     *      between vault, auction, and option protocol\n     */\n    function pause() public {\n        _assertPermissions();\n\n        paused = true;\n\n        emit Paused(msg.sender);\n    }\n\n    /**\n     * @notice Unpauses\n     */\n    function unpause() public {\n        _assertOwner();\n\n        paused = false;\n\n        emit Unpaused(msg.sender);\n    }\n\n    /*///////////////////////////////////////////////////////////////\n                    Override Upgrade Permission\n    //////////////////////////////////////////////////////////////*/\n\n    /**\n     * @dev Upgradable by the owner.\n     *\n     */\n    function _authorizeUpgrade(\n        address /*newImplementation*/\n    )\n        internal\n        view\n        override\n    {\n        _assertOwner();\n    }\n}\n"},{"file_path":"src/core/entitlements/RolesUtil.sol","source_code":"// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity ^0.8.0;\n\n/// @notice Role Utility\n/// @author dsshap (Circle)\n/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/auth/authorities/RolesAuthority.sol)\n/// @author Modified from Dappsys (https://github.com/dapphub/ds-roles/blob/master/src/roles.sol)\nlibrary RolesUtil {\n    /**\n     * @dev checks if userRole has role\n     */\n    function doesHaveRole(bytes32 userRoles, uint8 role) internal pure returns (bool) {\n        return (uint256(userRoles) >> role) & 1 != 0;\n    }\n\n    /**\n     * @dev checks if role has capability\n     */\n    function doesHaveCapability(bytes32 capabilities, uint8 role) internal pure returns (bool) {\n        return (uint256(capabilities) >> role) & 1 != 0;\n    }\n}\n"},{"file_path":"src/core/tellers/Teller.sol","source_code":"/**\n * Copyright 2025 Circle Internet Group, Inc. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npragma solidity ^0.8.0;\n\n// imported contracts and libraries\nimport {Access} from \"../entitlements/Access.sol\";\nimport {BokkyPooBahsDateTimeLibrary as DateTimeUtil} from \"bpb-dateTime/BokkyPooBahsDateTimeLibrary.sol\";\nimport {DaylightSavingsCalendar} from \"./calendars/DaylightSavingsCalendar.sol\";\nimport {DaylightSavingsLibrary} from \"./calendars/DaylightSavingsLibrary.sol\";\nimport {Initializable} from \"openzeppelin-upgradeable/proxy/utils/Initializable.sol\";\nimport {Ownable} from \"../entitlements/Ownable.sol\";\nimport {Math} from \"openzeppelin/utils/math/Math.sol\";\nimport {SafeERC20} from \"openzeppelin/token/ERC20/utils/SafeERC20.sol\";\nimport {UUPSUpgradeable} from \"openzeppelin/proxy/utils/UUPSUpgradeable.sol\";\n\n// interfaces\nimport {IToken} from \"../../interfaces/IToken.sol\";\nimport {IOracle} from \"../../interfaces/IOracle.sol\";\n\nimport \"../../config/constants.sol\";\nimport \"../../config/errors.sol\";\nimport \"../../config/types.sol\";\n\n/**\n * @title   Token Teller 3\n * @author  dsshap (Circle)\n * @dev     Provides liquidity for Share/Asset pair.\n */\ncontract Teller is Access, Initializable, Ownable, UUPSUpgradeable {\n    using DaylightSavingsLibrary for DaylightSavingsCalendar;\n    using Math for uint256;\n    using DateTimeUtil for uint256;\n    using SafeERC20 for IToken;\n\n    /*///////////////////////////////////////////////////////////////\n                        Constants & Immutables\n    //////////////////////////////////////////////////////////////*/\n\n    /// @notice Data contract encoding DST start/end timestamps through 2123.\n    DaylightSavingsCalendar public immutable dst;\n\n    /*///////////////////////////////////////////////////////////////\n                                Events\n    //////////////////////////////////////////////////////////////*/\n\n    event Deposit(address indexed caller, address indexed owner, uint256 assets, uint256 shares);\n    event Withdraw(address indexed caller, address indexed receiver, address indexed owner, uint256 assets, uint256 shares);\n    event Subscribe(address indexed from, address indexed receiver, uint256 assets, uint256 shares, uint256 price, uint256 fee);\n    event Redeem(address indexed from, address indexed receiver, uint256 assets, uint256 shares, uint256 price, uint256 fee);\n    event Approval(address indexed owner, address indexed spender, uint256 amount);\n    event Sweep(address indexed token, address indexed treasury, uint256 amount, address indexed recipient);\n    event FeesSet(address indexed owner, uint256 subscribe, uint256 newSubscribe, uint256 redeem, uint256 newRedeem);\n    event OracleSet(address indexed oracle, address indexed newOracle);\n    event TreasurySet(address indexed owner, address treasury, address newTreasury);\n    event FeeRecipientSet(address indexed feeRecipient, address indexed newFeeRecipient);\n    event AfterHourTradingSet(uint256 afterHourTrading, uint256 newAfterHourTrading);\n    event LimitsSet(address indexed owner, uint256 subscribe, uint256 newSubscribe, uint256 redeem, uint256 newRedeem);\n\n    /*///////////////////////////////////////////////////////////////\n                                Structures\n    //////////////////////////////////////////////////////////////*/\n\n    struct FeeSchedule {\n        uint64 subscribe;\n        uint64 redeem;\n    }\n\n    struct Limit {\n        uint56 subscribe;\n        uint56 redeem;\n    }\n\n    /*///////////////////////////////////////////////////////////////\n                         State Variables V1\n    //////////////////////////////////////////////////////////////*/\n\n    IToken public asset;\n\n    IToken public share;\n\n    IOracle public oracle;\n\n    uint256 private _oracleScale;\n\n    address public feeRecipient;\n\n    /// @notice investor fee schedule\n    mapping(address => FeeSchedule) public feeSchedule;\n\n    /// @notice after hour trading\n    uint256 public afterHourTrading;\n\n    /// @notice allowance for owners USYC to be redeem/withdraw on their behalf\n    mapping(address => mapping(address => uint256)) public allowance;\n\n    /// @notice investor specific treasury\n    mapping(address => address) private _treasury;\n\n    /// @notice investor specific subscription and redemption limits\n    mapping(address => Limit) public limit;\n\n    /// @notice investor subscription amount per day\n    mapping(address => mapping(uint256 => uint256)) public subscription;\n\n    /// @notice investor redemption amount per day\n    mapping(address => mapping(uint256 => uint256)) public redemption;\n\n    /**\n     * @dev This empty reserved space is put in place to allow future versions to add new\n     * variables without shifting down storage in the inheritance chain.\n     */\n    uint256[50] private __gap0;\n\n    /*///////////////////////////////////////////////////////////////\n                Constructor for implementation Contract\n    //////////////////////////////////////////////////////////////*/\n\n    constructor(address _authority, address _dst) Access(_authority) {\n        if (_dst == address(0)) revert BadAddress();\n\n        _disableInitializers();\n\n        dst = DaylightSavingsCalendar(_dst);\n    }\n\n    /*///////////////////////////////////////////////////////////////\n                            Initializer\n    //////////////////////////////////////////////////////////////*/\n\n    function initialize(TellerConfig calldata config) external initializer {\n        __Teller_init(config);\n    }\n\n    function __Teller_init(TellerConfig calldata config) internal onlyInitializing {\n        if (config.owner == address(0)) revert BadAddress();\n        if (config.asset == address(0)) revert BadAddress();\n        if (config.share == address(0)) revert BadAddress();\n        if (config.oracle == address(0)) revert BadAddress();\n        if (config.treasury == address(0)) revert BadAddress();\n        if (config.feeRecipient == address(0)) revert BadAddress();\n\n        _transferOwnership(config.owner);\n\n        asset = IToken(config.asset);\n        share = IToken(config.share);\n\n        if (asset.decimals() != share.decimals()) revert BadDecimals();\n\n        oracle = IOracle(config.oracle);\n        _oracleScale = 10 ** oracle.decimals();\n        _treasury[address(0)] = config.treasury;\n        feeRecipient = config.feeRecipient;\n        feeSchedule[address(0)] = FeeSchedule(config.subscribeFee, config.redeemFee);\n        afterHourTrading = config.afterHourTrading;\n        limit[address(0)] = Limit(config.subscribeLimit, config.redeemLimit);\n    }\n\n    /*//////////////////////////////////////////////////////////////\n                                VAULT ACTIONS\n    //////////////////////////////////////////////////////////////*/\n\n    function _inbound(address account, uint256 assets, uint256 shares, uint256 fee, address receiver) internal virtual {\n        uint256 today = todayTimestamp();\n        uint256 remaining = subscriptionLimitRemaining(account, today);\n        if (remaining < assets) revert LimitExceeded();\n        subscription[account][today] += assets;\n\n        address treasury_ = treasury(account);\n        asset.safeTransferFrom(account, treasury_, assets - fee);\n        if (fee > 0) asset.safeTransferFrom(account, feeRecipient, fee);\n\n        share.mint(receiver, shares);\n    }\n\n    function _deposit(uint256 assets, address receiver, address account) internal virtual returns (uint256 shares) {\n        uint256 fee;\n        int256 price;\n        (shares, fee, price) = previewDepositData(account, assets);\n\n        if (shares == 0) revert ZeroShares();\n\n        _assertPermission(account);\n        _assertCanReceive(address(share), receiver);\n\n        _inbound(account, assets, shares, fee, receiver);\n\n        emit Deposit(account, receiver, assets, shares);\n        emit Subscribe(account, receiver, assets, shares, uint256(price), fee);\n    }\n\n    function deposit(uint256 assets, address receiver) public virtual returns (uint256 shares) {\n        return _deposit(assets, receiver, msg.sender);\n    }\n\n    function depositWithPermit(uint256 assets, address receiver, uint256 deadline, uint8 v, bytes32 r, bytes32 s)\n        public\n        virtual\n        returns (uint256 shares)\n    {\n        return depositWithPermit(assets, receiver, deadline, abi.encodePacked(r, s, v));\n    }\n\n    function depositWithPermit(uint256 assets, address receiver, uint256 deadline, bytes memory signature)\n        public\n        virtual\n        returns (uint256 shares)\n    {\n        asset.permit(receiver, address(this), assets, deadline, signature);\n        return _deposit(assets, receiver, receiver);\n    }\n\n    function mint(uint256 shares, address receiver) public virtual returns (uint256 assets) {\n        uint256 fee;\n        int256 price;\n        (assets, fee, price) = previewMintData(msg.sender, shares);\n\n        if (assets == 0) revert ZeroAssets();\n\n        _assertPermission(msg.sender);\n        _assertCanReceive(address(share), receiver);\n\n        _inbound(msg.sender, assets, shares, fee, receiver);\n\n        emit Deposit(msg.sender, receiver, assets, shares);\n        emit Subscribe(msg.sender, receiver, assets, shares, uint256(price), fee);\n    }\n\n    function _outbound(address account, uint256 assets, uint256 shares, uint256 fee, address receiver) internal virtual {\n        uint256 today = todayTimestamp();\n        uint256 remaining = redemptionLimitRemaining(account, today);\n        if (remaining < assets) revert LimitExceeded();\n        redemption[account][today] += assets;\n\n        share.burn(account, shares);\n\n        address treasury_ = treasury(account);\n        asset.safeTransferFrom(treasury_, receiver, assets);\n        if (fee > 0) asset.safeTransferFrom(treasury_, feeRecipient, fee);\n    }\n\n    function withdraw(uint256 assets, address receiver, address account) public virtual returns (uint256 shares) {\n        uint256 fee;\n        int256 price;\n        (shares, fee, price) = previewWithdrawData(account, assets);\n\n        if (shares == 0) revert ZeroShares();\n\n        _spendAllowance(account, shares);\n        _assertPermission(msg.sender);\n        _assertCanReceive(address(share), account, receiver);\n\n        _outbound(account, assets, shares, fee, receiver);\n\n        emit Withdraw(msg.sender, receiver, account, assets, shares);\n        emit Redeem(account, receiver, assets, shares, uint256(price), fee);\n    }\n\n    function redeem(uint256 shares, address receiver, address account) public virtual returns (uint256 assets) {\n        _spendAllowance(account, shares);\n\n        uint256 fee;\n        int256 price;\n        (assets, fee, price) = previewRedeemData(account, shares);\n\n        if (assets == 0) revert ZeroAssets();\n\n        _assertPermission(msg.sender);\n        _assertCanReceive(address(share), account, receiver);\n\n        _outbound(account, assets, shares, fee, receiver);\n\n        emit Withdraw(msg.sender, receiver, account, assets, shares);\n        emit Redeem(account, receiver, assets, shares, uint256(price), fee);\n    }\n\n    function approve(address spender, uint256 amount) public virtual returns (bool) {\n        _assertPermission(msg.sender);\n\n        allowance[msg.sender][spender] = amount;\n\n        emit Approval(msg.sender, spender, amount);\n\n        return true;\n    }\n\n    /**\n     * @notice Returns treasury for an account\n     * @dev if no treasury set for account then the public treasury is returned\n     *      the public treasury is set at address(0)\n     * @param account address of investor\n     * @return treasuryAddr address of treasury\n     */\n    function treasury(address account) public view virtual returns (address treasuryAddr) {\n        if ((treasuryAddr = _treasury[account]) == address(0)) treasuryAddr = _treasury[address(0)];\n    }\n\n    /*//////////////////////////////////////////////////////////////\n                                ACCOUNTING\n    //////////////////////////////////////////////////////////////*/\n\n    /**\n     * @notice Returns assets available for redemptions\n     * @dev if called offchain this returns public assets available for redemptions\n     *      if called onchain this returns the assets available for redemptions by msg.sender\n     * @return assets available for redemptions\n     */\n    function totalAssets() public view virtual returns (uint256) {\n        return totalAssets(msg.sender);\n    }\n\n    /**\n     * @notice Returns assets available for redemptions by account\n     * @dev returns which ever is lowest: the balance of the asset in the treasury or the allowance\n     *      the public treasury is set at address(0)\n     * @param account address of investor\n     * @return assets available for redemptions\n     */\n    function totalAssets(address account) public view virtual returns (uint256) {\n        return asset.balanceOf(treasury(account)).min(asset.allowance(treasury(account), address(this)));\n    }\n\n    /**\n     * @notice Returns the current price for minting USYC\n     * @dev The price is in oracle decimals\n     * @return price the price from the oracle\n     */\n    function mintPrice() public view virtual returns (int256 price) {\n        // current price in terms of USD\n        uint256 updatedAt;\n        (, price,, updatedAt,) = oracle.latestRoundData();\n\n        uint256 afterHour = afterHourTrading;\n        if (afterHour == AFTER_HOURS_DISABLED) return price;\n\n        uint256 afterHourH = afterHour / 100;\n        uint256 afterHourM = afterHour % 100;\n\n        uint256 currentTime = _eT(block.timestamp);\n        (uint256 updatedY, uint256 updatedM, uint256 updatedD) = _eT(updatedAt).timestampToDate();\n        (uint256 nowY, uint256 nowM, uint256 nowD) = currentTime.timestampToDate();\n\n        // if price was not updated today OR in after hour trading, then use next price\n        if (\n            updatedY != nowY || updatedM != nowM || updatedD != nowD || currentTime.getHour() > afterHourH\n                || (currentTime.getHour() == afterHourH && currentTime.getMinute() >= afterHourM)\n        ) {\n            price = oracle.nextPrice();\n        }\n    }\n\n    function convertToShares(uint256 assets) public view virtual returns (uint256 shares) {\n        shares = assets.mulDiv(_oracleScale, uint256(mintPrice()));\n    }\n\n    function convertToAssets(uint256 shares) public view virtual returns (uint256 assets) {\n        (, int256 price,,,) = oracle.latestRoundData();\n        assets = shares.mulDiv(uint256(price), _oracleScale);\n    }\n\n    /**\n     * @notice Gets the subscription fee rate\n     * @dev If individual account rate is not set (aka 0) then uses default rate\n     *      If rate is set to type(uint64).max, then fee rate is 0\n     * @return rate the rate to be charged\n     */\n    function subscriptionFeeRate(address account) public view virtual returns (uint256 rate) {\n        if ((rate = feeSchedule[account].subscribe) == 0) rate = feeSchedule[address(0)].subscribe;\n        else if (rate == type(uint64).max) return 0;\n    }\n\n    /**\n     * @notice Gets the redemption fee rate\n     * @dev If individual account rate is not set (aka 0) then uses default rate\n     *      If rate is set to type(uint64).max, then fee rate is 0\n     * @return rate the rate to be charged\n     */\n    function redemptionFeeRate(address account) public view virtual returns (uint256 rate) {\n        if ((rate = feeSchedule[account].redeem) == 0) rate = feeSchedule[address(0)].redeem;\n        else if (rate == type(uint64).max) return 0;\n    }\n\n    /**\n     * @notice Gets the remaining subscription amount\n     * @dev If individual limit is not set (aka 0) then uses default rate\n     * @return assets the amount of assets that can be subscribed\n     */\n    function subscriptionLimitRemaining(address account, uint256 date) public view virtual returns (uint256 assets) {\n        if ((assets = limit[account].subscribe) == 0) assets = limit[address(0)].subscribe;\n        uint256 current = subscription[account][date];\n        if (current > assets) return 0; // if subscription limit was reduced during the day to less than current\n        else return assets - current;\n    }\n\n    /**\n     * @notice Gets the remaining redemption amount\n     * @dev If individual limit is not set (aka 0) then uses default rate\n     * @return assets the amount of assets that can be redeemed\n     */\n    function redemptionLimitRemaining(address account, uint256 date) public view virtual returns (uint256 assets) {\n        if ((assets = limit[account].redeem) == 0) assets = limit[address(0)].redeem;\n        uint256 current = redemption[account][date];\n        if (current > assets) return 0; // if redemption limit was reduced during the day to less than current\n        else return assets - current;\n    }\n\n    function previewDepositData(address account, uint256 assets)\n        public\n        view\n        virtual\n        returns (uint256 shares, uint256 fee, int256 price)\n    {\n        fee = subscriptionFeeRate(account);\n        uint256 netAssets = fee > 0 ? assets.mulDiv(HUNDRED_PCT, HUNDRED_PCT + fee) : assets;\n        fee = assets - netAssets;\n\n        price = mintPrice();\n        shares = netAssets.mulDiv(_oracleScale, uint256(price));\n    }\n\n    function previewDeposit(uint256 assets) external view virtual returns (uint256 shares) {\n        (shares,,) = previewDepositData(msg.sender, assets);\n    }\n\n    function previewMintData(address account, uint256 shares)\n        public\n        view\n        virtual\n        returns (uint256 assets, uint256 fee, int256 price)\n    {\n        price = mintPrice();\n        assets = shares.mulDiv(uint256(price), _oracleScale, Math.Rounding.Up);\n        fee = assets.mulDiv(subscriptionFeeRate(account), HUNDRED_PCT, Math.Rounding.Up);\n        assets += fee;\n    }\n\n    function previewMint(uint256 shares) external view virtual returns (uint256 assets) {\n        (assets,,) = previewMintData(msg.sender, shares);\n    }\n\n    function previewWithdrawData(address account, uint256 assets)\n        public\n        view\n        virtual\n        returns (uint256 shares, uint256 fee, int256 price)\n    {\n        fee = assets.mulDiv(redemptionFeeRate(account), HUNDRED_PCT, Math.Rounding.Up);\n        assets += fee;\n        (, price,,,) = oracle.latestRoundData();\n        shares = assets.mulDiv(_oracleScale, uint256(price), Math.Rounding.Up);\n    }\n\n    function previewWithdraw(uint256 assets) external view virtual returns (uint256 shares) {\n        (shares,,) = previewWithdrawData(msg.sender, assets);\n    }\n\n    function previewRedeemData(address account, uint256 shares)\n        public\n        view\n        virtual\n        returns (uint256 assets, uint256 fee, int256 price)\n    {\n        (, price,,,) = oracle.latestRoundData();\n        assets = shares.mulDiv(uint256(price), _oracleScale);\n\n        fee = redemptionFeeRate(account);\n        uint256 netAssets = fee > 0 ? assets.mulDiv(HUNDRED_PCT, HUNDRED_PCT + fee) : assets;\n        fee = assets - netAssets;\n\n        assets -= fee;\n    }\n\n    function previewRedeem(uint256 shares) external view virtual returns (uint256 assets) {\n        (assets,,) = previewRedeemData(msg.sender, shares);\n    }\n\n    /*//////////////////////////////////////////////////////////////\n                                MAXIMUMS\n    //////////////////////////////////////////////////////////////*/\n\n    function maxDeposit(address account) public view virtual returns (uint256 maxAssets) {\n        return asset.balanceOf(account).min(subscriptionLimitRemaining(account, todayTimestamp()));\n    }\n\n    function maxMint(address account) public view virtual returns (uint256 maxShares) {\n        return convertToShares(maxDeposit(account));\n    }\n\n    function maxWithdraw(address account) public view virtual returns (uint256 maxAssets) {\n        maxAssets = convertToAssets(share.balanceOf(account));\n        uint256 totalAssets_ = totalAssets(account).min(redemptionLimitRemaining(account, todayTimestamp()));\n        if (maxAssets > totalAssets_) maxAssets = totalAssets_;\n    }\n\n    function maxRedeem(address account) public view virtual returns (uint256 maxShares) {\n        (, int256 price,,,) = oracle.latestRoundData();\n        maxShares =\n            totalAssets(account).min(redemptionLimitRemaining(account, todayTimestamp())).mulDiv(_oracleScale, uint256(price));\n        uint256 totalShares = share.balanceOf(account);\n        if (maxShares > totalShares) maxShares = totalShares;\n    }\n\n    /*///////////////////////////////////////////////////////////////\n                        LIQUIDITY MANAGEMENT\n    //////////////////////////////////////////////////////////////*/\n\n    /**\n     * @notice Sweep tokens from teller to recipient\n     * @param token is the address of the token to transfer\n     * @param account is the address of the account tied to a treasury\n     * @param amount is the amount of token to transfer\n     * @param recipient is the address to send token to\n     */\n    function sweep(address token, address account, uint256 amount, address recipient) external virtual {\n        if (amount == 0) revert BadAmount();\n\n        _assertFundAdmin();\n\n        if (!authority.doesUserHaveRole(recipient, ROLE_RESERVES)) revert NotPermissioned();\n\n        address treasury_ = account == address(this) ? address(this) : treasury(account);\n\n        if (treasury_ == address(this)) IToken(token).safeTransfer(recipient, amount);\n        else IToken(token).safeTransferFrom(treasury_, recipient, amount);\n\n        emit Sweep(token, treasury_, amount, recipient);\n    }\n\n    /*///////////////////////////////////////////////////////////////\n                    DST & Time Conversion Functions\n    //////////////////////////////////////////////////////////////*/\n\n    /**\n     * @notice Returns timestamp at the start of the day (UTC)\n     * @dev Capturing the timestamp at the start of UTC day.\n     *      We get the timestamp then get the date from `timestampToDate`,\n     *      then we get the timestamp of that date from `timestampFromDate`,\n     */\n    function todayTimestamp() public view returns (uint256) {\n        (uint256 year, uint256 month, uint256 day) = block.timestamp.timestampToDate();\n        return DateTimeUtil.timestampFromDate(year, month, day);\n    }\n\n    /**\n     * @notice Return true if it's Daylight Savings Time in New York\n     */\n    function isDST() public view virtual returns (bool) {\n        // The DST calendar stores exact timestamps for start/end of DST in New York\n        uint256 year = block.timestamp.getYear();\n        (uint256 start, uint256 end) = dst.getTimestamps(year);\n        return block.timestamp >= start && block.timestamp < end;\n    }\n\n    /**\n     * @notice Return time in New York\n     */\n    function _eT(uint256 timestamp) internal view virtual returns (uint256) {\n        // Adjusts datetime to US Eastern Time\n        return timestamp - _etOffset();\n    }\n\n    /**\n     * @notice Return timezone offset in New York\n     * @dev ensure applied to UTC timestamp\n     */\n    function _etOffset() internal view virtual returns (uint256) {\n        return isDST() ? 4 hours : 5 hours;\n    }\n\n    /*///////////////////////////////////////////////////////////////\n                        Internal Functions\n    //////////////////////////////////////////////////////////////*/\n\n    function _spendAllowance(address account, uint256 shares) internal {\n        if (msg.sender != account && !_isFundAdmin()) {\n            uint256 allowed = allowance[account][msg.sender];\n\n            if (allowed != type(uint256).max) allowance[account][msg.sender] = allowed - shares;\n        }\n    }\n\n    /*///////////////////////////////////////////////////////////////\n                            Admin Functions\n    //////////////////////////////////////////////////////////////*/\n\n    /**\n     * @notice Sets oracle address\n     * @param _oracle address of oracle\n     */\n    function setOracle(address _oracle) external {\n        _assertFundAdmin();\n\n        if (_oracle == address(0)) revert BadAddress();\n\n        emit OracleSet(address(oracle), _oracle);\n\n        oracle = IOracle(_oracle);\n        _oracleScale = 10 ** oracle.decimals();\n    }\n\n    /**\n     * @notice Sets treasury address\n     * @param account address of account\n     * @param treasuryAddr address of treasury\n     */\n    function setTreasury(address account, address treasuryAddr) external {\n        _assertFundAdmin();\n\n        emit TreasurySet(account, _treasury[account], treasuryAddr);\n\n        _treasury[account] = treasuryAddr;\n    }\n\n    /**\n     * @notice Sets fee recipient address\n     * @param _feeRecipient address of recipient\n     */\n    function setFeeRecipient(address _feeRecipient) external {\n        _assertFundAdmin();\n\n        if (_feeRecipient == address(0)) revert BadAddress();\n\n        emit FeeRecipientSet(feeRecipient, _feeRecipient);\n\n        feeRecipient = _feeRecipient;\n    }\n\n    /**\n     * @notice Sets fees for subscribing and redeeming\n     * @dev fees are in bps, 18 decimals, max fee is 2.5%\n     *      to set default fees, use address(0) for _account\n     * @param _account address of account\n     * @param _subscribe fees for subscribing\n     * @param _redeem fees for redeeming\n     */\n    function setFees(address _account, uint64 _subscribe, uint64 _redeem) external {\n        _assertFundAdmin();\n\n        FeeSchedule memory schedule = feeSchedule[_account];\n\n        emit FeesSet(_account, schedule.subscribe, _subscribe, schedule.redeem, _redeem);\n\n        feeSchedule[_account] = FeeSchedule(_subscribe, _redeem);\n    }\n\n    /**\n     * @notice Sets limits for subscribing and redeeming\n     * @dev limits are in terms of asset\n     *      to set default limit, use address(0) for _account\n     * @param _account address of account\n     * @param _subscribe limit for subscribing\n     * @param _redeem limit for redeeming\n     */\n    function setLimits(address _account, uint56 _subscribe, uint56 _redeem) external {\n        _assertFundAdmin();\n\n        Limit memory limit_ = limit[_account];\n\n        emit LimitsSet(_account, limit_.subscribe, _subscribe, limit_.redeem, _redeem);\n\n        limit[_account] = Limit(_subscribe, _redeem);\n    }\n\n    /**\n     * @notice Sets after hours trading\n     * @dev value set as hhmm in 24h format, e.g. 1700 for 5pm\n     * if value is type(uint256).max, then turns off after hour pricing\n     * @param hourMinute hour and minute\n     */\n    function setAfterHourTrading(uint256 hourMinute) external {\n        _assertFundAdmin();\n\n        if (hourMinute != AFTER_HOURS_DISABLED) if (hourMinute / 100 > 23 || hourMinute % 100 > 59) revert BadTime();\n\n        emit AfterHourTradingSet(afterHourTrading, hourMinute);\n\n        afterHourTrading = hourMinute;\n    }\n\n    /*///////////////////////////////////////////////////////////////\n                        Override Upgrade Permission\n    //////////////////////////////////////////////////////////////*/\n\n    /**\n     * @dev Upgradable by the owner.\n     *\n     */\n    function _authorizeUpgrade(\n        address /*newImplementation*/\n    )\n        internal\n        virtual\n        override\n    {\n        _assertOwner();\n    }\n}\n"},{"file_path":"src/core/tellers/calendars/DaylightSavingsCalendar.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.15;\n\n/// @notice Data contract encoding Daylight Savings start/end timestamps.\n///         Each start/end pair is encoded as two 32-bit values, representing\n///         seconds since Jan 1, 2023 UTC. Use DaylightSavingsLibrary to decode.\n/// @author horsefacts (https://github.com/horsefacts/trading-days/blob/main/src/calendars/DaylightSavingsCalendar.sol)\ncontract DaylightSavingsCalendar {\n    constructor() {\n        bytes memory data = (\n            hex\"00\" // STOP opcode\n            hex\"005cab7001967070023c8d7003765270041c6f700556347005fc517007361670\"\n            hex\"07e56df0091f32f009c54ff00aff14f00ba531f00cdef6f00d8513f00ebed8f0\"\n            hex\"0f64f5f0109ebaf0114e12701287d770132df4701467b970150dd67016479b70\"\n            hex\"16edb87018277d7018cd9a701a075f701aad7c701be741701c9698f01dd05df0\"\n            hex\"1e767af01fb03ff020565cf0219021f022363ef0237003f0241620f0254fe5f0\"\n            hex\"25f602f0272fc7f027df1f702918e47029bf01702af8c6702b9ee3702cd8a870\"\n            hex\"2d7ec5702eb88a702f5ea77030986c703147c3f0328188f03327a5f034616af0\"\n            hex\"350787f036414cf036e769f038212ef038c74bf03a0110f03aa72df03be0f2f0\"\n            hex\"3c904a703dca0f703e702c703fa9f17040500e704189d370422ff0704369b570\"\n            hex\"440fd2704549977045f8eef04732b3f047d8d0f0491295f049b8b2f04af277f0\"\n            hex\"4b9894f04cd259f04d7876f04eb23bf04f5858f050921df051417570527b3a70\"\n            hex\"53215770545b1c7055013970563afe7056e11b70581ae07058c0fd7059fac270\"\n            hex\"5aa0df705bdaa4705c89fbf05dc3c0f05e69ddf05fa3a2f06049bff0618384f0\"\n            hex\"6229a1f0636366f0640983f0654348f065f2a070672c657067d28270690c4770\"\n            hex\"69b264706aec29706b9246706ccc0b706d7228706eabed706f520a70708bcf70\"\n            hex\"713b26f07274ebf0731b08f07454cdf074faeaf07634aff076daccf0781491f0\"\n            hex\"78baaef079f473f07aa3cb707bdd90707c83ad707dbd72707e638f707f9d5470\"\n            hex\"80437170817d367082235370835d187084033570853cfa7085ec51f0872616f0\"\n            hex\"87cc33f08905f8f089ac15f08ae5daf08b8bf7f08cc5bcf08d6bd9f08ea59ef0\"\n            hex\"8f4bbbf0908580f09134d870926e9d709314ba70944e7f7094f49c70962e6170\"\n            hex\"96d47e70980e437098b4607099ee25709a9442709bce07709c7d5ef09db723f0\"\n            hex\"9e5d40f09f9705f0a03d22f0a176e7f0a21d04f0a356c9f0a3fce6f0a536abf0\"\n            hex\"a5dcc8f0a7168df0a7c5e570a8ffaa70a9a5c770aadf8c70ab85a970acbf6e70\"\n            hex\"ad658b70ae9f5070af456d70b07f3270b12e89f0b2684ef0b30e6bf0b44830f0\"\n            hex\"b4ee4df0b62812f0b6ce2ff0b807f4f0b8ae11f0b9e7d6f0ba8df3f0bbc7b8f0\"\n            hex\"bc771070bdb0d570\"\n        );\n        assembly {\n            return(add(data, 0x20), mload(data))\n        }\n    }\n}\n"},{"file_path":"src/core/tellers/calendars/DaylightSavingsLibrary.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.15;\n\nimport {DaylightSavingsCalendar} from \"./DaylightSavingsCalendar.sol\";\n\n/// @author horsefacts (https://github.com/horsefacts/trading-days/blob/main/src/calendars/DaylightSavingsLibrary.sol)\nlibrary DaylightSavingsLibrary {\n    /// @notice DaylightSavingsLibrary supports 100 years, from 2023 to 2123.\n    ///         Years outside this range revert with this error.\n    error YearNotFound();\n\n    /// @dev Timestamps are stored as seconds since Jan 1, 2023 UTC.\n    uint256 private constant EPOCH_START = 1672531200;\n\n    /// @dev Size of the leading STOP opcode byte in the data contract.\n    uint256 private constant STOP_BYTE = 0x1;\n\n    /// @dev Width of one encoded timestamp pair.\n    uint256 private constant ONE_PAIR = 0x8;\n\n    /// @dev Offset copied bytes by 24 bytes, so the 8 byte encoded pair\n    ///      is laid out at the end of a 32-byte word in scratch space.\n    uint256 private constant COPY_OFFSET = 0x18;\n\n    /// @dev Alias for scratch space memory address.\n    uint256 private constant SCRATCH_SPACE = 0x0;\n\n    /// @dev Width of one encoded date in bits.\n    uint256 private constant DATE_BIT_WIDTH = 32;\n\n    /// @dev Mask to extract upper 32 bits from an encoded pair.\n    uint256 private constant START_BIT_MASK = 0xffffffff00000000;\n\n    /// @dev Mask to extract lower 32 bits from an encoded pair.\n    uint256 private constant END_BIT_MASK = 0xffffffff;\n\n    function getTimestamps(DaylightSavingsCalendar dst, uint256 year) internal view returns (uint256 start, uint256 end) {\n        if (year < 2023 || year > 2123) revert YearNotFound();\n\n        assembly (\"memory-safe\") {\n            extcodecopy(dst, COPY_OFFSET, add(STOP_BYTE, mul(sub(year, 2023), ONE_PAIR)), ONE_PAIR)\n            let pair := mload(SCRATCH_SPACE)\n            start := add(shr(DATE_BIT_WIDTH, and(pair, START_BIT_MASK)), EPOCH_START)\n            end := add(and(pair, END_BIT_MASK), EPOCH_START)\n        }\n    }\n}\n"},{"file_path":"src/interfaces/IAggregatorV3.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/// @author Modified from smartcontractkit (https://github.com/smartcontractkit/chainlink/blob/develop/contracts/src/v0.8/shared/interfaces/AggregatorV3Interface.sol)\ninterface IAggregatorV3 {\n    function decimals() external view returns (uint8);\n\n    function description() external view returns (string memory);\n\n    function version() external view returns (uint256);\n\n    // getRoundData and latestRoundData should both raise \"No data present\"\n    // if they do not have data to report, instead of returning unset values\n    // which could be misinterpreted as actual reported values.\n    function getRoundData(uint80 _roundId)\n        external\n        view\n        returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound);\n\n    function latestRoundData()\n        external\n        view\n        returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound);\n\n    function latestRound() external view returns (uint256);\n\n    function transmit(uint256 _answer, uint256 _updatedAt) external returns (uint80 roundId);\n}\n"},{"file_path":"src/interfaces/IAuthority.sol","source_code":"/**\n * Copyright 2025 Circle Internet Group, Inc. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npragma solidity ^0.8.0;\n\ninterface IAuthority {\n    function canCall(address user, address target, bytes4 functionSig) external view returns (bool);\n    function doesUserHaveRole(address user, uint8 role) external view returns (bool);\n    function getUserRoles(address user) external view returns (bytes32);\n}\n"},{"file_path":"src/interfaces/IOracle.sol","source_code":"/**\n * Copyright 2025 Circle Internet Group, Inc. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npragma solidity ^0.8.0;\n\nimport {IAggregatorV3} from \"./IAggregatorV3.sol\";\n\ninterface IOracle is IAggregatorV3 {\n    function getRoundDetails(uint80)\n        external\n        view\n        returns (uint80 roundId, uint256 balance, uint256 interest, uint256 totalSupply, uint256 updatedAt);\n\n    function latestRoundDetails()\n        external\n        view\n        returns (uint80 roundId, uint256 balance, uint256 interest, uint256 totalSupply, uint256 updatedAt);\n\n    function nextPrice() external view returns (int256);\n}\n"},{"file_path":"src/interfaces/IToken.sol","source_code":"/**\n * Copyright 2025 Circle Internet Group, Inc. All rights reserved.\n *\n * SPDX-License-Identifier: Apache-2.0\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n *     http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\npragma solidity ^0.8.0;\n\nimport {IERC20Metadata} from \"openzeppelin/token/ERC20/extensions/IERC20Metadata.sol\";\n\ninterface IToken is IERC20Metadata {\n    function permit(address owner, address spender, uint256 value, uint256 deadline, bytes memory signature) external;\n    function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external;\n    function mint(address _to, uint256 _amount) external returns (bool);\n    function burn(uint256 _amount) external;\n    function burn(address _from, uint256 _amount) external;\n}\n"}],"certified":false,"conflicting_implementations":null,"abi":[{"inputs":[{"internalType":"address","name":"_authority","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"BadAddress","type":"error"},{"inputs":[],"name":"NoAccess","type":"error"},{"inputs":[],"name":"NotPermissioned","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"previousAdmin","type":"address"},{"indexed":false,"internalType":"address","name":"newAdmin","type":"address"}],"name":"AdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"beacon","type":"address"}],"name":"BeaconUpgraded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Deposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"fee","type":"uint256"}],"name":"FeeProcessed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"address","name":"newRecipient","type":"address"}],"name":"FeeRecipientSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint8","name":"version","type":"uint8"}],"name":"Initialized","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"managementFee","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newManagementFee","type":"uint256"}],"name":"ManagementFeeSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"minter","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"MinterConfigured","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oracle","type":"address"},{"indexed":false,"internalType":"address","name":"newOracle","type":"address"}],"name":"OracleSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Sweep","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"teller","type":"address"},{"indexed":false,"internalType":"address","name":"newTeller","type":"address"}],"name":"TellerSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"TradeToFiat","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"token","type":"address"}],"name":"UnderlyingSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"implementation","type":"address"}],"name":"Upgraded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Withdrawal","type":"event"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acceptOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"authority","outputs":[{"internalType":"contract RolesAuthority","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"burnFor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_minter","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"decrementMinterAllowance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_minter","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"incrementMinterAllowance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_symbol","type":"string"},{"internalType":"uint8","name":"_dec","type":"uint8"},{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_minter","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"mint","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"minterAllowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"proxiableUUID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_minter","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"setMinterAllowance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"address","name":"_recipient","type":"address"}],"name":"sweep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_from","type":"address"},{"internalType":"address","name":"_to","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"}],"name":"upgradeTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newImplementation","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"upgradeToAndCall","outputs":[],"stateMutability":"payable","type":"function"}],"is_changed_bytecode":false,"is_partially_verified":false,"constructor_args":"0x000000000000000000000000902d906b8d988092213be799b18bd2cbd64f808c"}