{"file_path":"src/spoke/ShareToken.sol","creation_status":"success","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.28;\n\nimport {IShareToken, IERC1404} from \"./interfaces/IShareToken.sol\";\n\nimport {ERC20} from \"../misc/ERC20.sol\";\nimport {IERC20} from \"../misc/interfaces/IERC20.sol\";\nimport {MathLib} from \"../misc/libraries/MathLib.sol\";\nimport {IERC7575Share, IERC165} from \"../misc/interfaces/IERC7575.sol\";\n\nimport {\n    ITransferHook,\n    HookData,\n    SUCCESS_CODE_ID,\n    SUCCESS_MESSAGE,\n    ERROR_CODE_ID,\n    ERROR_MESSAGE\n} from \"../common/interfaces/ITransferHook.sol\";\n\n/// @title  Share Token\n/// @notice Extension of ERC20 + ERC1404,\n///         integrating an external hook optionally for ERC20 callbacks and ERC1404 checks.\ncontract ShareToken is ERC20, IShareToken {\n    using MathLib for uint256;\n\n    address public hook;\n    mapping(address => Balance) private balances;\n    mapping(address asset => address) public vault;\n\n    constructor(uint8 decimals_) ERC20(decimals_) {}\n\n    modifier authOrHook() {\n        require(wards[msg.sender] == 1 || msg.sender == hook, NotAuthorizedOrHook());\n        _;\n    }\n\n    //----------------------------------------------------------------------------------------------\n    // Administration\n    //----------------------------------------------------------------------------------------------\n\n    /// @inheritdoc IShareToken\n    function file(bytes32 what, address data) external auth {\n        if (what == \"hook\") hook = data;\n        else revert FileUnrecognizedParam();\n        emit File(what, data);\n    }\n\n    /// @inheritdoc IShareToken\n    function file(bytes32 what, string memory data) public override(ERC20, IShareToken) auth {\n        super.file(what, data);\n    }\n\n    /// @inheritdoc IShareToken\n    function updateVault(address asset, address vault_) external auth {\n        vault[asset] = vault_;\n        emit VaultUpdate(asset, vault_);\n    }\n\n    //----------------------------------------------------------------------------------------------\n    // ERC-20 overrides\n    //----------------------------------------------------------------------------------------------\n\n    function _balanceOf(address user) internal view override returns (uint256) {\n        return balances[user].amount;\n    }\n\n    function _setBalance(address user, uint256 value) internal override {\n        balances[user].amount = value.toUint128();\n    }\n\n    /// @inheritdoc IShareToken\n    function hookDataOf(address user) public view returns (bytes16) {\n        return balances[user].hookData;\n    }\n\n    /// @inheritdoc IShareToken\n    function setHookData(address user, bytes16 hookData) public authOrHook {\n        balances[user].hookData = hookData;\n        emit SetHookData(user, hookData);\n    }\n\n    /// @inheritdoc IERC20\n    function transfer(address to, uint256 value) public override(ERC20, IERC20) returns (bool success) {\n        success = super.transfer(to, value);\n        _onTransfer(msg.sender, to, value);\n    }\n\n    /// @inheritdoc IERC20\n    function transferFrom(address from, address to, uint256 value)\n        public\n        override(ERC20, IERC20)\n        returns (bool success)\n    {\n        success = super.transferFrom(from, to, value);\n        _onTransfer(from, to, value);\n    }\n\n    /// @inheritdoc IShareToken\n    function mint(address to, uint256 value) public override(ERC20, IShareToken) {\n        super.mint(to, value);\n        require(totalSupply <= type(uint128).max, ExceedsMaxSupply());\n        _onTransfer(address(0), to, value);\n    }\n\n    /// @inheritdoc IShareToken\n    function burn(address from, uint256 value) public override(ERC20, IShareToken) {\n        super.burn(from, value);\n        _onTransfer(from, address(0), value);\n    }\n\n    function _onTransfer(address from, address to, uint256 value) internal {\n        address hook_ = hook;\n        require(\n            hook_ == address(0)\n                || ITransferHook(hook_).onERC20Transfer(from, to, value, HookData(hookDataOf(from), hookDataOf(to)))\n                    == ITransferHook.onERC20Transfer.selector,\n            RestrictionsFailed()\n        );\n    }\n\n    /// @inheritdoc IShareToken\n    function authTransferFrom(address sender, address from, address to, uint256 value)\n        public\n        auth\n        returns (bool success)\n    {\n        success = _transferFrom(sender, from, to, value);\n        address hook_ = hook;\n        if (hook_ != address(0)) {\n            ITransferHook(hook_).onERC20AuthTransfer(\n                sender, from, to, value, HookData(hookDataOf(from), hookDataOf(to))\n            );\n        }\n    }\n\n    //----------------------------------------------------------------------------------------------\n    // ERC-1404\n    //----------------------------------------------------------------------------------------------\n\n    /// @inheritdoc IShareToken\n    function checkTransferRestriction(address from, address to, uint256 value) public view returns (bool) {\n        return detectTransferRestriction(from, to, value) == SUCCESS_CODE_ID;\n    }\n\n    /// @inheritdoc IERC1404\n    function detectTransferRestriction(address from, address to, uint256 value) public view returns (uint8) {\n        address hook_ = hook;\n        if (hook_ == address(0)) return SUCCESS_CODE_ID;\n        return ITransferHook(hook_).checkERC20Transfer(from, to, value, HookData(hookDataOf(from), hookDataOf(to)))\n            ? SUCCESS_CODE_ID\n            : ERROR_CODE_ID;\n    }\n\n    /// @inheritdoc IERC1404\n    function messageForTransferRestriction(uint8 restrictionCode) external pure returns (string memory) {\n        return restrictionCode == SUCCESS_CODE_ID ? SUCCESS_MESSAGE : ERROR_MESSAGE;\n    }\n\n    //----------------------------------------------------------------------------------------------\n    // ERC-165\n    //----------------------------------------------------------------------------------------------\n\n    /// @inheritdoc IERC165\n    function supportsInterface(bytes4 interfaceId) external pure override returns (bool) {\n        return interfaceId == type(IERC7575Share).interfaceId || interfaceId == type(IERC165).interfaceId;\n    }\n}\n","deployed_bytecode":"0x608060405234801561000f575f5ffd5b506004361061017e575f3560e01c806301ffc9a71461018257806306fdde03146101aa578063095ea7b3146101bf578063097ac46e146101d257806318160ddd146101e75780631b451d28146101fe57806323b872dd1461021157806330adf81f14610224578063313ce567146102385780633644e5151461027157806340c10f191461027957806365fae35e1461028c5780636a9154aa1461029f57806370a08231146102b25780637ecebe00146102c55780637f4ab1dd146102e45780637f5a7c7b146102f7578063887ca2491461031757806395d89b411461032a5780639c52a7f1146103325780639dc29fac146103455780639fd5a6cf14610358578063a9059cbb1461036b578063bf353dbb1461037e578063cd0d00961461039d578063d4ce1415146103c4578063d4e8be83146103d7578063d505accf146103ea578063dd62ed3e146103fd578063e8e6dc7514610427578063f815c03d14610447578063fa1e71301461046f575b5f5ffd5b610195610190366004611694565b610482565b60405190151581526020015b60405180910390f35b6101b26104b8565b6040516101a191906116dd565b6101956101cd36600461170a565b610544565b6101e56101e03660046117bb565b61059c565b005b6101f060035481565b6040519081526020016101a1565b6101e561020c366004611811565b6105d9565b61019561021f366004611842565b610673565b6101f05f516020611cd85f395f51905f5281565b61025f7f000000000000000000000000000000000000000000000000000000000000001281565b60405160ff90911681526020016101a1565b6101f0610693565b6101e561028736600461170a565b610784565b6101e561029a36600461187c565b6107c3565b6101e56102ad366004611895565b610836565b6101f06102c036600461187c565b6108da565b6101f06102d336600461187c565b60066020525f908152604090205481565b6101b26102f23660046118e6565b6108e4565b60075461030a906001600160a01b031681565b6040516101a191906118ff565b610195610325366004611913565b610949565b6101b2610a54565b6101e561034036600461187c565b610a61565b6101e561035336600461170a565b610ad3565b6101e561036636600461195b565b610ae8565b61019561037936600461170a565b610c49565b6101f061038c36600461187c565b5f6020819052908152604090205481565b6101f07f000000000000000000000000000000000000000000000000000000000000000181565b61025f6103d2366004611842565b610c61565b6101e56103e53660046119da565b610d40565b6101e56103f83660046119fb565b610de6565b6101f061040b366004611811565b600560209081525f928352604080842090915290825290205481565b61043a61043536600461187c565b610e3d565b6040516101a19190611a61565b61030a61045536600461187c565b60096020525f90815260409020546001600160a01b031681565b61019561047d366004611842565b610e61565b5f6001600160e01b0319821663f815c03d60e01b14806104b257506001600160e01b031982166301ffc9a760e01b145b92915050565b600180546104c590611a76565b80601f01602080910402602001604051908101604052809291908181526020018280546104f190611a76565b801561053c5780601f106105135761010080835404028352916020019161053c565b820191905f5260205f20905b81548152906001019060200180831161051f57829003601f168201915b505050505081565b335f8181526005602090815260408083206001600160a01b038716808552925280832085905551919290915f516020611cf85f395f51905f529061058b9086815260200190565b60405180910390a350600192915050565b335f908152602081905260409020546001146105cb5760405163ea8e4eb560e01b815260040160405180910390fd5b6105d58282610e7a565b5050565b335f908152602081905260409020546001146106085760405163ea8e4eb560e01b815260040160405180910390fd5b6001600160a01b038281165f818152600960205260409081902080546001600160a01b0319169385169390931790925590517fd8c6b8f6ca4977137bd0c05f8e49099e0bbbefe5ed3010bf828a76dbab958313906106679084906118ff565b60405180910390a25050565b5f61067f848484610f15565b905061068c848484610f2a565b9392505050565b5f7f0000000000000000000000000000000000000000000000000000000000000001461461075f5750604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6020808301919091527fe416b338a274162320c79445ae6604141d1cb08275eb27011b69f002dc094d05828401527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b507f06097c406baba09362148661ecb06244443469afa99c787262c2f8582459d2fa90565b61078e828261102d565b6003546001600160801b0310156107b85760405163c30436e960e01b815260040160405180910390fd5b6105d55f8383610f2a565b335f908152602081905260409020546001146107f25760405163ea8e4eb560e01b815260040160405180910390fd5b6001600160a01b0381165f8181526020819052604080822060019055517fdd0e34038ac38b2a1ce960229778ac48a8719bc900b6c4f8d0475c6e8b385a609190a250565b335f908152602081905260409020546001148061085d57506007546001600160a01b031633145b61087a57604051632d03803360e11b815260040160405180910390fd5b6001600160a01b0382165f818152600860205260409081902080546001600160801b0316600160801b608086901c02179055517f8fa29948e0a84e3c738d2e921e65fab6e5a02291fe898fd94d60c3c8ee614c4590610667908490611a61565b5f6104b2826110f5565b606060ff82161561091d576040518060400160405280601081526020016f1d1c985b9cd9995c8b589b1bd8dad95960821b8152506104b2565b505060408051808201909152601081526f1d1c985b9cd9995c8b585b1b1bddd95960821b602082015290565b335f908152602081905260408120546001146109785760405163ea8e4eb560e01b815260040160405180910390fd5b61098485858585611118565b6007549091506001600160a01b03168015610a4b57806001600160a01b031663078d18cd8787878760405180604001604052806109c08d610e3d565b6001600160801b03191681526020016109d88c610e3d565b6001600160801b03191690526040516001600160e01b031960e088901b168152610a09959493929190600401611aca565b6020604051808303815f875af1158015610a25573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a499190611afe565b505b50949350505050565b600280546104c590611a76565b335f90815260208190526040902054600114610a905760405163ea8e4eb560e01b815260040160405180910390fd5b6001600160a01b0381165f81815260208190526040808220829055517f184450df2e323acec0ed3b5c7531b81f9b4cdef7914dfd4c0a4317416bb5251b9190a250565b610add8282611277565b6105d5825f83610f2a565b81421115610b095760405163068568f360e21b815260040160405180910390fd5b6001600160a01b0385165f90815260066020526040812080546001810190915590610b32610693565b604080515f516020611cd85f395f51905f5260208201526001600160a01b03808b169282019290925290881660608201526080810187905260a0810184905260c0810186905260e00160405160208183030381529060405280519060200120604051602001610bb892919061190160f01b81526002810192909252602282015260420190565b604051602081830303815290604052805190602001209050610bdb8782856113a0565b610bf85760405163ddafbaef60e01b815260040160405180910390fd5b6001600160a01b038781165f818152600560209081526040808320948b168084529482529182902089905590518881525f516020611cf85f395f51905f52910160405180910390a350505050505050565b5f610c54838361154f565b90506104b2338484610f2a565b6007545f906001600160a01b031680610c7d575f91505061068c565b806001600160a01b031663ef59bc928686866040518060400160405280610ca38c610e3d565b6001600160801b0319168152602001610cbb8b610e3d565b6001600160801b03191690526040516001600160e01b031960e087901b168152610ceb9493929190600401611b19565b602060405180830381865afa158015610d06573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d2a9190611b45565b610d35576001610d37565b5f5b95945050505050565b335f90815260208190526040902054600114610d6f5760405163ea8e4eb560e01b815260040160405180910390fd5b8163686f6f6b60e01b03610d9d57600780546001600160a01b0319166001600160a01b038316179055610db6565b604051633db0d5b960e01b815260040160405180910390fd5b817f8fef588b5fc1afbf5b2f06c1a435d513f208da2e6704c3d8f0e0ec91167066ba8260405161066791906118ff565b610e3487878787868689604051602001610e2093929190928352602083019190915260f81b6001600160f81b031916604082015260410190565b604051602081830303815290604052610ae8565b50505050505050565b6001600160a01b03165f90815260086020526040902054600160801b900460801b90565b5f80610e6e858585610c61565b60ff1614949350505050565b335f90815260208190526040902054600114610ea95760405163ea8e4eb560e01b815260040160405180910390fd5b81636e616d6560e01b03610ec9576001610ec38282611bb0565b50610ee5565b81651cde5b589bdb60d21b03610d9d576002610ec38282611bb0565b817fe42e0b9a029dc87ccb1029c632e6359090acd0eb032b2b59c811e3ec70160dc68260405161066791906116dd565b5f610f2233858585611118565b949350505050565b6007546001600160a01b031680158061100a5750633f71910e60e01b6001600160e01b031916816001600160a01b0316633f71910e8686866040518060400160405280610f768c610e3d565b6001600160801b0319168152602001610f8e8b610e3d565b6001600160801b03191690526040516001600160e01b031960e087901b168152610fbe9493929190600401611b19565b6020604051808303815f875af1158015610fda573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ffe9190611afe565b6001600160e01b031916145b61102757604051637f31a9dd60e01b815260040160405180910390fd5b50505050565b335f9081526020819052604090205460011461105c5760405163ea8e4eb560e01b815260040160405180910390fd5b6001600160a01b0382161580159061107d57506001600160a01b0382163014155b61109a5760405163e6c4247b60e01b815260040160405180910390fd5b6110ae82826110a8856110f5565b0161160c565b8060035f8282546110bf9190611c6a565b90915550506040518181526001600160a01b038316905f905f516020611cb85f395f51905f529060200160405180910390a35050565b6001600160a01b03165f908152600860205260409020546001600160801b031690565b5f6001600160a01b0383161580159061113a57506001600160a01b0383163014155b6111575760405163e6c4247b60e01b815260040160405180910390fd5b5f611161856108da565b90508281101561118457604051631e9acf1760e31b815260040160405180910390fd5b856001600160a01b0316856001600160a01b031614611217576001600160a01b038086165f908152600560209081526040808320938a16835292905220545f19811461121557838110156111eb576040516313be252b60e01b815260040160405180910390fd5b6001600160a01b038087165f908152600560209081526040808320938b1683529290522084820390555b505b6112238584830361160c565b61123184846110a8876110f5565b836001600160a01b0316856001600160a01b03165f516020611cb85f395f51905f528560405161126391815260200190565b60405180910390a350600195945050505050565b335f908152602081905260409020546001146112a65760405163ea8e4eb560e01b815260040160405180910390fd5b5f6112b0836108da565b9050818110156112d357604051631e9acf1760e31b815260040160405180910390fd5b6001600160a01b0383163314611359576001600160a01b0383165f9081526005602090815260408083203384529091529020545f198114611357578281101561132f576040516313be252b60e01b815260040160405180910390fd5b6001600160a01b0384165f908152600560209081526040808320338452909152902083820390555b505b6113658383830361160c565b6003805483900390556040518281525f906001600160a01b038516905f516020611cb85f395f51905f529060200160405180910390a3505050565b5f6001600160a01b0384166113c857604051632057875960e21b815260040160405180910390fd5b81516041036114605760208281015160408085015160608087015183515f8082529681018086528a9052951a928501839052840183905260808401819052919260019060a0016020604051602081039080840390855afa15801561142e573d5f5f3e3d5ffd5b505050602060405103516001600160a01b0316876001600160a01b03160361145c576001935050505061068c565b5050505b6001600160a01b0384163b1561068c575f5f856001600160a01b0316858560405160240161148f929190611c89565b60408051601f198184030181529181526020820180516001600160e01b0316630b135d3f60e11b179052516114c49190611ca1565b5f60405180830381855afa9150503d805f81146114fc576040519150601f19603f3d011682016040523d82523d5f602084013e611501565b606091505b5091509150818015611514575080516020145b801561154557508051630b135d3f60e11b906115399083016020908101908401611afe565b6001600160e01b031916145b9695505050505050565b5f6001600160a01b0383161580159061157157506001600160a01b0383163014155b61158e5760405163e6c4247b60e01b815260040160405180910390fd5b5f611598336108da565b9050828110156115bb57604051631e9acf1760e31b815260040160405180910390fd5b6115c73384830361160c565b6115d584846110a8876110f5565b6040518381526001600160a01b0385169033905f516020611cb85f395f51905f529060200160405180910390a35060019392505050565b6116158161164f565b6001600160a01b03929092165f90815260086020526040902080546001600160801b0319166001600160801b039093169290921790915550565b5f6001600160801b038211156116785760405163e999826d60e01b815260040160405180910390fd5b5090565b6001600160e01b031981168114611691575f5ffd5b50565b5f602082840312156116a4575f5ffd5b813561068c8161167c565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f61068c60208301846116af565b80356001600160a01b0381168114611705575f5ffd5b919050565b5f5f6040838503121561171b575f5ffd5b611724836116ef565b946020939093013593505050565b634e487b7160e01b5f52604160045260245ffd5b5f806001600160401b0384111561175f5761175f611732565b50604051601f19601f85018116603f011681018181106001600160401b038211171561178d5761178d611732565b6040528381529050808284018510156117a4575f5ffd5b838360208301375f60208583010152509392505050565b5f5f604083850312156117cc575f5ffd5b8235915060208301356001600160401b038111156117e8575f5ffd5b8301601f810185136117f8575f5ffd5b61180785823560208401611746565b9150509250929050565b5f5f60408385031215611822575f5ffd5b61182b836116ef565b9150611839602084016116ef565b90509250929050565b5f5f5f60608486031215611854575f5ffd5b61185d846116ef565b925061186b602085016116ef565b929592945050506040919091013590565b5f6020828403121561188c575f5ffd5b61068c826116ef565b5f5f604083850312156118a6575f5ffd5b6118af836116ef565b915060208301356001600160801b0319811681146118cb575f5ffd5b809150509250929050565b803560ff81168114611705575f5ffd5b5f602082840312156118f6575f5ffd5b61068c826118d6565b6001600160a01b0391909116815260200190565b5f5f5f5f60808587031215611926575f5ffd5b61192f856116ef565b935061193d602086016116ef565b925061194b604086016116ef565b9396929550929360600135925050565b5f5f5f5f5f60a0868803121561196f575f5ffd5b611978866116ef565b9450611986602087016116ef565b9350604086013592506060860135915060808601356001600160401b038111156119ae575f5ffd5b8601601f810188136119be575f5ffd5b6119cd88823560208401611746565b9150509295509295909350565b5f5f604083850312156119eb575f5ffd5b82359150611839602084016116ef565b5f5f5f5f5f5f5f60e0888a031215611a11575f5ffd5b611a1a886116ef565b9650611a28602089016116ef565b95506040880135945060608801359350611a44608089016118d6565b9699959850939692959460a0840135945060c09093013592915050565b6001600160801b031991909116815260200190565b600181811c90821680611a8a57607f821691505b602082108103611aa857634e487b7160e01b5f52602260045260245ffd5b50919050565b80516001600160801b0319908116835260209182015116910152565b6001600160a01b0386811682528581166020830152841660408201526060810183905260c081016115456080830184611aae565b5f60208284031215611b0e575f5ffd5b815161068c8161167c565b6001600160a01b038581168252841660208201526040810183905260a08101610d376060830184611aae565b5f60208284031215611b55575f5ffd5b8151801515811461068c575f5ffd5b601f821115611bab57805f5260205f20601f840160051c81016020851015611b895750805b601f840160051c820191505b81811015611ba8575f8155600101611b95565b50505b505050565b81516001600160401b03811115611bc957611bc9611732565b611bdd81611bd78454611a76565b84611b64565b6020601f821160018114611c0f575f8315611bf85750848201515b5f19600385901b1c1916600184901b178455611ba8565b5f84815260208120601f198516915b82811015611c3e5787850151825560209485019460019092019101611c1e565b5084821015611c5b57868401515f19600387901b60f8161c191681555b50505050600190811b01905550565b808201808211156104b257634e487b7160e01b5f52601160045260245ffd5b828152604060208201525f610f2260408301846116af565b5f82518060208501845e5f92019182525091905056feddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925a26469706673582212204937a01138ea0d8238e3d4651492d5970e5e30f24bee18edb4afee8d0ceb536d64736f6c634300081c0033","optimization_enabled":true,"verified_twin_address_hash":null,"is_verified":true,"compiler_settings":{"evmVersion":"cancun","libraries":{},"metadata":{"appendCBOR":true,"bytecodeHash":"ipfs","useLiteralContent":false},"optimizer":{"enabled":true,"runs":1},"outputSelection":{"*":{"":["*"],"*":["*"]}},"remappings":["forge-std/=lib/forge-std/src/","@chimera/=lib/chimera/src/","createx-forge/=lib/createx-forge/","chimera/=lib/chimera/src/","ds-test/=lib/chimera/lib/forge-std/lib/ds-test/src/"],"viaIR":false},"optimization_runs":1,"sourcify_repo_url":null,"decoded_constructor_args":[["18",{"internalType":"uint8","name":"decimals_","type":"uint8"}]],"compiler_version":"v0.8.28+commit.7893614a","is_verified_via_verifier_alliance":false,"verified_at":"2026-01-14T20:04:23.732166Z","implementations":[],"proxy_type":null,"external_libraries":[],"creation_bytecode":"0x610120604052348015610010575f5ffd5b50604051611f17380380611f1783398101604081905261002f9161015f565b335f81815260208190526040808220600190555183929182917fdd0e34038ac38b2a1ce960229778ac48a8719bc900b6c4f8d0475c6e8b385a609190a25060ff166080908152604080518082018252600a81526943656e7472696675676560b01b6020918201527fe416b338a274162320c79445ae6604141d1cb08275eb27011b69f002dc094d0560a09081528251808401845260018152603160f81b908301527fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc660c08181524660e0819052835186517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f818801528088019190915260608101939093529582019590955230818301528351808203909201825290930190915281519101206101005250610186565b5f6020828403121561016f575f5ffd5b815160ff8116811461017f575f5ffd5b9392505050565b60805160a05160c05160e05161010051611d4d6101ca5f395f61076201525f81816103a2015261069601525f61071101525f6106ec01525f61023d0152611d4d5ff3fe608060405234801561000f575f5ffd5b506004361061017e575f3560e01c806301ffc9a71461018257806306fdde03146101aa578063095ea7b3146101bf578063097ac46e146101d257806318160ddd146101e75780631b451d28146101fe57806323b872dd1461021157806330adf81f14610224578063313ce567146102385780633644e5151461027157806340c10f191461027957806365fae35e1461028c5780636a9154aa1461029f57806370a08231146102b25780637ecebe00146102c55780637f4ab1dd146102e45780637f5a7c7b146102f7578063887ca2491461031757806395d89b411461032a5780639c52a7f1146103325780639dc29fac146103455780639fd5a6cf14610358578063a9059cbb1461036b578063bf353dbb1461037e578063cd0d00961461039d578063d4ce1415146103c4578063d4e8be83146103d7578063d505accf146103ea578063dd62ed3e146103fd578063e8e6dc7514610427578063f815c03d14610447578063fa1e71301461046f575b5f5ffd5b610195610190366004611694565b610482565b60405190151581526020015b60405180910390f35b6101b26104b8565b6040516101a191906116dd565b6101956101cd36600461170a565b610544565b6101e56101e03660046117bb565b61059c565b005b6101f060035481565b6040519081526020016101a1565b6101e561020c366004611811565b6105d9565b61019561021f366004611842565b610673565b6101f05f516020611cd85f395f51905f5281565b61025f7f000000000000000000000000000000000000000000000000000000000000000081565b60405160ff90911681526020016101a1565b6101f0610693565b6101e561028736600461170a565b610784565b6101e561029a36600461187c565b6107c3565b6101e56102ad366004611895565b610836565b6101f06102c036600461187c565b6108da565b6101f06102d336600461187c565b60066020525f908152604090205481565b6101b26102f23660046118e6565b6108e4565b60075461030a906001600160a01b031681565b6040516101a191906118ff565b610195610325366004611913565b610949565b6101b2610a54565b6101e561034036600461187c565b610a61565b6101e561035336600461170a565b610ad3565b6101e561036636600461195b565b610ae8565b61019561037936600461170a565b610c49565b6101f061038c36600461187c565b5f6020819052908152604090205481565b6101f07f000000000000000000000000000000000000000000000000000000000000000081565b61025f6103d2366004611842565b610c61565b6101e56103e53660046119da565b610d40565b6101e56103f83660046119fb565b610de6565b6101f061040b366004611811565b600560209081525f928352604080842090915290825290205481565b61043a61043536600461187c565b610e3d565b6040516101a19190611a61565b61030a61045536600461187c565b60096020525f90815260409020546001600160a01b031681565b61019561047d366004611842565b610e61565b5f6001600160e01b0319821663f815c03d60e01b14806104b257506001600160e01b031982166301ffc9a760e01b145b92915050565b600180546104c590611a76565b80601f01602080910402602001604051908101604052809291908181526020018280546104f190611a76565b801561053c5780601f106105135761010080835404028352916020019161053c565b820191905f5260205f20905b81548152906001019060200180831161051f57829003601f168201915b505050505081565b335f8181526005602090815260408083206001600160a01b038716808552925280832085905551919290915f516020611cf85f395f51905f529061058b9086815260200190565b60405180910390a350600192915050565b335f908152602081905260409020546001146105cb5760405163ea8e4eb560e01b815260040160405180910390fd5b6105d58282610e7a565b5050565b335f908152602081905260409020546001146106085760405163ea8e4eb560e01b815260040160405180910390fd5b6001600160a01b038281165f818152600960205260409081902080546001600160a01b0319169385169390931790925590517fd8c6b8f6ca4977137bd0c05f8e49099e0bbbefe5ed3010bf828a76dbab958313906106679084906118ff565b60405180910390a25050565b5f61067f848484610f15565b905061068c848484610f2a565b9392505050565b5f7f0000000000000000000000000000000000000000000000000000000000000000461461075f5750604080517f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6020808301919091527f0000000000000000000000000000000000000000000000000000000000000000828401527f000000000000000000000000000000000000000000000000000000000000000060608301524660808301523060a0808401919091528351808403909101815260c0909201909252805191012090565b507f000000000000000000000000000000000000000000000000000000000000000090565b61078e828261102d565b6003546001600160801b0310156107b85760405163c30436e960e01b815260040160405180910390fd5b6105d55f8383610f2a565b335f908152602081905260409020546001146107f25760405163ea8e4eb560e01b815260040160405180910390fd5b6001600160a01b0381165f8181526020819052604080822060019055517fdd0e34038ac38b2a1ce960229778ac48a8719bc900b6c4f8d0475c6e8b385a609190a250565b335f908152602081905260409020546001148061085d57506007546001600160a01b031633145b61087a57604051632d03803360e11b815260040160405180910390fd5b6001600160a01b0382165f818152600860205260409081902080546001600160801b0316600160801b608086901c02179055517f8fa29948e0a84e3c738d2e921e65fab6e5a02291fe898fd94d60c3c8ee614c4590610667908490611a61565b5f6104b2826110f5565b606060ff82161561091d576040518060400160405280601081526020016f1d1c985b9cd9995c8b589b1bd8dad95960821b8152506104b2565b505060408051808201909152601081526f1d1c985b9cd9995c8b585b1b1bddd95960821b602082015290565b335f908152602081905260408120546001146109785760405163ea8e4eb560e01b815260040160405180910390fd5b61098485858585611118565b6007549091506001600160a01b03168015610a4b57806001600160a01b031663078d18cd8787878760405180604001604052806109c08d610e3d565b6001600160801b03191681526020016109d88c610e3d565b6001600160801b03191690526040516001600160e01b031960e088901b168152610a09959493929190600401611aca565b6020604051808303815f875af1158015610a25573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a499190611afe565b505b50949350505050565b600280546104c590611a76565b335f90815260208190526040902054600114610a905760405163ea8e4eb560e01b815260040160405180910390fd5b6001600160a01b0381165f81815260208190526040808220829055517f184450df2e323acec0ed3b5c7531b81f9b4cdef7914dfd4c0a4317416bb5251b9190a250565b610add8282611277565b6105d5825f83610f2a565b81421115610b095760405163068568f360e21b815260040160405180910390fd5b6001600160a01b0385165f90815260066020526040812080546001810190915590610b32610693565b604080515f516020611cd85f395f51905f5260208201526001600160a01b03808b169282019290925290881660608201526080810187905260a0810184905260c0810186905260e00160405160208183030381529060405280519060200120604051602001610bb892919061190160f01b81526002810192909252602282015260420190565b604051602081830303815290604052805190602001209050610bdb8782856113a0565b610bf85760405163ddafbaef60e01b815260040160405180910390fd5b6001600160a01b038781165f818152600560209081526040808320948b168084529482529182902089905590518881525f516020611cf85f395f51905f52910160405180910390a350505050505050565b5f610c54838361154f565b90506104b2338484610f2a565b6007545f906001600160a01b031680610c7d575f91505061068c565b806001600160a01b031663ef59bc928686866040518060400160405280610ca38c610e3d565b6001600160801b0319168152602001610cbb8b610e3d565b6001600160801b03191690526040516001600160e01b031960e087901b168152610ceb9493929190600401611b19565b602060405180830381865afa158015610d06573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d2a9190611b45565b610d35576001610d37565b5f5b95945050505050565b335f90815260208190526040902054600114610d6f5760405163ea8e4eb560e01b815260040160405180910390fd5b8163686f6f6b60e01b03610d9d57600780546001600160a01b0319166001600160a01b038316179055610db6565b604051633db0d5b960e01b815260040160405180910390fd5b817f8fef588b5fc1afbf5b2f06c1a435d513f208da2e6704c3d8f0e0ec91167066ba8260405161066791906118ff565b610e3487878787868689604051602001610e2093929190928352602083019190915260f81b6001600160f81b031916604082015260410190565b604051602081830303815290604052610ae8565b50505050505050565b6001600160a01b03165f90815260086020526040902054600160801b900460801b90565b5f80610e6e858585610c61565b60ff1614949350505050565b335f90815260208190526040902054600114610ea95760405163ea8e4eb560e01b815260040160405180910390fd5b81636e616d6560e01b03610ec9576001610ec38282611bb0565b50610ee5565b81651cde5b589bdb60d21b03610d9d576002610ec38282611bb0565b817fe42e0b9a029dc87ccb1029c632e6359090acd0eb032b2b59c811e3ec70160dc68260405161066791906116dd565b5f610f2233858585611118565b949350505050565b6007546001600160a01b031680158061100a5750633f71910e60e01b6001600160e01b031916816001600160a01b0316633f71910e8686866040518060400160405280610f768c610e3d565b6001600160801b0319168152602001610f8e8b610e3d565b6001600160801b03191690526040516001600160e01b031960e087901b168152610fbe9493929190600401611b19565b6020604051808303815f875af1158015610fda573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ffe9190611afe565b6001600160e01b031916145b61102757604051637f31a9dd60e01b815260040160405180910390fd5b50505050565b335f9081526020819052604090205460011461105c5760405163ea8e4eb560e01b815260040160405180910390fd5b6001600160a01b0382161580159061107d57506001600160a01b0382163014155b61109a5760405163e6c4247b60e01b815260040160405180910390fd5b6110ae82826110a8856110f5565b0161160c565b8060035f8282546110bf9190611c6a565b90915550506040518181526001600160a01b038316905f905f516020611cb85f395f51905f529060200160405180910390a35050565b6001600160a01b03165f908152600860205260409020546001600160801b031690565b5f6001600160a01b0383161580159061113a57506001600160a01b0383163014155b6111575760405163e6c4247b60e01b815260040160405180910390fd5b5f611161856108da565b90508281101561118457604051631e9acf1760e31b815260040160405180910390fd5b856001600160a01b0316856001600160a01b031614611217576001600160a01b038086165f908152600560209081526040808320938a16835292905220545f19811461121557838110156111eb576040516313be252b60e01b815260040160405180910390fd5b6001600160a01b038087165f908152600560209081526040808320938b1683529290522084820390555b505b6112238584830361160c565b61123184846110a8876110f5565b836001600160a01b0316856001600160a01b03165f516020611cb85f395f51905f528560405161126391815260200190565b60405180910390a350600195945050505050565b335f908152602081905260409020546001146112a65760405163ea8e4eb560e01b815260040160405180910390fd5b5f6112b0836108da565b9050818110156112d357604051631e9acf1760e31b815260040160405180910390fd5b6001600160a01b0383163314611359576001600160a01b0383165f9081526005602090815260408083203384529091529020545f198114611357578281101561132f576040516313be252b60e01b815260040160405180910390fd5b6001600160a01b0384165f908152600560209081526040808320338452909152902083820390555b505b6113658383830361160c565b6003805483900390556040518281525f906001600160a01b038516905f516020611cb85f395f51905f529060200160405180910390a3505050565b5f6001600160a01b0384166113c857604051632057875960e21b815260040160405180910390fd5b81516041036114605760208281015160408085015160608087015183515f8082529681018086528a9052951a928501839052840183905260808401819052919260019060a0016020604051602081039080840390855afa15801561142e573d5f5f3e3d5ffd5b505050602060405103516001600160a01b0316876001600160a01b03160361145c576001935050505061068c565b5050505b6001600160a01b0384163b1561068c575f5f856001600160a01b0316858560405160240161148f929190611c89565b60408051601f198184030181529181526020820180516001600160e01b0316630b135d3f60e11b179052516114c49190611ca1565b5f60405180830381855afa9150503d805f81146114fc576040519150601f19603f3d011682016040523d82523d5f602084013e611501565b606091505b5091509150818015611514575080516020145b801561154557508051630b135d3f60e11b906115399083016020908101908401611afe565b6001600160e01b031916145b9695505050505050565b5f6001600160a01b0383161580159061157157506001600160a01b0383163014155b61158e5760405163e6c4247b60e01b815260040160405180910390fd5b5f611598336108da565b9050828110156115bb57604051631e9acf1760e31b815260040160405180910390fd5b6115c73384830361160c565b6115d584846110a8876110f5565b6040518381526001600160a01b0385169033905f516020611cb85f395f51905f529060200160405180910390a35060019392505050565b6116158161164f565b6001600160a01b03929092165f90815260086020526040902080546001600160801b0319166001600160801b039093169290921790915550565b5f6001600160801b038211156116785760405163e999826d60e01b815260040160405180910390fd5b5090565b6001600160e01b031981168114611691575f5ffd5b50565b5f602082840312156116a4575f5ffd5b813561068c8161167c565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b602081525f61068c60208301846116af565b80356001600160a01b0381168114611705575f5ffd5b919050565b5f5f6040838503121561171b575f5ffd5b611724836116ef565b946020939093013593505050565b634e487b7160e01b5f52604160045260245ffd5b5f806001600160401b0384111561175f5761175f611732565b50604051601f19601f85018116603f011681018181106001600160401b038211171561178d5761178d611732565b6040528381529050808284018510156117a4575f5ffd5b838360208301375f60208583010152509392505050565b5f5f604083850312156117cc575f5ffd5b8235915060208301356001600160401b038111156117e8575f5ffd5b8301601f810185136117f8575f5ffd5b61180785823560208401611746565b9150509250929050565b5f5f60408385031215611822575f5ffd5b61182b836116ef565b9150611839602084016116ef565b90509250929050565b5f5f5f60608486031215611854575f5ffd5b61185d846116ef565b925061186b602085016116ef565b929592945050506040919091013590565b5f6020828403121561188c575f5ffd5b61068c826116ef565b5f5f604083850312156118a6575f5ffd5b6118af836116ef565b915060208301356001600160801b0319811681146118cb575f5ffd5b809150509250929050565b803560ff81168114611705575f5ffd5b5f602082840312156118f6575f5ffd5b61068c826118d6565b6001600160a01b0391909116815260200190565b5f5f5f5f60808587031215611926575f5ffd5b61192f856116ef565b935061193d602086016116ef565b925061194b604086016116ef565b9396929550929360600135925050565b5f5f5f5f5f60a0868803121561196f575f5ffd5b611978866116ef565b9450611986602087016116ef565b9350604086013592506060860135915060808601356001600160401b038111156119ae575f5ffd5b8601601f810188136119be575f5ffd5b6119cd88823560208401611746565b9150509295509295909350565b5f5f604083850312156119eb575f5ffd5b82359150611839602084016116ef565b5f5f5f5f5f5f5f60e0888a031215611a11575f5ffd5b611a1a886116ef565b9650611a28602089016116ef565b95506040880135945060608801359350611a44608089016118d6565b9699959850939692959460a0840135945060c09093013592915050565b6001600160801b031991909116815260200190565b600181811c90821680611a8a57607f821691505b602082108103611aa857634e487b7160e01b5f52602260045260245ffd5b50919050565b80516001600160801b0319908116835260209182015116910152565b6001600160a01b0386811682528581166020830152841660408201526060810183905260c081016115456080830184611aae565b5f60208284031215611b0e575f5ffd5b815161068c8161167c565b6001600160a01b038581168252841660208201526040810183905260a08101610d376060830184611aae565b5f60208284031215611b55575f5ffd5b8151801515811461068c575f5ffd5b601f821115611bab57805f5260205f20601f840160051c81016020851015611b895750805b601f840160051c820191505b81811015611ba8575f8155600101611b95565b50505b505050565b81516001600160401b03811115611bc957611bc9611732565b611bdd81611bd78454611a76565b84611b64565b6020601f821160018114611c0f575f8315611bf85750848201515b5f19600385901b1c1916600184901b178455611ba8565b5f84815260208120601f198516915b82811015611c3e5787850151825560209485019460019092019101611c1e565b5084821015611c5b57868401515f19600387901b60f8161c191681555b50505050600190811b01905550565b808201808211156104b257634e487b7160e01b5f52601160045260245ffd5b828152604060208201525f610f2260408301846116af565b5f82518060208501845e5f92019182525091905056feddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c98c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925a26469706673582212204937a01138ea0d8238e3d4651492d5970e5e30f24bee18edb4afee8d0ceb536d64736f6c634300081c00330000000000000000000000000000000000000000000000000000000000000012","name":"ShareToken","is_blueprint":false,"license_type":"none","is_fully_verified":false,"is_verified_via_eth_bytecode_db":true,"language":"solidity","evm_version":"cancun","can_be_visualized_via_sol2uml":true,"is_verified_via_sourcify":false,"additional_sources":[{"file_path":"src/common/interfaces/ITransferHook.sol","source_code":"// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity 0.8.28;\n\nimport {IERC165} from \"../../misc/interfaces/IERC7575.sol\";\n\nstruct HookData {\n    bytes16 from;\n    bytes16 to;\n}\n\nuint8 constant SUCCESS_CODE_ID = 0;\nstring constant SUCCESS_MESSAGE = \"transfer-allowed\";\n\nuint8 constant ERROR_CODE_ID = 1;\nstring constant ERROR_MESSAGE = \"transfer-blocked\";\n\n/// @dev Magic address denoting a transfer to the escrow\n/// @dev Solely used for gas saving since escrow is per pool\n/// @dev Equals 118_624 such that there is no collision with any uint16 Centrifuge ID\naddress constant ESCROW_HOOK_ID = address(uint160(0x1CF60));\n\n/// @notice Hook interface to customize share token behaviour\n/// @dev    To detect specific system actions:\n///           Deposit request:                  address(0)      -> address(user)\n///           Deposit request fulfillment:       address(0)      -> ESCROW_HOOK_ID\n///           Deposit claim:                    ESCROW_HOOK_ID  -> address(user)\n///           Redeem request:                   address(user)   -> ESCROW_HOOK_ID\n///           Redeem request fulfillment:        ESCROW_HOOK_ID  -> address(0)\n///           Redeem claim:                     address(user)   -> address(0)\n///           Cross-chain transfer:             address(user)   -> address(uint160(chainId))\ninterface ITransferHook is IERC165 {\n    // --- Errors ---\n    error TransferBlocked();\n    error InvalidUpdate();\n\n    /// @notice Callback on standard ERC20 transfer.\n    /// @dev    MUST return bytes4(keccak256(\"onERC20Transfer(address,address,uint256,(bytes16,bytes16))\"))\n    ///         if successful\n    function onERC20Transfer(address from, address to, uint256 value, HookData calldata hookdata)\n        external\n        returns (bytes4);\n\n    /// @notice Callback on authorized ERC20 transfer.\n    /// @dev    Cannot be blocked, can only be used to update state.\n    ///         Return value is ignored, only kept for compatibility with V2 share tokens.\n    function onERC20AuthTransfer(address sender, address from, address to, uint256 value, HookData calldata hookdata)\n        external\n        returns (bytes4);\n\n    /// @notice Check if given transfer can be performed\n    function checkERC20Transfer(address from, address to, uint256 value, HookData calldata hookData)\n        external\n        view\n        returns (bool);\n\n    /// @notice Update a set of restriction for a token\n    /// @dev    MAY be user specific, which would be included in the encoded `update` value\n    function updateRestriction(address token, bytes memory update) external;\n}\n"},{"file_path":"src/misc/Auth.sol","source_code":"// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity 0.8.28;\n\nimport {IAuth} from \"./interfaces/IAuth.sol\";\n\n/// @title  Auth\n/// @notice Simple authentication pattern\n/// @author Based on code from https://github.com/makerdao/dss\nabstract contract Auth is IAuth {\n    /// @inheritdoc IAuth\n    mapping(address => uint256) public wards;\n\n    constructor(address initialWard) {\n        wards[initialWard] = 1;\n        emit Rely(initialWard);\n    }\n\n    /// @dev Check if the msg.sender has permissions\n    modifier auth() {\n        require(wards[msg.sender] == 1, NotAuthorized());\n        _;\n    }\n\n    /// @inheritdoc IAuth\n    function rely(address user) public auth {\n        wards[user] = 1;\n        emit Rely(user);\n    }\n\n    /// @inheritdoc IAuth\n    function deny(address user) public auth {\n        wards[user] = 0;\n        emit Deny(user);\n    }\n}\n"},{"file_path":"src/misc/ERC20.sol","source_code":"// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity 0.8.28;\n\nimport {Auth} from \"./Auth.sol\";\nimport {EIP712Lib} from \"./libraries/EIP712Lib.sol\";\nimport {SignatureLib} from \"./libraries/SignatureLib.sol\";\nimport {IERC20, IERC20Metadata, IERC20Permit} from \"./interfaces/IERC20.sol\";\n\n/// @title  ERC20\n/// @notice Standard ERC-20 implementation, with mint/burn functionality and permit logic.\n/// @author Modified from https://github.com/makerdao/xdomain-dss/blob/master/src/Dai.sol\ncontract ERC20 is Auth, IERC20Metadata, IERC20Permit {\n    event File(bytes32 indexed what, string data);\n\n    error FileUnrecognizedParam();\n\n    // Metadata\n    string public name;\n    string public symbol;\n    uint8 public immutable decimals;\n\n    // Balances\n    uint256 public totalSupply;\n    mapping(address => uint256) private balances;\n    mapping(address => mapping(address => uint256)) public allowance;\n\n    // EIP-712\n    bytes32 private immutable nameHash;\n    bytes32 private immutable versionHash;\n    mapping(address => uint256) public nonces;\n    uint256 public immutable deploymentChainId;\n    bytes32 private immutable _DOMAIN_SEPARATOR;\n    bytes32 public constant PERMIT_TYPEHASH =\n        keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n\n    constructor(uint8 decimals_) Auth(msg.sender) {\n        decimals = decimals_;\n\n        nameHash = keccak256(bytes(\"Centrifuge\"));\n        versionHash = keccak256(bytes(\"1\"));\n        deploymentChainId = block.chainid;\n        _DOMAIN_SEPARATOR = EIP712Lib.calculateDomainSeparator(nameHash, versionHash);\n    }\n\n    //----------------------------------------------------------------------------------------------\n    // Administration\n    //----------------------------------------------------------------------------------------------\n\n    function file(bytes32 what, string memory data) public virtual auth {\n        if (what == \"name\") name = data;\n        else if (what == \"symbol\") symbol = data;\n        else revert FileUnrecognizedParam();\n        emit File(what, data);\n    }\n\n    //----------------------------------------------------------------------------------------------\n    // ERC20 balances\n    //----------------------------------------------------------------------------------------------\n\n    /// @inheritdoc IERC20\n    function balanceOf(address user) public view virtual returns (uint256) {\n        return _balanceOf(user);\n    }\n\n    function _balanceOf(address user) internal view virtual returns (uint256) {\n        return balances[user];\n    }\n\n    function _setBalance(address user, uint256 value) internal virtual {\n        balances[user] = value;\n    }\n\n    //----------------------------------------------------------------------------------------------\n    // ERC20 mutations\n    //----------------------------------------------------------------------------------------------\n\n    /// @inheritdoc IERC20\n    function transfer(address to, uint256 value) public virtual returns (bool) {\n        require(to != address(0) && to != address(this), InvalidAddress());\n        uint256 balance = balanceOf(msg.sender);\n        require(balance >= value, InsufficientBalance());\n\n        unchecked {\n            _setBalance(msg.sender, balance - value);\n            // We don't need an overflow check here b/c sum of all balances == totalSupply\n            _setBalance(to, _balanceOf(to) + value);\n        }\n\n        emit Transfer(msg.sender, to, value);\n\n        return true;\n    }\n\n    /// @inheritdoc IERC20\n    function transferFrom(address from, address to, uint256 value) public virtual returns (bool) {\n        return _transferFrom(msg.sender, from, to, value);\n    }\n\n    function _transferFrom(address sender, address from, address to, uint256 value) internal virtual returns (bool) {\n        require(to != address(0) && to != address(this), InvalidAddress());\n        uint256 balance = balanceOf(from);\n        require(balance >= value, InsufficientBalance());\n\n        if (from != sender) {\n            uint256 allowed = allowance[from][sender];\n            if (allowed != type(uint256).max) {\n                require(allowed >= value, InsufficientAllowance());\n                unchecked {\n                    allowance[from][sender] = allowed - value;\n                }\n            }\n        }\n\n        unchecked {\n            _setBalance(from, balance - value);\n            // We don't need an overflow check here b/c sum of all balances == totalSupply\n            _setBalance(to, _balanceOf(to) + value);\n        }\n\n        emit Transfer(from, to, value);\n\n        return true;\n    }\n\n    /// @inheritdoc IERC20\n    function approve(address spender, uint256 value) external returns (bool) {\n        allowance[msg.sender][spender] = value;\n\n        emit Approval(msg.sender, spender, value);\n\n        return true;\n    }\n\n    //----------------------------------------------------------------------------------------------\n    // Mint/burn\n    //----------------------------------------------------------------------------------------------\n\n    function mint(address to, uint256 value) public virtual auth {\n        require(to != address(0) && to != address(this), InvalidAddress());\n        unchecked {\n            // We don't need an overflow check here b/c balances[to] <= totalSupply\n            // and there is an overflow check below\n            _setBalance(to, _balanceOf(to) + value);\n        }\n        totalSupply += value;\n\n        emit Transfer(address(0), to, value);\n    }\n\n    function burn(address from, uint256 value) public virtual auth {\n        uint256 balance = balanceOf(from);\n        require(balance >= value, InsufficientBalance());\n\n        if (from != msg.sender) {\n            uint256 allowed = allowance[from][msg.sender];\n            if (allowed != type(uint256).max) {\n                require(allowed >= value, InsufficientAllowance());\n\n                unchecked {\n                    allowance[from][msg.sender] = allowed - value;\n                }\n            }\n        }\n\n        unchecked {\n            // We don't need overflow checks b/c require(balance >= value) and balance <= totalSupply\n            _setBalance(from, balance - value);\n            totalSupply -= value;\n        }\n\n        emit Transfer(from, address(0), value);\n    }\n\n    //----------------------------------------------------------------------------------------------\n    // Permit\n    //----------------------------------------------------------------------------------------------\n\n    /// @inheritdoc IERC20Permit\n    function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s)\n        external\n    {\n        permit(owner, spender, value, deadline, abi.encodePacked(r, s, v));\n    }\n\n    function permit(address owner, address spender, uint256 value, uint256 deadline, bytes memory signature) public {\n        require(block.timestamp <= deadline, PermitExpired());\n\n        uint256 nonce;\n        unchecked {\n            nonce = nonces[owner]++;\n        }\n\n        bytes32 digest = keccak256(\n            abi.encodePacked(\n                \"\\x19\\x01\",\n                DOMAIN_SEPARATOR(),\n                keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, value, nonce, deadline))\n            )\n        );\n\n        require(SignatureLib.isValidSignature(owner, digest, signature), InvalidPermit());\n\n        allowance[owner][spender] = value;\n        emit Approval(owner, spender, value);\n    }\n\n    /// @inheritdoc IERC20Permit\n    function DOMAIN_SEPARATOR() public view returns (bytes32) {\n        return block.chainid == deploymentChainId\n            ? _DOMAIN_SEPARATOR\n            : EIP712Lib.calculateDomainSeparator(nameHash, versionHash);\n    }\n}\n"},{"file_path":"src/misc/interfaces/IAuth.sol","source_code":"// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\ninterface IAuth {\n    event Rely(address indexed user);\n    event Deny(address indexed user);\n\n    error NotAuthorized();\n\n    /// @notice Returns whether the target is a ward (has admin access)\n    function wards(address target) external view returns (uint256);\n\n    /// @notice Make user a ward (give them admin access)\n    function rely(address user) external;\n\n    /// @notice Remove user as a ward (remove admin access)\n    function deny(address user) external;\n}\n"},{"file_path":"src/misc/interfaces/IERC165.sol","source_code":"// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others.\n */\ninterface IERC165 {\n    /**\n     * @dev Returns true if this contract implements the interface defined by\n     * `interfaceId`. See the corresponding\n     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n     * to learn more about how these ids are created.\n     *\n     * This function call must use less than 30 000 gas.\n     */\n    function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n"},{"file_path":"src/misc/interfaces/IERC20.sol","source_code":"// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\n/// @title  IERC20\n/// @dev    Interface of the ERC20 standard as defined in the EIP.\n/// @author Modified from OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)\ninterface IERC20 {\n    error InvalidAddress();\n    error InsufficientBalance();\n    error InsufficientAllowance();\n\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 value of tokens in existence.\n     */\n    function totalSupply() external view returns (uint256);\n\n    /**\n     * @dev Returns the value of tokens owned by `account`.\n     */\n    function balanceOf(address account) external view returns (uint256);\n\n    /**\n     * @dev Moves a `value` amount of 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 value) 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 a `value` amount of tokens as the allowance of `spender` over the\n     * 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 value) external returns (bool);\n\n    /**\n     * @dev Moves a `value` amount of tokens from `from` to `to` using the\n     * allowance mechanism. `value` 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(address from, address to, uint256 value) external returns (bool);\n}\n\n/**\n * @dev Interface for the optional metadata functions from the ERC20 standard.\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\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 *\n * ==== Security Considerations\n *\n * There are two important considerations concerning the use of `permit`. The first is that a valid permit signature\n * expresses an allowance, and it should not be assumed to convey additional meaning. In particular, it should not be\n * considered as an intention to spend the allowance in any specific way. The second is that because permits have\n * built-in replay protection and can be submitted by anyone, they can be frontrun. A protocol that uses permits should\n * take this into consideration and allow a `permit` call to fail. Combining these two aspects, a pattern that may be\n * generally recommended is:\n *\n * ```solidity\n * function doThingWithPermit(..., uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s) public {\n *     try token.permit(msg.sender, address(this), value, deadline, v, r, s) {} catch {}\n *     doThing(..., value);\n * }\n *\n * function doThing(..., uint256 value) public {\n *     token.safeTransferFrom(msg.sender, address(this), value);\n *     ...\n * }\n * ```\n *\n * Observe that: 1) `msg.sender` is used as the owner, leaving no ambiguity as to the signer intent, and 2) the use of\n * `try/catch` allows the permit to fail and makes the code tolerant to frontrunning. (See also\n * {SafeERC20-safeTransferFrom}).\n *\n * Additionally, note that smart contract wallets (such as Argent or Safe) are not able to produce permit signatures, so\n * contracts should have entry points that don't rely on permit.\n */\ninterface IERC20Permit {\n    error PermitExpired();\n    error InvalidPermit();\n\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     * CAUTION: See Security Considerations above.\n     */\n    function permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, 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\ninterface IERC20Wrapper {\n    /**\n     * @dev Returns the address of the underlying ERC-20 token that is being wrapped.\n     */\n    function underlying() external view returns (address);\n\n    /**\n     * @dev Allow a user to deposit underlying tokens and mint the corresponding number of wrapped tokens.\n     */\n    function depositFor(address account, uint256 value) external returns (bool);\n\n    /**\n     * @dev Allow a user to burn a number of wrapped tokens and withdraw the corresponding number of underlying tokens.\n     */\n    function withdrawTo(address account, uint256 value) external returns (bool);\n}\n"},{"file_path":"src/misc/interfaces/IERC7575.sol","source_code":"// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\nimport {IERC165} from \"./IERC165.sol\";\n\ninterface IERC7575 is IERC165 {\n    event Deposit(address indexed sender, address indexed owner, uint256 assets, uint256 shares);\n    event Withdraw(\n        address indexed sender, address indexed receiver, address indexed owner, uint256 assets, uint256 shares\n    );\n\n    /**\n     * @dev Returns the address of the underlying token used for the Vault for accounting, depositing, and withdrawing.\n     *\n     * - MUST be an ERC-20 token contract.\n     * - MUST NOT revert.\n     */\n    function asset() external view returns (address assetTokenAddress);\n\n    /**\n     * @dev Returns the address of the share token\n     *\n     * - MUST be an ERC-20 token contract.\n     * - MUST NOT revert.\n     */\n    function share() external view returns (address shareTokenAddress);\n\n    /**\n     * @dev Returns the amount of shares that the Vault would exchange for the amount of assets provided, in an ideal\n     * scenario where all the conditions are met.\n     *\n     * - MUST NOT be inclusive of any fees that are charged against assets in the Vault.\n     * - MUST NOT show any variations depending on the caller.\n     * - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.\n     * - MUST NOT revert.\n     *\n     * NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the\n     * “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and\n     * from.\n     */\n    function convertToShares(uint256 assets) external view returns (uint256 shares);\n\n    /**\n     * @dev Returns the amount of assets that the Vault would exchange for the amount of shares provided, in an ideal\n     * scenario where all the conditions are met.\n     *\n     * - MUST NOT be inclusive of any fees that are charged against assets in the Vault.\n     * - MUST NOT show any variations depending on the caller.\n     * - MUST NOT reflect slippage or other on-chain conditions, when performing the actual exchange.\n     * - MUST NOT revert.\n     *\n     * NOTE: This calculation MAY NOT reflect the “per-user” price-per-share, and instead should reflect the\n     * “average-user’s” price-per-share, meaning what the average user should expect to see when exchanging to and\n     * from.\n     */\n    function convertToAssets(uint256 shares) external view returns (uint256 assets);\n\n    /**\n     * @dev Returns the total amount of the underlying asset that is “managed” by Vault.\n     *\n     * - SHOULD include any compounding that occurs from yield.\n     * - MUST be inclusive of any fees that are charged against assets in the Vault.\n     * - MUST NOT revert.\n     */\n    function totalAssets() external view returns (uint256 totalManagedAssets);\n\n    /**\n     * @dev Returns the maximum amount of the underlying asset that can be deposited into the Vault for the receiver,\n     * through a deposit call.\n     *\n     * - MUST return a limited value if receiver is subject to some deposit limit.\n     * - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of assets that may be deposited.\n     * - MUST NOT revert.\n     */\n    function maxDeposit(address receiver) external view returns (uint256 maxAssets);\n\n    /**\n     * @dev Allows an on-chain or off-chain user to simulate the effects of their deposit at the current block, given\n     * current on-chain conditions.\n     *\n     * - MUST return as close to and no more than the exact amount of Vault shares that would be minted in a deposit\n     *   call in the same transaction. I.e. deposit should return the same or more shares as previewDeposit if called\n     *   in the same transaction.\n     * - MUST NOT account for deposit limits like those returned from maxDeposit and should always act as though the\n     *   deposit would be accepted, regardless if the user has enough tokens approved, etc.\n     * - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.\n     * - MUST NOT revert.\n     *\n     * NOTE: any unfavorable discrepancy between convertToShares and previewDeposit SHOULD be considered slippage in\n     * share price or some other type of condition, meaning the depositor will lose assets by depositing.\n     */\n    function previewDeposit(uint256 assets) external view returns (uint256 shares);\n\n    /**\n     * @dev Mints shares Vault shares to receiver by depositing exactly amount of underlying tokens.\n     *\n     * - MUST emit the Deposit event.\n     * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the\n     *   deposit execution, and are accounted for during deposit.\n     * - MUST revert if all of assets cannot be deposited (due to deposit limit being reached, slippage, the user not\n     *   approving enough underlying tokens to the Vault contract, etc).\n     *\n     * NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token.\n     */\n    function deposit(uint256 assets, address receiver) external returns (uint256 shares);\n\n    /**\n     * @dev Returns the maximum amount of the Vault shares that can be minted for the receiver, through a mint call.\n     * - MUST return a limited value if receiver is subject to some mint limit.\n     * - MUST return 2 ** 256 - 1 if there is no limit on the maximum amount of shares that may be minted.\n     * - MUST NOT revert.\n     */\n    function maxMint(address receiver) external view returns (uint256 maxShares);\n\n    /**\n     * @dev Allows an on-chain or off-chain user to simulate the effects of their mint at the current block, given\n     * current on-chain conditions.\n     *\n     * - MUST return as close to and no fewer than the exact amount of assets that would be deposited in a mint call\n     *   in the same transaction. I.e. mint should return the same or fewer assets as previewMint if called in the\n     *   same transaction.\n     * - MUST NOT account for mint limits like those returned from maxMint and should always act as though the mint\n     *   would be accepted, regardless if the user has enough tokens approved, etc.\n     * - MUST be inclusive of deposit fees. Integrators should be aware of the existence of deposit fees.\n     * - MUST NOT revert.\n     *\n     * NOTE: any unfavorable discrepancy between convertToAssets and previewMint SHOULD be considered slippage in\n     * share price or some other type of condition, meaning the depositor will lose assets by minting.\n     */\n    function previewMint(uint256 shares) external view returns (uint256 assets);\n\n    /**\n     * @dev Mints exactly shares Vault shares to receiver by depositing amount of underlying tokens.\n     *\n     * - MUST emit the Deposit event.\n     * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the mint\n     *   execution, and are accounted for during mint.\n     * - MUST revert if all of shares cannot be minted (due to deposit limit being reached, slippage, the user not\n     *   approving enough underlying tokens to the Vault contract, etc).\n     *\n     * NOTE: most implementations will require pre-approval of the Vault with the Vault’s underlying asset token.\n     */\n    function mint(uint256 shares, address receiver) external returns (uint256 assets);\n\n    /**\n     * @dev Returns the maximum amount of the underlying asset that can be withdrawn from the owner balance in the\n     * Vault, through a withdraw call.\n     *\n     * - MUST return a limited value if owner is subject to some withdrawal limit or timelock.\n     * - MUST NOT revert.\n     */\n    function maxWithdraw(address owner) external view returns (uint256 maxAssets);\n\n    /**\n     * @dev Allows an on-chain or off-chain user to simulate the effects of their withdrawal at the current block,\n     * given current on-chain conditions.\n     *\n     * - MUST return as close to and no fewer than the exact amount of Vault shares that would be burned in a withdraw\n     *   call in the same transaction. I.e. withdraw should return the same or fewer shares as previewWithdraw if\n     *   called\n     *   in the same transaction.\n     * - MUST NOT account for withdrawal limits like those returned from maxWithdraw and should always act as though\n     *   the withdrawal would be accepted, regardless if the user has enough shares, etc.\n     * - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.\n     * - MUST NOT revert.\n     *\n     * NOTE: any unfavorable discrepancy between convertToShares and previewWithdraw SHOULD be considered slippage in\n     * share price or some other type of condition, meaning the depositor will lose assets by depositing.\n     */\n    function previewWithdraw(uint256 assets) external view returns (uint256 shares);\n\n    /**\n     * @dev Burns shares from owner and sends exactly assets of underlying tokens to receiver.\n     *\n     * - MUST emit the Withdraw event.\n     * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the\n     *   withdraw execution, and are accounted for during withdraw.\n     * - MUST revert if all of assets cannot be withdrawn (due to withdrawal limit being reached, slippage, the owner\n     *   not having enough shares, etc).\n     *\n     * Note that some implementations will require pre-requesting to the Vault before a withdrawal may be performed.\n     * Those methods should be performed separately.\n     */\n    function withdraw(uint256 assets, address receiver, address owner) external returns (uint256 shares);\n\n    /**\n     * @dev Returns the maximum amount of Vault shares that can be redeemed from the owner balance in the Vault,\n     * through a redeem call.\n     *\n     * - MUST return a limited value if owner is subject to some withdrawal limit or timelock.\n     * - MUST return balanceOf(owner) if owner is not subject to any withdrawal limit or timelock.\n     * - MUST NOT revert.\n     */\n    function maxRedeem(address owner) external view returns (uint256 maxShares);\n\n    /**\n     * @dev Allows an on-chain or off-chain user to simulate the effects of their redeemption at the current block,\n     * given current on-chain conditions.\n     *\n     * - MUST return as close to and no more than the exact amount of assets that would be withdrawn in a redeem call\n     *   in the same transaction. I.e. redeem should return the same or more assets as previewRedeem if called in the\n     *   same transaction.\n     * - MUST NOT account for redemption limits like those returned from maxRedeem and should always act as though the\n     *   redemption would be accepted, regardless if the user has enough shares, etc.\n     * - MUST be inclusive of withdrawal fees. Integrators should be aware of the existence of withdrawal fees.\n     * - MUST NOT revert.\n     *\n     * NOTE: any unfavorable discrepancy between convertToAssets and previewRedeem SHOULD be considered slippage in\n     * share price or some other type of condition, meaning the depositor will lose assets by redeeming.\n     */\n    function previewRedeem(uint256 shares) external view returns (uint256 assets);\n\n    /**\n     * @dev Burns exactly shares from owner and sends assets of underlying tokens to receiver.\n     *\n     * - MUST emit the Withdraw event.\n     * - MAY support an additional flow in which the underlying tokens are owned by the Vault contract before the\n     *   redeem execution, and are accounted for during redeem.\n     * - MUST revert if all of shares cannot be redeemed (due to withdrawal limit being reached, slippage, the owner\n     *   not having enough shares, etc).\n     *\n     * NOTE: some implementations will require pre-requesting to the Vault before a withdrawal may be performed.\n     * Those methods should be performed separately.\n     */\n    function redeem(uint256 shares, address receiver, address owner) external returns (uint256 assets);\n}\n\ninterface IERC7575Share is IERC165 {\n    event VaultUpdate(address indexed asset, address vault);\n\n    /**\n     * @dev Returns the address of the Vault for the given asset.\n     *\n     * @param asset the ERC-20 token to deposit with into the Vault\n     */\n    function vault(address asset) external view returns (address);\n}\n"},{"file_path":"src/misc/libraries/EIP712Lib.sol","source_code":"// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity 0.8.28;\n\n/// @title  EIP712 Lib\nlibrary EIP712Lib {\n    // keccak256(\"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\")\n    bytes32 public constant EIP712_DOMAIN_TYPEHASH = 0x8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f;\n\n    function calculateDomainSeparator(bytes32 nameHash, bytes32 versionHash) internal view returns (bytes32) {\n        return keccak256(abi.encode(EIP712_DOMAIN_TYPEHASH, nameHash, versionHash, block.chainid, address(this)));\n    }\n}\n"},{"file_path":"src/misc/libraries/MathLib.sol","source_code":"// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity 0.8.28;\n\nlibrary MathLib {\n    enum Rounding {\n        Down, // Toward negative infinity\n        Up, // Toward infinity\n        Zero // Toward zero\n\n    }\n\n    error MulDiv_Overflow();\n    error Uint8_Overflow();\n    error Uint32_Overflow();\n    error Uint64_Overflow();\n    error Uint128_Overflow();\n    error Int128_Overflow();\n\n    uint256 public constant One27 = 10 ** 27;\n\n    /// @notice Returns x^n with rounding precision of base\n    ///\n    /// @dev Source: https://github.com/makerdao/dss/blob/fa4f6630afb0624d04a003e920b0d71a00331d98/src/jug.sol#L62\n    ///\n    /// @param x The base value which should be exponentiated\n    /// @param n The exponent\n    /// @param base The scaling base, typically used for fix-point calculations\n    function rpow(uint256 x, uint256 n, uint256 base) public pure returns (uint256 z) {\n        assembly {\n            switch x\n            case 0 {\n                switch n\n                case 0 { z := base }\n                default { z := 0 }\n            }\n            default {\n                switch mod(n, 2)\n                case 0 { z := base }\n                default { z := x }\n                let half := div(base, 2) // for rounding.\n                for { n := div(n, 2) } n { n := div(n, 2) } {\n                    let xx := mul(x, x)\n                    if iszero(eq(div(xx, x), x)) { revert(0, 0) }\n                    let xxRound := add(xx, half)\n                    if lt(xxRound, xx) { revert(0, 0) }\n                    x := div(xxRound, base)\n                    if mod(n, 2) {\n                        let zx := mul(z, x)\n                        if and(iszero(iszero(x)), iszero(eq(div(zx, x), z))) { revert(0, 0) }\n                        let zxRound := add(zx, half)\n                        if lt(zxRound, zx) { revert(0, 0) }\n                        z := div(zxRound, base)\n                    }\n                }\n            }\n        }\n    }\n\n    /// @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or\n    ///         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    // slither-disable-start divide-before-multiply\n    function mulDiv(uint256 x, uint256 y, uint256 denominator) 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                // Solidity will revert if denominator == 0, unlike the div opcode on its own.\n                // The surrounding unchecked block does not change this fact.\n                // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.\n                return prod0 / denominator;\n            }\n\n            // Make sure the result is less than 2^256. Also prevents denominator == 0.\n            require(denominator > prod1, MulDiv_Overflow());\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.\n            // 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\n            // 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    // slither-disable-end divide-before-multiply\n\n    /// @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n    function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) 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    /// @notice Safe type conversion from uint256 to uint8.\n    function toUint8(uint256 value) internal pure returns (uint8) {\n        require(value <= type(uint8).max, Uint8_Overflow());\n        return uint8(value);\n    }\n\n    function toUint32(uint256 value) internal pure returns (uint32) {\n        require(value <= type(uint32).max, Uint32_Overflow());\n        return uint32(value);\n    }\n\n    function toUint64(uint256 value) internal pure returns (uint64) {\n        require(value <= type(uint64).max, Uint64_Overflow());\n        return uint64(value);\n    }\n\n    /// @notice Safe type conversion from uint256 to uint128.\n    function toUint128(uint256 value) internal pure returns (uint128) {\n        require(value <= type(uint128).max, Uint128_Overflow());\n        return uint128(value);\n    }\n\n    /// @notice Returns the smallest of two numbers.\n    function min(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a > b ? b : a;\n    }\n\n    /// @notice Returns the largest of two numbers.\n    function max(uint256 a, uint256 b) internal pure returns (uint256) {\n        return a > b ? a : b;\n    }\n}\n"},{"file_path":"src/misc/libraries/SignatureLib.sol","source_code":"// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity 0.8.28;\n\ninterface IERC1271 {\n    function isValidSignature(bytes32, bytes memory) external view returns (bytes4);\n}\n\n/// @title  Signature Lib\nlibrary SignatureLib {\n    error InvalidSigner();\n\n    function isValidSignature(address signer, bytes32 digest, bytes memory signature)\n        internal\n        view\n        returns (bool valid)\n    {\n        require(signer != address(0), InvalidSigner());\n\n        if (signature.length == 65) {\n            bytes32 r;\n            bytes32 s;\n            uint8 v;\n            assembly {\n                r := mload(add(signature, 0x20))\n                s := mload(add(signature, 0x40))\n                v := byte(0, mload(add(signature, 0x60)))\n            }\n            if (signer == ecrecover(digest, v, r, s)) {\n                return true;\n            }\n        }\n\n        if (signer.code.length > 0) {\n            (bool success, bytes memory result) =\n                signer.staticcall(abi.encodeCall(IERC1271.isValidSignature, (digest, signature)));\n            valid =\n                (success && result.length == 32 && abi.decode(result, (bytes4)) == IERC1271.isValidSignature.selector);\n        }\n    }\n}\n"},{"file_path":"src/spoke/interfaces/IShareToken.sol","source_code":"// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity 0.8.28;\n\nimport {IERC20Metadata} from \"../../misc/interfaces/IERC20.sol\";\nimport {IERC7575Share} from \"../../misc/interfaces/IERC7575.sol\";\n\ninterface IERC1404 {\n    /// @notice Detects if a transfer will be reverted and if so returns an appropriate reference code\n    /// @param from Sending address\n    /// @param to Receiving address\n    /// @param value Amount of tokens being transferred\n    /// @return Code by which to reference message for rejection reasoning\n    /// @dev Overwrite with your custom transfer restriction logic\n    function detectTransferRestriction(address from, address to, uint256 value) external view returns (uint8);\n\n    /// @notice Returns a human-readable message for a given restriction code\n    /// @param restrictionCode Identifier for looking up a message\n    /// @return Text showing the restriction's reasoning\n    /// @dev Overwrite with your custom message and restrictionCode handling\n    function messageForTransferRestriction(uint8 restrictionCode) external view returns (string memory);\n}\n\ninterface IShareToken is IERC20Metadata, IERC7575Share, IERC1404 {\n    // --- Events ---\n    event File(bytes32 indexed what, address data);\n    event SetHookData(address indexed user, bytes16 data);\n\n    // --- Errors ---\n    error NotAuthorizedOrHook();\n    error ExceedsMaxSupply();\n    error RestrictionsFailed();\n\n    struct Balance {\n        /// @dev The user balance is limited to uint128. This is safe because the decimals are limited to 18,\n        ///      thus the max balance is 2^128-1 / 10**18 = 3.40 * 10**20. This is also enforced on mint.\n        uint128 amount;\n        /// @dev There are 16 bytes that are used to store hook data (e.g. restrictions for users).\n        bytes16 hookData;\n    }\n\n    // --- Administration ---\n    /// @notice returns the hook that transfers perform callbacks to\n    /// @dev    MUST comply to `ITransferHook` interface\n    function hook() external view returns (address);\n\n    /// @notice Updates a contract parameter\n    /// @param what Accepts a bytes32 representation of 'name', 'symbol'\n    function file(bytes32 what, string memory data) external;\n\n    /// @notice Updates a contract parameter\n    /// @param what Accepts a bytes32 representation of 'hook'\n    function file(bytes32 what, address data) external;\n\n    /// @notice updates the vault for a given `asset`\n    function updateVault(address asset, address vault_) external;\n\n    // --- ERC20 overrides ---\n    /// @notice returns the 16 byte hook data of the given `user`.\n    /// @dev    Stored in the 128 most significant bits of the user balance\n    function hookDataOf(address user) external view returns (bytes16);\n\n    /// @notice update the 16 byte hook data of the given `user`\n    function setHookData(address user, bytes16 hookData) external;\n\n    /// @notice Function to mint tokens\n    function mint(address user, uint256 value) external;\n\n    /// @notice Function to burn tokens\n    function burn(address user, uint256 value) external;\n\n    /// @notice Checks if the tokens can be transferred given the input values\n    function checkTransferRestriction(address from, address to, uint256 value) external view returns (bool);\n\n    /// @notice Performs an authorized transfer, with `sender` as the given sender.\n    /// @dev    Requires allowance if `sender` != `from`\n    function authTransferFrom(address sender, address from, address to, uint256 amount) external returns (bool);\n}\n"}],"certified":false,"conflicting_implementations":null,"abi":[{"inputs":[{"internalType":"uint8","name":"decimals_","type":"uint8"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ExceedsMaxSupply","type":"error"},{"inputs":[],"name":"FileUnrecognizedParam","type":"error"},{"inputs":[],"name":"InsufficientAllowance","type":"error"},{"inputs":[],"name":"InsufficientBalance","type":"error"},{"inputs":[],"name":"InvalidAddress","type":"error"},{"inputs":[],"name":"InvalidPermit","type":"error"},{"inputs":[],"name":"InvalidSigner","type":"error"},{"inputs":[],"name":"NotAuthorized","type":"error"},{"inputs":[],"name":"NotAuthorizedOrHook","type":"error"},{"inputs":[],"name":"PermitExpired","type":"error"},{"inputs":[],"name":"RestrictionsFailed","type":"error"},{"inputs":[],"name":"Uint128_Overflow","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"}],"name":"Deny","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"what","type":"bytes32"},{"indexed":false,"internalType":"string","name":"data","type":"string"}],"name":"File","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"what","type":"bytes32"},{"indexed":false,"internalType":"address","name":"data","type":"address"}],"name":"File","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"}],"name":"Rely","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"bytes16","name":"data","type":"bytes16"}],"name":"SetHookData","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":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":false,"internalType":"address","name":"vault","type":"address"}],"name":"VaultUpdate","type":"event"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PERMIT_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","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":"value","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"authTransferFrom","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"checkTransferRestriction","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"deny","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"deploymentChainId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"detectTransferRestriction","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"what","type":"bytes32"},{"internalType":"string","name":"data","type":"string"}],"name":"file","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"what","type":"bytes32"},{"internalType":"address","name":"data","type":"address"}],"name":"file","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"hook","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"hookDataOf","outputs":[{"internalType":"bytes16","name":"","type":"bytes16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8","name":"restrictionCode","type":"uint8"}],"name":"messageForTransferRestriction","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"mint","outputs":[],"stateMutability":"nonpayable","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":[{"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":"bytes","name":"signature","type":"bytes"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","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":[{"internalType":"address","name":"user","type":"address"}],"name":"rely","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"bytes16","name":"hookData","type":"bytes16"}],"name":"setHookData","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","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":"value","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"success","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"address","name":"vault_","type":"address"}],"name":"updateVault","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"asset","type":"address"}],"name":"vault","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"wards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}],"is_changed_bytecode":false,"is_partially_verified":true,"constructor_args":"0000000000000000000000000000000000000000000000000000000000000012"}