{"file_path":"src/core/spoke/Spoke.sol","creation_status":"success","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.28;\n\nimport {Price} from \"./types/Price.sol\";\nimport {IShareToken} from \"./interfaces/IShareToken.sol\";\nimport {ITransferHook} from \"./interfaces/ITransferHook.sol\";\nimport {ITokenFactory} from \"./factories/interfaces/ITokenFactory.sol\";\nimport {IPoolEscrowFactory} from \"./factories/interfaces/IPoolEscrowFactory.sol\";\nimport {AssetIdKey, Pool, ShareClassDetails, TokenDetails, ISpoke} from \"./interfaces/ISpoke.sol\";\n\nimport {Auth} from \"../../misc/Auth.sol\";\nimport {D18} from \"../../misc/types/D18.sol\";\nimport {Recoverable} from \"../../misc/Recoverable.sol\";\nimport {CastLib} from \"../../misc/libraries/CastLib.sol\";\nimport {MathLib} from \"../../misc/libraries/MathLib.sol\";\nimport {BytesLib} from \"../../misc/libraries/BytesLib.sol\";\nimport {IERC20Metadata} from \"../../misc/interfaces/IERC20.sol\";\nimport {IERC6909MetadataExt} from \"../../misc/interfaces/IERC6909.sol\";\nimport {ReentrancyProtection} from \"../../misc/ReentrancyProtection.sol\";\n\nimport {IGateway} from \"../messaging/interfaces/IGateway.sol\";\nimport {MessageLib} from \"../messaging/libraries/MessageLib.sol\";\nimport {ISpokeMessageSender} from \"../messaging/interfaces/IGatewaySenders.sol\";\nimport {ISpokeGatewayHandler} from \"../messaging/interfaces/IGatewayHandlers.sol\";\n\nimport {PoolId} from \"../types/PoolId.sol\";\nimport {ShareClassId} from \"../types/ShareClassId.sol\";\nimport {newAssetId, AssetId} from \"../types/AssetId.sol\";\nimport {IRequestManager} from \"../interfaces/IRequestManager.sol\";\n\n/// @title  Spoke\n/// @notice This contract manages which pools & share classes exist, controlling allowed pool currencies,\n///         initiating cross-chain transfers for tokens, and registering and linking vaults.\ncontract Spoke is Auth, Recoverable, ReentrancyProtection, ISpoke, ISpokeGatewayHandler {\n    using CastLib for *;\n    using MessageLib for *;\n    using BytesLib for bytes;\n    using MathLib for uint256;\n\n    uint8 internal constant MIN_DECIMALS = 2;\n    uint8 internal constant MAX_DECIMALS = 18;\n\n    IGateway public gateway;\n    ITokenFactory public tokenFactory;\n    ISpokeMessageSender public sender;\n    IPoolEscrowFactory public poolEscrowFactory;\n\n    mapping(PoolId => Pool) public pool;\n    mapping(PoolId => IRequestManager) public requestManager;\n    mapping(PoolId => mapping(ShareClassId => ShareClassDetails)) public shareClass;\n\n    uint64 internal _assetCounter;\n    mapping(AssetId => AssetIdKey) internal _idToAsset;\n    mapping(address token => TokenDetails) internal _tokenDetails;\n    mapping(address asset => mapping(uint256 tokenId => AssetId)) internal _assetToId;\n    mapping(PoolId => mapping(ShareClassId => mapping(AssetId => Price))) internal _pricePoolPerAsset;\n\n    constructor(ITokenFactory tokenFactory_, address deployer) Auth(deployer) {\n        tokenFactory = tokenFactory_;\n    }\n\n    //----------------------------------------------------------------------------------------------\n    // Administration\n    //----------------------------------------------------------------------------------------------\n\n    /// @inheritdoc ISpoke\n    function file(bytes32 what, address data) external auth {\n        if (what == \"gateway\") gateway = IGateway(data);\n        else if (what == \"sender\") sender = ISpokeMessageSender(data);\n        else if (what == \"tokenFactory\") tokenFactory = ITokenFactory(data);\n        else if (what == \"poolEscrowFactory\") poolEscrowFactory = IPoolEscrowFactory(data);\n        else revert FileUnrecognizedParam();\n        emit File(what, data);\n    }\n\n    //----------------------------------------------------------------------------------------------\n    // Outgoing methods\n    //----------------------------------------------------------------------------------------------\n\n    /// @inheritdoc ISpoke\n    function crosschainTransferShares(\n        uint16 centrifugeId,\n        PoolId poolId,\n        ShareClassId scId,\n        bytes32 receiver,\n        uint128 amount,\n        uint128 extraGasLimit,\n        uint128 remoteExtraGasLimit,\n        address refund\n    ) public payable protected {\n        IShareToken share = IShareToken(shareToken(poolId, scId));\n        require(centrifugeId != sender.localCentrifugeId(), LocalTransferNotAllowed());\n        require(\n            share.checkTransferRestriction(msg.sender, address(uint160(centrifugeId)), amount),\n            CrossChainTransferNotAllowed()\n        );\n\n        share.authTransferFrom(msg.sender, msg.sender, address(this), amount);\n        share.burn(address(this), amount);\n\n        emit InitiateTransferShares(centrifugeId, poolId, scId, msg.sender, receiver, amount);\n\n        sender.sendInitiateTransferShares{value: msg.value}(\n            centrifugeId, poolId, scId, receiver, amount, extraGasLimit, remoteExtraGasLimit, refund\n        );\n    }\n\n    /// @inheritdoc ISpoke\n    function crosschainTransferShares(\n        uint16 centrifugeId,\n        PoolId poolId,\n        ShareClassId scId,\n        bytes32 receiver,\n        uint128 amount,\n        uint128 remoteExtraGasLimit\n    ) external payable protected {\n        crosschainTransferShares(centrifugeId, poolId, scId, receiver, amount, 0, remoteExtraGasLimit, msg.sender);\n    }\n\n    /// @inheritdoc ISpoke\n    function registerAsset(uint16 centrifugeId, address asset, uint256 tokenId, address refund)\n        external\n        payable\n        protected\n        returns (AssetId assetId)\n    {\n        string memory name;\n        string memory symbol;\n        uint8 decimals;\n\n        decimals = _safeGetAssetDecimals(asset, tokenId);\n        require(decimals >= MIN_DECIMALS, TooFewDecimals());\n        require(decimals <= MAX_DECIMALS, TooManyDecimals());\n\n        if (tokenId == 0) {\n            IERC20Metadata meta = IERC20Metadata(asset);\n            name = meta.name();\n            symbol = meta.symbol();\n        } else {\n            IERC6909MetadataExt meta = IERC6909MetadataExt(asset);\n            name = meta.name(tokenId);\n            symbol = meta.symbol(tokenId);\n        }\n\n        assetId = _assetToId[asset][tokenId];\n        bool isInitialization = assetId.raw() == 0;\n        if (isInitialization) {\n            _assetCounter++;\n            assetId = newAssetId(sender.localCentrifugeId(), _assetCounter);\n\n            _idToAsset[assetId] = AssetIdKey(asset, tokenId);\n            _assetToId[asset][tokenId] = assetId;\n        }\n\n        emit RegisterAsset(centrifugeId, assetId, asset, tokenId, name, symbol, decimals, isInitialization);\n        sender.sendRegisterAsset{value: msg.value}(centrifugeId, assetId, decimals, refund);\n    }\n\n    /// @inheritdoc ISpoke\n    function updateContract(\n        PoolId poolId,\n        ShareClassId scId,\n        bytes32 target,\n        bytes calldata payload,\n        uint128 extraGasLimit,\n        address refund\n    ) external payable {\n        emit UntrustedContractUpdate(poolId.centrifugeId(), poolId, scId, target, payload, msg.sender);\n\n        sender.sendUntrustedContractUpdate{value: msg.value}(\n            poolId, scId, target, payload, msg.sender.toBytes32(), extraGasLimit, refund\n        );\n    }\n\n    //----------------------------------------------------------------------------------------------\n    // Pool & token management\n    //----------------------------------------------------------------------------------------------\n\n    /// @inheritdoc ISpokeGatewayHandler\n    function addPool(PoolId poolId) public auth {\n        Pool storage pool_ = pool[poolId];\n        require(pool_.createdAt == 0, PoolAlreadyAdded());\n        pool_.createdAt = uint64(block.timestamp);\n        poolEscrowFactory.newEscrow(poolId);\n\n        emit AddPool(poolId);\n    }\n\n    /// @inheritdoc ISpokeGatewayHandler\n    function addShareClass(\n        PoolId poolId,\n        ShareClassId scId,\n        string memory name,\n        string memory symbol,\n        uint8 decimals,\n        bytes32 salt,\n        address hook\n    ) public auth {\n        require(isPoolActive(poolId), InvalidPool());\n        require(decimals >= MIN_DECIMALS, TooFewDecimals());\n        require(decimals <= MAX_DECIMALS, TooManyDecimals());\n        require(address(shareClass[poolId][scId].shareToken) == address(0), ShareClassAlreadyRegistered());\n\n        IShareToken shareToken_ = tokenFactory.newToken(name, symbol, decimals, salt);\n        if (hook != address(0)) shareToken_.file(\"hook\", hook);\n        linkToken(poolId, scId, shareToken_);\n    }\n\n    /// @inheritdoc ISpoke\n    function linkToken(PoolId poolId, ShareClassId scId, IShareToken shareToken_) public auth {\n        shareClass[poolId][scId].shareToken = shareToken_;\n        _tokenDetails[address(shareToken_)] = TokenDetails(poolId, scId);\n        emit AddShareClass(poolId, scId, shareToken_);\n    }\n\n    /// @inheritdoc ISpokeGatewayHandler\n    function setRequestManager(PoolId poolId, IRequestManager manager) public auth {\n        require(isPoolActive(poolId), InvalidPool());\n        requestManager[poolId] = manager;\n        emit SetRequestManager(poolId, manager);\n    }\n\n    /// @inheritdoc ISpokeGatewayHandler\n    function updateShareMetadata(PoolId poolId, ShareClassId scId, string memory name, string memory symbol)\n        public\n        auth\n    {\n        IShareToken shareToken_ = shareToken(poolId, scId);\n        require(\n            keccak256(bytes(shareToken_.name())) != keccak256(bytes(name))\n                || keccak256(bytes(shareToken_.symbol())) != keccak256(bytes(symbol)),\n            OldMetadata()\n        );\n\n        shareToken_.file(\"name\", name);\n        shareToken_.file(\"symbol\", symbol);\n    }\n\n    /// @inheritdoc ISpokeGatewayHandler\n    function updateShareHook(PoolId poolId, ShareClassId scId, address hook) public auth {\n        IShareToken shareToken_ = shareToken(poolId, scId);\n        require(hook != shareToken_.hook(), OldHook());\n        shareToken_.file(\"hook\", hook);\n    }\n\n    /// @inheritdoc ISpokeGatewayHandler\n    function updateRestriction(PoolId poolId, ShareClassId scId, bytes memory update) public auth {\n        IShareToken shareToken_ = shareToken(poolId, scId);\n        address hook = shareToken_.hook();\n        require(hook != address(0), InvalidHook());\n        ITransferHook(hook).updateRestriction(address(shareToken_), update);\n    }\n\n    /// @inheritdoc ISpokeGatewayHandler\n    function executeTransferShares(PoolId poolId, ShareClassId scId, bytes32 receiver, uint128 amount) public auth {\n        IShareToken shareToken_ = shareToken(poolId, scId);\n        shareToken_.mint(address(this), amount);\n        shareToken_.transfer(receiver.toAddress(), amount);\n        emit ExecuteTransferShares(poolId, scId, receiver.toAddress(), amount);\n    }\n\n    /// @inheritdoc ISpoke\n    function setShareTokenVault(PoolId poolId, ShareClassId scId, address asset, address vault) external auth {\n        IShareToken token = shareToken(poolId, scId);\n        token.updateVault(asset, vault);\n    }\n\n    //----------------------------------------------------------------------------------------------\n    // Price management\n    //----------------------------------------------------------------------------------------------\n\n    /// @inheritdoc ISpokeGatewayHandler\n    function updatePricePoolPerShare(PoolId poolId, ShareClassId scId, D18 price, uint64 computedAt) public auth {\n        ShareClassDetails storage shareClass_ = _shareClass(poolId, scId);\n        Price storage poolPerShare = shareClass_.pricePoolPerShare;\n        require(computedAt >= shareClass_.pricePoolPerShare.computedAt, CannotSetOlderPrice());\n\n        // Disable expiration of the price if never initialized\n        if (poolPerShare.computedAt == 0 && poolPerShare.maxAge == 0) {\n            poolPerShare.maxAge = type(uint64).max;\n        }\n\n        poolPerShare.price = price;\n        poolPerShare.computedAt = computedAt;\n        emit UpdateSharePrice(poolId, scId, price, computedAt);\n    }\n\n    /// @inheritdoc ISpokeGatewayHandler\n    function updatePricePoolPerAsset(PoolId poolId, ShareClassId scId, AssetId assetId, D18 price, uint64 computedAt)\n        public\n        auth\n    {\n        (address asset, uint256 tokenId) = idToAsset(assetId);\n        Price storage poolPerAsset = _pricePoolPerAsset[poolId][scId][assetId];\n        require(computedAt >= poolPerAsset.computedAt, CannotSetOlderPrice());\n\n        // Disable expiration of the price if never initialized\n        if (poolPerAsset.computedAt == 0 && poolPerAsset.maxAge == 0) {\n            poolPerAsset.maxAge = type(uint64).max;\n        }\n\n        poolPerAsset.price = price;\n        poolPerAsset.computedAt = computedAt;\n        emit UpdateAssetPrice(poolId, scId, asset, tokenId, price, computedAt);\n    }\n\n    function setMaxSharePriceAge(PoolId poolId, ShareClassId scId, uint64 maxPriceAge) external auth {\n        ShareClassDetails storage shareClass_ = _shareClass(poolId, scId);\n        shareClass_.pricePoolPerShare.maxAge = maxPriceAge;\n        emit UpdateMaxSharePriceAge(poolId, scId, maxPriceAge);\n    }\n\n    function setMaxAssetPriceAge(PoolId poolId, ShareClassId scId, AssetId assetId, uint64 maxPriceAge) external auth {\n        (address asset, uint256 tokenId) = idToAsset(assetId);\n        _pricePoolPerAsset[poolId][scId][assetId].maxAge = maxPriceAge;\n        emit UpdateMaxAssetPriceAge(poolId, scId, asset, tokenId, maxPriceAge);\n    }\n\n    //----------------------------------------------------------------------------------------------\n    // Request management\n    //----------------------------------------------------------------------------------------------\n\n    /// @inheritdoc ISpoke\n    function request(\n        PoolId poolId,\n        ShareClassId scId,\n        AssetId assetId,\n        bytes memory payload,\n        uint128 extraGasLimit,\n        bool unpaid,\n        address refund\n    ) external payable {\n        IRequestManager manager = requestManager[poolId];\n        require(address(manager) != address(0), InvalidRequestManager());\n        require(msg.sender == address(manager), NotAuthorized());\n\n        sender.sendRequest{value: msg.value}(poolId, scId, assetId, payload, extraGasLimit, unpaid, refund);\n    }\n\n    /// @inheritdoc ISpokeGatewayHandler\n    function requestCallback(PoolId poolId, ShareClassId scId, AssetId assetId, bytes memory payload) external auth {\n        IRequestManager manager = requestManager[poolId];\n        require(address(manager) != address(0), InvalidRequestManager());\n\n        manager.callback(poolId, scId, assetId, payload);\n    }\n\n    //----------------------------------------------------------------------------------------------\n    // View methods\n    //----------------------------------------------------------------------------------------------\n\n    /// @inheritdoc ISpoke\n    function isPoolActive(PoolId poolId) public view returns (bool) {\n        return pool[poolId].createdAt > 0;\n    }\n\n    /// @inheritdoc ISpoke\n    function shareToken(PoolId poolId, ShareClassId scId) public view returns (IShareToken) {\n        return _shareClass(poolId, scId).shareToken;\n    }\n\n    /// @inheritdoc ISpoke\n    function idToAsset(AssetId assetId) public view returns (address asset, uint256 tokenId) {\n        AssetIdKey memory assetIdKey = _idToAsset[assetId];\n        require(assetIdKey.asset != address(0), UnknownAsset());\n        return (assetIdKey.asset, assetIdKey.tokenId);\n    }\n\n    /// @inheritdoc ISpoke\n    function assetToId(address asset, uint256 tokenId) public view returns (AssetId assetId) {\n        assetId = _assetToId[asset][tokenId];\n        require(assetId.raw() != 0, UnknownAsset());\n    }\n\n    /// @inheritdoc ISpoke\n    function shareTokenDetails(address shareToken_) public view returns (PoolId poolId, ShareClassId scId) {\n        TokenDetails storage details = _tokenDetails[shareToken_];\n        poolId = details.poolId;\n        scId = details.scId;\n        require(!poolId.isNull() && !scId.isNull(), ShareTokenDoesNotExist());\n    }\n\n    /// @inheritdoc ISpoke\n    function pricePoolPerShare(PoolId poolId, ShareClassId scId, bool checkValidity) public view returns (D18 price) {\n        ShareClassDetails storage shareClass_ = _shareClass(poolId, scId);\n        require(!checkValidity || shareClass_.pricePoolPerShare.isValid(), InvalidPrice());\n\n        return shareClass_.pricePoolPerShare.price;\n    }\n\n    /// @inheritdoc ISpoke\n    function pricePoolPerAsset(PoolId poolId, ShareClassId scId, AssetId assetId, bool checkValidity)\n        public\n        view\n        returns (D18 price)\n    {\n        Price memory poolPerAsset = _pricePoolPerAsset[poolId][scId][assetId];\n        require(!checkValidity || poolPerAsset.isValid(), InvalidPrice());\n\n        return poolPerAsset.price;\n    }\n\n    /// @inheritdoc ISpoke\n    function pricesPoolPer(PoolId poolId, ShareClassId scId, AssetId assetId, bool checkValidity)\n        public\n        view\n        returns (D18 pricePoolPerAsset_, D18 pricePoolPerShare_)\n    {\n        ShareClassDetails storage shareClass_ = _shareClass(poolId, scId);\n\n        Price memory poolPerAsset = _pricePoolPerAsset[poolId][scId][assetId];\n        Price memory poolPerShare = shareClass_.pricePoolPerShare;\n\n        require(!checkValidity || poolPerAsset.isValid() && poolPerShare.isValid(), InvalidPrice());\n\n        return (poolPerAsset.price, poolPerShare.price);\n    }\n\n    /// @inheritdoc ISpoke\n    function markersPricePoolPerShare(PoolId poolId, ShareClassId scId)\n        external\n        view\n        returns (uint64 computedAt, uint64 maxAge, uint64 validUntil)\n    {\n        ShareClassDetails storage shareClass_ = _shareClass(poolId, scId);\n        computedAt = shareClass_.pricePoolPerShare.computedAt;\n        maxAge = shareClass_.pricePoolPerShare.maxAge;\n        validUntil = shareClass_.pricePoolPerShare.validUntil();\n    }\n\n    /// @inheritdoc ISpoke\n    function markersPricePoolPerAsset(PoolId poolId, ShareClassId scId, AssetId assetId)\n        external\n        view\n        returns (uint64 computedAt, uint64 maxAge, uint64 validUntil)\n    {\n        Price memory poolPerAsset = _pricePoolPerAsset[poolId][scId][assetId];\n        computedAt = poolPerAsset.computedAt;\n        maxAge = poolPerAsset.maxAge;\n        validUntil = poolPerAsset.validUntil();\n    }\n\n    //----------------------------------------------------------------------------------------------\n    // Internal methods\n    //----------------------------------------------------------------------------------------------\n\n    function _safeGetAssetDecimals(address asset, uint256 tokenId) private view returns (uint8) {\n        bytes memory callData;\n\n        if (tokenId == 0) {\n            callData = abi.encodeCall(IERC20Metadata.decimals, ());\n        } else {\n            callData = abi.encodeCall(IERC6909MetadataExt.decimals, tokenId);\n        }\n\n        (bool success, bytes memory data) = asset.staticcall(callData);\n        require(success && data.length >= 32, AssetMissingDecimals());\n\n        return abi.decode(data, (uint8));\n    }\n\n    function _shareClass(PoolId poolId, ShareClassId scId)\n        internal\n        view\n        returns (ShareClassDetails storage shareClass_)\n    {\n        shareClass_ = shareClass[poolId][scId];\n        require(address(shareClass_.shareToken) != address(0), ShareTokenDoesNotExist());\n    }\n}\n","deployed_bytecode":"0x6080604052600436106101e0575f3560e01c8063116191b6146101e457806318a96c29146102195780631f1b5aba146102585780632b67cde0146102795780632b89610114610298578063323d900f146102b757806339ceb095146103865780633a4ba8bf1461039957806344211693146103b85780634869ac69146103d75780634faac801146103f65780635274887b146104095780635d67c59e146104355780635f3e849f1461045457806365fae35e14610473578063668b4c1f1461049257806367e404ce146104d95780636aa6f457146104f85780636ea6e0a11461052c5780638004add31461054b5780638601872c1461055e5780638725b3f3146105a7578063931efb54146105c6578063947b330a146105e55780639c52a7f114610604578063ac5cbed914610623578063bccbfa8914610642578063bf353dbb14610661578063c05ff1521461069a578063c2b656c3146106b9578063c6526074146106cc578063cee8983d146106fb578063d490e7c214610728578063d4e8be8314610747578063da17f41714610766578063db057f1b146107a7578063db1b3cdc146107ba578063e77772fe146107d9578063eece6c43146107f8578063f60b8b1914610817578063fb59077a14610836578063fd6906ed14610855575b5f5ffd5b3480156101ef575f5ffd5b50600154610203906001600160a01b031681565b60405161021091906134ef565b60405180910390f35b348015610224575f5ffd5b5061023861023336600461355d565b610874565b604080516001600160801b03938416815292909116602083015201610210565b348015610263575f5ffd5b50610277610272366004613672565b61096c565b005b348015610284575f5ffd5b50600454610203906001600160a01b031681565b3480156102a3575f5ffd5b506102776102b23660046136c3565b610a94565b3480156102c2575f5ffd5b5061033e6102d13660046136de565b600760209081525f9283526040808420825291835291819020805482516060810184526001909201546001600160801b03811683526001600160401b03600160801b8204811695840195909552600160c01b9004909316918101919091526001600160a01b039091169082565b604080516001600160a01b03909316835281516001600160801b03166020808501919091528201516001600160401b0390811684830152910151166060820152608001610210565b610277610394366004613720565b610bbe565b3480156103a4575f5ffd5b506102776103b3366004613793565b610c47565b3480156103c3575f5ffd5b506102776103d2366004613812565b610dd5565b3480156103e2575f5ffd5b506102776103f1366004613849565b610e95565b6102776104043660046138a0565b610fdd565b348015610414575f5ffd5b50610428610423366004613939565b6115c4565b604051610210919061397f565b348015610440575f5ffd5b5061027761044f366004613993565b611655565b34801561045f575f5ffd5b5061027761046e3660046139df565b6116c9565b34801561047e575f5ffd5b5061027761048d366004613a1d565b611737565b34801561049d575f5ffd5b506104b16104ac366004613a1d565b6117aa565b604080516001600160401b0390931683526001600160801b0319909116602083015201610210565b3480156104e4575f5ffd5b50600354610203906001600160a01b031681565b348015610503575f5ffd5b506102036105123660046136c3565b60066020525f90815260409020546001600160a01b031681565b348015610537575f5ffd5b50610277610546366004613a46565b611815565b610277610559366004613afa565b6119f3565b348015610569575f5ffd5b5061057d6105783660046136de565b611ac9565b604080516001600160401b0394851681529284166020840152921691810191909152606001610210565b3480156105b2575f5ffd5b5061057d6105c1366004613bb2565b611b34565b3480156105d1575f5ffd5b506102776105e0366004613bed565b611bbd565b3480156105f0575f5ffd5b506102776105ff366004613c72565b611d88565b34801561060f575f5ffd5b5061027761061e366004613a1d565b611e4d565b34801561062e575f5ffd5b5061042861063d366004613cb7565b611ebf565b34801561064d575f5ffd5b5061027761065c366004613ce1565b611f12565b34801561066c575f5ffd5b5061068c61067b366004613a1d565b5f6020819052908152604090205481565b604051908152602001610210565b3480156106a5575f5ffd5b506102036106b43660046136de565b612086565b6102776106c7366004613d24565b6120a2565b3480156106d7575f5ffd5b506106eb6106e63660046136c3565b612180565b6040519015158152602001610210565b348015610706575f5ffd5b5061071a610715366004613dba565b61219f565b604051610210929190613dd5565b348015610733575f5ffd5b50610277610742366004613849565b61220d565b348015610752575f5ffd5b50610277610761366004613dee565b6122f3565b348015610771575f5ffd5b5061079a6107803660046136c3565b60056020525f90815260409020546001600160401b031681565b6040516102109190613e11565b6104286107b5366004613e25565b61243d565b3480156107c5575f5ffd5b506102776107d4366004613e6a565b612cd2565b3480156107e4575f5ffd5b50600254610203906001600160a01b031681565b348015610803575f5ffd5b50610277610812366004613ec0565b612d72565b348015610822575f5ffd5b50610277610831366004613efb565b612e2b565b348015610841575f5ffd5b50610277610850366004613efb565b612f24565b348015610860575f5ffd5b5061042861086f36600461355d565b613046565b5f5f5f61088187876130ee565b6001600160401b038089165f908152600c602090815260408083206001600160801b03198c16845282528083206001600160801b038b811685529083529281902081516060808201845291548086168252600160801b808204881683870152600160c01b918290048816838601528451938401855260018901549687168452860487169483019490945292909304909316928201929092529192509085158061093e575061092e82613142565b801561093e575061093e81613142565b61095a5760405162bfc92160e01b815260040160405180910390fd5b90519051909890975095505050505050565b335f9081526020819052604090205460011461099b5760405163ea8e4eb560e01b815260040160405180910390fd5b5f6109a68484612086565b90505f816001600160a01b0316637f5a7c7b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156109e5573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a099190613f36565b90506001600160a01b038116610a3257604051639c9d882360e01b815260040160405180910390fd5b604051637aeba8d560e01b81526001600160a01b03821690637aeba8d590610a609085908790600401613f7f565b5f604051808303815f87803b158015610a77575f5ffd5b505af1158015610a89573d5f5f3e3d5ffd5b505050505050505050565b335f90815260208190526040902054600114610ac35760405163ea8e4eb560e01b815260040160405180910390fd5b6001600160401b038082165f908152600560205260409020805490911615610afe57604051633caf458560e01b815260040160405180910390fd5b80546001600160401b031916426001600160401b03161781556004805460405163388830bd60e11b81526001600160a01b0390911691637110617a91610b4691869101613e11565b6020604051808303815f875af1158015610b62573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b869190613f36565b506040516001600160401b038316907f28d6040dea8c2130b7a53f31f1c59e0771c45cac20965972891b1bdea59a1256905f90a25050565b5f5c6001600160a01b0316610c0557335f805c6001600160a01b0319168217905d50610bf086868686865f8733610fdd565b5f6001600160a01b0319815c16815d50610c3f565b336001600160a01b035f5c1614610c2f57604051630101292160e31b815260040160405180910390fd5b610c3f86868686865f8733610fdd565b505050505050565b335f90815260208190526040902054600114610c765760405163ea8e4eb560e01b815260040160405180910390fd5b5f5f610c818561219f565b6001600160401b03808a165f908152600c602090815260408083206001600160801b03198d16845282528083206001600160801b038c168452909152902080549395509193509091600160801b900481169085161015610cf45760405163957919e960e01b815260040160405180910390fd5b8054600160801b90046001600160401b0316158015610d2257508054600160c01b90046001600160401b0316155b15610d3f5780546001600160c01b03166001600160c01b03191781555b80546001600160801b0386166001600160c01b03199091168117600160801b6001600160401b038781169182029290921784556040805186815260208101949094528301526001600160a01b038516916001600160801b03198a16918b16907f808cd3ba373a28daeb965ce9e1dc2af3beaaa9f9a4e3c3f2431d0378eb6962a99060600160405180910390a45050505050505050565b335f90815260208190526040902054600114610e045760405163ea8e4eb560e01b815260040160405180910390fd5b610e0d82612180565b610e295760405162820f3560e61b815260040160405180910390fd5b6001600160401b0382165f818152600660205260409081902080546001600160a01b0319166001600160a01b038516179055517f7e6e289a79525732885fc1693691e8155df216a64630e31000a81b71e1f592d090610e899084906134ef565b60405180910390a25050565b335f90815260208190526040902054600114610ec45760405163ea8e4eb560e01b815260040160405180910390fd5b5f610ecf85856130ee565b600181018054919250906001600160401b03600160801b90910481169084161015610f0d5760405163957919e960e01b815260040160405180910390fd5b8054600160801b90046001600160401b0316158015610f3b57508054600160c01b90046001600160401b0316155b15610f585780546001600160c01b03166001600160c01b03191781555b80546001600160801b0385166001600160c01b03199091168117600160801b6001600160401b038681169182029290921784556040805193845260208401919091526001600160801b0319881692918916917f50ae94913f401513d2eded2f37844a070743c57ff5148fcfaf081085653a2856910160405180910390a3505050505050565b5f5c6001600160a01b03166112d357335f805c6001600160a01b0319168217905d505f61100a8888612086565b905060035f9054906101000a90046001600160a01b03166001600160a01b0316630a14789a6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561105c573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110809190613fa2565b61ffff168961ffff16036110a75760405163e9e4330360e01b815260040160405180910390fd5b604051630fa1e71360e41b81526001600160a01b0382169063fa1e7130906110db90339061ffff8e16908a90600401613fbd565b602060405180830381865afa1580156110f6573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061111a9190613fe9565b61113757604051632ba542af60e01b815260040160405180910390fd5b60405163887ca24960e01b81526001600160a01b0382169063887ca24990611169903390819030908b90600401614004565b6020604051808303815f875af1158015611185573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111a99190613fe9565b50604051632770a7eb60e21b81526001600160a01b03821690639dc29fac906111d89030908990600401614036565b5f604051808303815f87803b1580156111ef575f5ffd5b505af1158015611201573d5f5f3e3d5ffd5b50505050336001600160a01b0316876001600160801b031916896001600160401b03165f5160206144cb5f395f51905f528c8a8a60405161124493929190614058565b60405180910390a4600354604051631b17a41b60e21b81526001600160a01b0390911690636c5e906c90349061128c908d908d908d908d908d908d908d908d9060040161407d565b5f604051808303818588803b1580156112a3575f5ffd5b505af11580156112b5573d5f5f3e3d5ffd5b505f9450506001600160a01b0319845c169250839150505d506115ba565b336001600160a01b035f5c16146112fd57604051630101292160e31b815260040160405180910390fd5b5f6113088888612086565b905060035f9054906101000a90046001600160a01b03166001600160a01b0316630a14789a6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561135a573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061137e9190613fa2565b61ffff168961ffff16036113a55760405163e9e4330360e01b815260040160405180910390fd5b604051630fa1e71360e41b81526001600160a01b0382169063fa1e7130906113d990339061ffff8e16908a90600401613fbd565b602060405180830381865afa1580156113f4573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906114189190613fe9565b61143557604051632ba542af60e01b815260040160405180910390fd5b60405163887ca24960e01b81526001600160a01b0382169063887ca24990611467903390819030908b90600401614004565b6020604051808303815f875af1158015611483573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906114a79190613fe9565b50604051632770a7eb60e21b81526001600160a01b03821690639dc29fac906114d69030908990600401614036565b5f604051808303815f87803b1580156114ed575f5ffd5b505af11580156114ff573d5f5f3e3d5ffd5b50505050336001600160a01b0316876001600160801b031916896001600160401b03165f5160206144cb5f395f51905f528c8a8a60405161154293929190614058565b60405180910390a4600354604051631b17a41b60e21b81526001600160a01b0390911690636c5e906c90349061158a908d908d908d908d908d908d908d908d9060040161407d565b5f604051808303818588803b1580156115a1575f5ffd5b505af11580156115b3573d5f5f3e3d5ffd5b5050505050505b5050505050505050565b5f5f6115d085856130ee565b905082158061162457506040805160608101825260018301546001600160801b03811682526001600160401b03600160801b820481166020840152600160c01b909104169181019190915261162490613142565b6116405760405162bfc92160e01b815260040160405180910390fd5b600101546001600160801b0316949350505050565b335f908152602081905260409020546001146116845760405163ea8e4eb560e01b815260040160405180910390fd5b5f61168f8585612086565b604051630368a3a560e31b81526001600160a01b038581166004830152848116602483015291925090821690631b451d2890604401610a60565b335f908152602081905260409020546001146116f85760405163ea8e4eb560e01b815260040160405180910390fd5b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b0384160161172c57611727828261317e565b505050565b611727838383613208565b335f908152602081905260409020546001146117665760405163ea8e4eb560e01b815260040160405180910390fd5b6001600160a01b0381165f8181526020819052604080822060019055517fdd0e34038ac38b2a1ce960229778ac48a8719bc900b6c4f8d0475c6e8b385a609190a250565b6001600160a01b0381165f908152600a6020526040902080546001600160401b03811691600160401b90910460801b9082151580156117f257506001600160801b0319821615155b61180f57604051630344039160e61b815260040160405180910390fd5b50915091565b335f908152602081905260409020546001146118445760405163ea8e4eb560e01b815260040160405180910390fd5b61184d87612180565b6118695760405162820f3560e61b815260040160405180910390fd5b600260ff8416101561188e57604051633f78ded760e01b815260040160405180910390fd5b601260ff841611156118b3576040516330e571f960e11b815260040160405180910390fd5b6001600160401b0387165f9081526007602090815260408083206001600160801b03198a1684529091529020546001600160a01b0316156119075760405163019163ff60e11b815260040160405180910390fd5b6002546040516362e92b0760e01b81525f916001600160a01b0316906362e92b079061193d9089908990899089906004016140e4565b6020604051808303815f875af1158015611959573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061197d9190613f36565b90506001600160a01b038216156119e85760405163d4e8be8360e01b81526001600160a01b0382169063d4e8be83906119ba90859060040161411f565b5f604051808303815f87803b1580156119d1575f5ffd5b505af11580156119e3573d5f5f3e3d5ffd5b505050505b6115ba888883612e2b565b336001600160401b038816603089901c61ffff1661ffff167f18910e041c7e37349ae25debc64b0f4f44af0b288a55d48f6c8565a9d76ad88289898989604051611a409493929190614168565b60405180910390a46003546001600160a01b03166363900d623489898989893360601b6001600160601b0319168a8a6040518a63ffffffff1660e01b8152600401611a92989796959493929190614194565b5f604051808303818588803b158015611aa9575f5ffd5b505af1158015611abb573d5f5f3e3d5ffd5b505050505050505050505050565b5f5f5f5f611ad786866130ee565b6001810154604080516060810182526001600160801b03831681526001600160401b03600160801b8404811660208301819052600160c01b909404169181018290529196509450909150611b2a9061334e565b9150509250925092565b6001600160401b038084165f908152600c602090815260408083206001600160801b03198716845282528083206001600160801b038681168552908352818420825160608101845290549182168152600160801b82048616938101849052600160c01b9091049094169084018190529092909190611bb18161334e565b91505093509350939050565b335f90815260208190526040902054600114611bec5760405163ea8e4eb560e01b815260040160405180910390fd5b5f611bf78585612086565b90508280519060200120816001600160a01b03166306fdde036040518163ffffffff1660e01b81526004015f60405180830381865afa158015611c3c573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052611c639190810190614201565b80519060200120141580611ce657508180519060200120816001600160a01b03166395d89b416040518163ffffffff1660e01b81526004015f60405180830381865afa158015611cb5573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052611cdc9190810190614201565b8051906020012014155b611d035760405163d7e605c360e01b815260040160405180910390fd5b6040516304bd623760e11b81526001600160a01b0382169063097ac46e90611d2f908690600401614275565b5f604051808303815f87803b158015611d46575f5ffd5b505af1158015611d58573d5f5f3e3d5ffd5b50506040516304bd623760e11b81526001600160a01b038416925063097ac46e9150610a60908590600401614294565b335f90815260208190526040902054600114611db75760405163ea8e4eb560e01b815260040160405180910390fd5b825f03611dce57611dc98483836116c9565b611e47565b6040516304ade6db60e11b81526001600160a01b038381166004830152602482018590526044820183905285169063095bcdb6906064016020604051808303815f875af1158015611e21573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611e459190613fe9565b505b50505050565b335f90815260208190526040902054600114611e7c5760405163ea8e4eb560e01b815260040160405180910390fd5b6001600160a01b0381165f81815260208190526040808220829055517f184450df2e323acec0ed3b5c7531b81f9b4cdef7914dfd4c0a4317416bb5251b9190a250565b6001600160a01b0382165f908152600b602090815260408083208484529091528120546001600160801b031690819003611f0c5760405163c97d95cf60e01b815260040160405180910390fd5b92915050565b335f90815260208190526040902054600114611f415760405163ea8e4eb560e01b815260040160405180910390fd5b5f611f4c8585612086565b6040516340c10f1960e01b81529091506001600160a01b038216906340c10f1990611f7d9030908690600401614036565b5f604051808303815f87803b158015611f94575f5ffd5b505af1158015611fa6573d5f5f3e3d5ffd5b50505050806001600160a01b031663a9059cbb611fc285613380565b846040518363ffffffff1660e01b8152600401611fe0929190614036565b6020604051808303815f875af1158015611ffc573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906120209190613fe9565b5061202a83613380565b6001600160a01b0316846001600160801b031916866001600160401b03167f646bf4da76b559478ffb33bb35acfe75c89ebe6b145c823775910ae16b17f84585604051612077919061397f565b60405180910390a45050505050565b5f61209183836130ee565b546001600160a01b03169392505050565b6001600160401b0387165f908152600660205260409020546001600160a01b0316806120e157604051632131eb8160e11b815260040160405180910390fd5b336001600160a01b0382161461210a5760405163ea8e4eb560e01b815260040160405180910390fd5b600354604051632ecc233760e21b81526001600160a01b039091169063bb308cdc903490612148908c908c908c908c908c908c908c906004016142b5565b5f604051808303818588803b15801561215f575f5ffd5b505af1158015612171573d5f5f3e3d5ffd5b50505050505050505050505050565b6001600160401b039081165f9081526005602052604090205416151590565b6001600160801b0381165f908152600960209081526040808320815180830190925280546001600160a01b03168083526001909101549282019290925282916121fb5760405163c97d95cf60e01b815260040160405180910390fd5b80516020909101519094909350915050565b335f9081526020819052604090205460011461223c5760405163ea8e4eb560e01b815260040160405180910390fd5b5f5f6122478461219f565b6001600160401b038881165f818152600c602090815260408083206001600160801b03198d168085529083528184206001600160801b038d16855283529281902080546001600160c01b0316600160c01b968c169687021790558051868152918201949094529496509294506001600160a01b0386169390917fd0c6def17ddcc3d8efe57bf365c0bef197870035a47752f720fc601eff9c0b3d910160405180910390a4505050505050565b335f908152602081905260409020546001146123225760405163ea8e4eb560e01b815260040160405180910390fd5b81666761746577617960c81b0361235357600180546001600160a01b0319166001600160a01b03831617905561240d565b816539b2b73232b960d11b0361238357600380546001600160a01b0319166001600160a01b03831617905561240d565b816b746f6b656e466163746f727960a01b036123b957600280546001600160a01b0319166001600160a01b03831617905561240d565b8170706f6f6c457363726f77466163746f727960781b036123f457600480546001600160a01b0319166001600160a01b03831617905561240d565b604051633db0d5b960e01b815260040160405180910390fd5b817f8fef588b5fc1afbf5b2f06c1a435d513f208da2e6704c3d8f0e0ec91167066ba82604051610e8991906134ef565b5f805c6001600160a01b03166128a657335f805c6001600160a01b0319168217905d506060805f61246e87876133b0565b9050600260ff8216101561249557604051633f78ded760e01b815260040160405180910390fd5b601260ff821611156124ba576040516330e571f960e11b815260040160405180910390fd5b855f03612593575f879050806001600160a01b03166306fdde036040518163ffffffff1660e01b81526004015f60405180830381865afa158015612500573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526125279190810190614201565b9350806001600160a01b03166395d89b416040518163ffffffff1660e01b81526004015f60405180830381865afa158015612564573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f1916820160405261258b9190810190614201565b92505061266c565b604051622b600360e21b81526004810187905287906001600160a01b0382169062ad800c906024015f60405180830381865afa1580156125d5573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526125fc9190810190614201565b604051634e41a1fb60e01b8152600481018990529094506001600160a01b03821690634e41a1fb906024015f60405180830381865afa158015612641573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526126689190810190614201565b9250505b6001600160a01b0387165f908152600b602090815260408083208984529091529020546001600160801b03169350831580156127e357600880546001600160401b0316905f6126ba8361433c565b91906101000a8154816001600160401b0302191690836001600160401b031602179055505061276760035f9054906101000a90046001600160a01b03166001600160a01b0316630a14789a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612732573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906127569190613fa2565b6008546001600160401b03166134c9565b6040805180820182526001600160a01b038b811680835260208084018d81526001600160801b0387165f81815260098452878120965187546001600160a01b03191696169590951786559051600190950194909455908252600b81528382208c835290529190912080546001600160801b031916909117905594505b86886001600160a01b0316866001600160801b03165f5160206144eb5f395f51905f528c8888888860405161281c959493929190614367565b60405180910390a46003546040516346458fc760e11b81526001600160a01b0390911690638c8b1f8e90349061285c908d908a9088908d906004016143b2565b5f604051808303818588803b158015612873575f5ffd5b505af1158015612885573d5f5f3e3d5ffd5b505f9750506001600160a01b0319875c169550869450505050505d50612cca565b336001600160a01b035f5c16146128d057604051630101292160e31b815260040160405180910390fd5b6060805f6128de87876133b0565b9050600260ff8216101561290557604051633f78ded760e01b815260040160405180910390fd5b601260ff8216111561292a576040516330e571f960e11b815260040160405180910390fd5b855f03612a03575f879050806001600160a01b03166306fdde036040518163ffffffff1660e01b81526004015f60405180830381865afa158015612970573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526129979190810190614201565b9350806001600160a01b03166395d89b416040518163ffffffff1660e01b81526004015f60405180830381865afa1580156129d4573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526129fb9190810190614201565b925050612adc565b604051622b600360e21b81526004810187905287906001600160a01b0382169062ad800c906024015f60405180830381865afa158015612a45573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052612a6c9190810190614201565b604051634e41a1fb60e01b8152600481018990529094506001600160a01b03821690634e41a1fb906024015f60405180830381865afa158015612ab1573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052612ad89190810190614201565b9250505b6001600160a01b0387165f908152600b602090815260408083208984529091529020546001600160801b0316935083158015612c1e57600880546001600160401b0316905f612b2a8361433c565b91906101000a8154816001600160401b0302191690836001600160401b0316021790555050612ba260035f9054906101000a90046001600160a01b03166001600160a01b0316630a14789a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612732573d5f5f3e3d5ffd5b6040805180820182526001600160a01b038b811680835260208084018d81526001600160801b0387165f81815260098452878120965187546001600160a01b03191696169590951786559051600190950194909455908252600b81528382208c835290529190912080546001600160801b031916909117905594505b86886001600160a01b0316866001600160801b03165f5160206144eb5f395f51905f528c88888888604051612c57959493929190614367565b60405180910390a46003546040516346458fc760e11b81526001600160a01b0390911690638c8b1f8e903490612c97908d908a9088908d906004016143b2565b5f604051808303818588803b158015612cae575f5ffd5b505af1158015612cc0573d5f5f3e3d5ffd5b5050505050505050505b949350505050565b335f90815260208190526040902054600114612d015760405163ea8e4eb560e01b815260040160405180910390fd5b6001600160401b0384165f908152600660205260409020546001600160a01b031680612d4057604051632131eb8160e11b815260040160405180910390fd5b604051631c0b2ad560e21b81526001600160a01b0382169063702cab5490610a609088908890889088906004016143e8565b335f90815260208190526040902054600114612da15760405163ea8e4eb560e01b815260040160405180910390fd5b5f612dac84846130ee565b905081816001015f0160186101000a8154816001600160401b0302191690836001600160401b03160217905550826001600160801b031916846001600160401b03167fd566c97f11867171a51ecec2586f08002bff134b1819350c5417d12feca54aee84604051612e1d9190613e11565b60405180910390a350505050565b335f90815260208190526040902054600114612e5a5760405163ea8e4eb560e01b815260040160405180910390fd5b6001600160401b038084165f8181526007602090815260408083206001600160801b0319881680855290835281842080546001600160a01b0389166001600160a01b0319909116811790915582518084018452868152808501838152918652600a9094529382902092518354945160801c600160401b026001600160c01b0319909516961695909517929092179055517fe69d7376db85d5607fd179347a15f31913add0e3ada2b1e5e205120a8f6d9e4490612f179085906134ef565b60405180910390a3505050565b335f90815260208190526040902054600114612f535760405163ea8e4eb560e01b815260040160405180910390fd5b5f612f5e8484612086565b9050806001600160a01b0316637f5a7c7b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612f9c573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612fc09190613f36565b6001600160a01b0316826001600160a01b031603612ff157604051632a53f92160e11b815260040160405180910390fd5b60405163d4e8be8360e01b81526001600160a01b0382169063d4e8be839061301d90859060040161411f565b5f604051808303815f87803b158015613034575f5ffd5b505af11580156115ba573d5f5f3e3d5ffd5b6001600160401b038085165f908152600c602090815260408083206001600160801b03198816845282528083206001600160801b038781168552908352818420825160608101845290549182168152600160801b8204861693810193909352600160c01b900490931692810192909252908215806130c857506130c881613142565b6130e45760405162bfc92160e01b815260040160405180910390fd5b5195945050505050565b6001600160401b0382165f9081526007602090815260408083206001600160801b031985168452909152902080546001600160a01b0316611f0c57604051630344039160e61b815260040160405180910390fd5b5f81602001516001600160401b03165f14613172576131608261334e565b6001600160401b031642111592915050565b505f919050565b919050565b604080515f808252602082019092526001600160a01b0384169083906040516131a7919061442a565b5f6040518083038185875af1925050503d805f81146131e1576040519150601f19603f3d011682016040523d82523d5f602084013e6131e6565b606091505b505090508061172757604051630d2fa21160e31b815260040160405180910390fd5b5f836001600160a01b03163b1161323257604051633c11a9c560e21b815260040160405180910390fd5b5f5f846001600160a01b03168484604051602401613251929190613dd5565b60408051601f198184030181529181526020820180516001600160e01b031663a9059cbb60e01b17905251613286919061442a565b5f604051808303815f865af19150503d805f81146132bf576040519150601f19603f3d011682016040523d82523d5f602084013e6132c4565b606091505b50915091508180156132ee5750805115806132ee5750808060200190518101906132ee9190613fe9565b6040805160048152602481019091526020810180516001600160e01b031663fb7f507960e01b179052869163a9059cbb60e01b918491610a89576040516390bfb86560e01b81526004016133459493929190614440565b60405180910390fd5b604081015160208201515f918101906001600160401b039081169082161015611f0c57506001600160401b0392915050565b5f6001600160601b038216156133a95760405163e8bd165960e01b815260040160405180910390fd5b5060601c90565b5f6060825f036133e957506040805160048152602481019091526020810180516001600160e01b031663313ce56760e01b179052613423565b6040516024810184905260440160408051601f198184030181529190526020810180516001600160e01b0316631fa3f33160e11b17905290505b5f5f856001600160a01b03168360405161343d919061442a565b5f60405180830381855afa9150503d805f8114613475576040519150601f19603f3d011682016040523d82523d5f602084013e61347a565b606091505b509150915081801561348e57506020815110155b6134ab576040516366b0142960e01b815260040160405180910390fd5b808060200190518101906134bf9190614490565b9695505050505050565b5f6134e86001600160401b03831661ffff60701b607086901b166144ab565b9392505050565b6001600160a01b0391909116815260200190565b6001600160401b0381168114613517575f5ffd5b50565b80356001600160801b031981168114613179575f5ffd5b6001600160801b0381168114613517575f5ffd5b803561317981613531565b8015158114613517575f5ffd5b5f5f5f5f60808587031215613570575f5ffd5b843561357b81613503565b93506135896020860161351a565b9250604085013561359981613531565b915060608501356135a981613550565b939692955090935050565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f191681016001600160401b03811182821017156135f0576135f06135b4565b604052919050565b5f6001600160401b03821115613610576136106135b4565b50601f01601f191660200190565b5f82601f83011261362d575f5ffd5b8135602083015f613645613640846135f8565b6135c8565b9050828152858383011115613658575f5ffd5b828260208301375f92810160200192909252509392505050565b5f5f5f60608486031215613684575f5ffd5b833561368f81613503565b925061369d6020850161351a565b915060408401356001600160401b038111156136b7575f5ffd5b611b2a8682870161361e565b5f602082840312156136d3575f5ffd5b81356134e881613503565b5f5f604083850312156136ef575f5ffd5b82356136fa81613503565b91506137086020840161351a565b90509250929050565b61ffff81168114613517575f5ffd5b5f5f5f5f5f5f60c08789031215613735575f5ffd5b863561374081613711565b9550602087013561375081613503565b945061375e6040880161351a565b935060608701359250608087013561377581613531565b915060a087013561378581613531565b809150509295509295509295565b5f5f5f5f5f60a086880312156137a7575f5ffd5b85356137b281613503565b94506137c06020870161351a565b935060408601356137d081613531565b925060608601356137e081613531565b915060808601356137f081613503565b809150509295509295909350565b6001600160a01b0381168114613517575f5ffd5b5f5f60408385031215613823575f5ffd5b823561382e81613503565b9150602083013561383e816137fe565b809150509250929050565b5f5f5f5f6080858703121561385c575f5ffd5b843561386781613503565b93506138756020860161351a565b9250604085013561388581613531565b915060608501356135a981613503565b8035613179816137fe565b5f5f5f5f5f5f5f5f610100898b0312156138b8575f5ffd5b88356138c381613711565b975060208901356138d381613503565b96506138e160408a0161351a565b95506060890135945060808901356138f881613531565b935060a089013561390881613531565b925060c089013561391881613531565b915060e0890135613928816137fe565b809150509295985092959890939650565b5f5f5f6060848603121561394b575f5ffd5b833561395681613503565b92506139646020850161351a565b9150604084013561397481613550565b809150509250925092565b6001600160801b0391909116815260200190565b5f5f5f5f608085870312156139a6575f5ffd5b84356139b181613503565b93506139bf6020860161351a565b925060408501356139cf816137fe565b915060608501356135a9816137fe565b5f5f5f606084860312156139f1575f5ffd5b83356139fc816137fe565b92506020840135613a0c816137fe565b929592945050506040919091013590565b5f60208284031215613a2d575f5ffd5b81356134e8816137fe565b60ff81168114613517575f5ffd5b5f5f5f5f5f5f5f60e0888a031215613a5c575f5ffd5b8735613a6781613503565b9650613a756020890161351a565b955060408801356001600160401b03811115613a8f575f5ffd5b613a9b8a828b0161361e565b95505060608801356001600160401b03811115613ab6575f5ffd5b613ac28a828b0161361e565b9450506080880135613ad381613a38565b925060a0880135915060c0880135613aea816137fe565b8091505092959891949750929550565b5f5f5f5f5f5f5f60c0888a031215613b10575f5ffd5b8735613b1b81613503565b9650613b296020890161351a565b95506040880135945060608801356001600160401b03811115613b4a575f5ffd5b8801601f81018a13613b5a575f5ffd5b80356001600160401b03811115613b6f575f5ffd5b8a6020828401011115613b80575f5ffd5b60209190910194509250613b9660808901613545565b9150613ba460a08901613895565b905092959891949750929550565b5f5f5f60608486031215613bc4575f5ffd5b8335613bcf81613503565b9250613bdd6020850161351a565b9150604084013561397481613531565b5f5f5f5f60808587031215613c00575f5ffd5b8435613c0b81613503565b9350613c196020860161351a565b925060408501356001600160401b03811115613c33575f5ffd5b613c3f8782880161361e565b92505060608501356001600160401b03811115613c5a575f5ffd5b613c668782880161361e565b91505092959194509250565b5f5f5f5f60808587031215613c85575f5ffd5b8435613c90816137fe565b9350602085013592506040850135613ca7816137fe565b9396929550929360600135925050565b5f5f60408385031215613cc8575f5ffd5b8235613cd3816137fe565b946020939093013593505050565b5f5f5f5f60808587031215613cf4575f5ffd5b8435613cff81613503565b9350613d0d6020860161351a565b92506040850135915060608501356135a981613531565b5f5f5f5f5f5f5f60e0888a031215613d3a575f5ffd5b8735613d4581613503565b9650613d536020890161351a565b95506040880135613d6381613531565b945060608801356001600160401b03811115613d7d575f5ffd5b613d898a828b0161361e565b9450506080880135613d9a81613531565b925060a0880135613daa81613550565b915060c0880135613aea816137fe565b5f60208284031215613dca575f5ffd5b81356134e881613531565b6001600160a01b03929092168252602082015260400190565b5f5f60408385031215613dff575f5ffd5b82359150602083013561383e816137fe565b6001600160401b0391909116815260200190565b5f5f5f5f60808587031215613e38575f5ffd5b8435613e4381613711565b93506020850135613e53816137fe565b92506040850135915060608501356135a9816137fe565b5f5f5f5f60808587031215613e7d575f5ffd5b8435613e8881613503565b9350613e966020860161351a565b92506040850135613ea681613531565b915060608501356001600160401b03811115613c5a575f5ffd5b5f5f5f60608486031215613ed2575f5ffd5b8335613edd81613503565b9250613eeb6020850161351a565b9150604084013561397481613503565b5f5f5f60608486031215613f0d575f5ffd5b8335613f1881613503565b9250613f266020850161351a565b91506040840135613974816137fe565b5f60208284031215613f46575f5ffd5b81516134e8816137fe565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b6001600160a01b03831681526040602082018190525f90612cca90830184613f51565b5f60208284031215613fb2575f5ffd5b81516134e881613711565b6001600160a01b0393841681529190921660208201526001600160801b03909116604082015260600190565b5f60208284031215613ff9575f5ffd5b81516134e881613550565b6001600160a01b0394851681529284166020840152921660408201526001600160801b03909116606082015260800190565b6001600160a01b039290921682526001600160801b0316602082015260400190565b61ffff93909316835260208301919091526001600160801b0316604082015260600190565b61ffff9890981688526001600160401b039690961660208801526001600160801b031994909416604087015260608601929092526001600160801b03908116608086015290811660a08501521660c08301526001600160a01b031660e08201526101000190565b608081525f6140f66080830187613f51565b82810360208401526141088187613f51565b60ff95909516604084015250506060015292915050565b63686f6f6b60e01b81526001600160a01b0391909116602082015260400190565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b6001600160801b031985168152602081018490526060604082018190525f906134bf9083018486614140565b6001600160401b03891681526001600160801b0319881660208201526040810187905260e0606082018190525f906141cf9083018789614140565b6080830195909552506001600160801b039290921660a08301526001600160a01b031660c09091015295945050505050565b5f60208284031215614211575f5ffd5b81516001600160401b03811115614226575f5ffd5b8201601f81018413614236575f5ffd5b8051614244613640826135f8565b818152856020838501011115614258575f5ffd5b8160208401602083015e5f91810160200191909152949350505050565b636e616d6560e01b8152604060208201525f6134e86040830184613f51565b651cde5b589bdb60d21b8152604060208201525f6134e86040830184613f51565b6001600160401b03881681526001600160801b0319871660208201526001600160801b038616604082015260e0606082018190525f906142f790830187613f51565b6001600160801b039590951660808301525091151560a08301526001600160a01b031660c090910152949350505050565b634e487b7160e01b5f52601160045260245ffd5b5f6001600160401b0382166002600160401b0319810161435e5761435e614328565b60010192915050565b61ffff8616815260a060208201525f61438360a0830187613f51565b82810360408401526143958187613f51565b60ff95909516606084015250509015156080909101529392505050565b61ffff9490941684526001600160801b0392909216602084015260ff1660408301526001600160a01b0316606082015260800190565b6001600160401b03851681526001600160801b0319841660208201526001600160801b03831660408201526080606082018190525f906134bf90830184613f51565b5f82518060208501845e5f920191825250919050565b6001600160a01b03851681526001600160e01b0319841660208201526080604082018190525f9061447390830185613f51565b82810360608401526144858185613f51565b979650505050505050565b5f602082840312156144a0575f5ffd5b81516134e881613a38565b6001600160801b038181168382160190811115611f0c57611f0c61432856fea16fb530429730804c0ab63e8deb338ca454bd82677d828b46231ccd1ee8c7b26b25100a5b37af8c57023626b9eecad698a5e230a6d0e0d761f5f8999fb0534b","optimization_enabled":true,"verified_twin_address_hash":null,"is_verified":true,"compiler_settings":{"evmVersion":"cancun","libraries":{},"metadata":{"appendCBOR":false,"bytecodeHash":"none","useLiteralContent":true},"optimizer":{"enabled":true,"runs":1},"outputSelection":{"*":{"":["*"],"*":["*"]}},"remappings":["forge-std/=lib/forge-std/src/","@chimera/=lib/chimera/src/","safe-utils/=lib/safe-utils/src/","safe-smart-account/=lib/safe-utils/lib/safe-smart-account/contracts/","solidity-http/=lib/safe-utils/lib/solidity-http/src/","solidity-stringutils/=lib/safe-utils/lib/solidity-stringutils/src/"],"viaIR":false},"optimization_runs":1,"sourcify_repo_url":null,"decoded_constructor_args":[["0xcE1616505F93215751FBb41Efac618b631997c38",{"internalType":"contract ITokenFactory","name":"tokenFactory_","type":"address"}],["0xB3C086Db30c1BE6e40D8775607C3662ab160bda5",{"internalType":"address","name":"deployer","type":"address"}]],"compiler_version":"v0.8.28+commit.7893614a","is_verified_via_verifier_alliance":false,"verified_at":"2026-02-08T05:19:25.583796Z","implementations":[],"proxy_type":null,"external_libraries":[],"creation_bytecode":"0x6080604052348015600e575f5ffd5b506040516145f53803806145f5833981016040819052602b9160aa565b6001600160a01b0381165f8181526020819052604080822060019055518392917fdd0e34038ac38b2a1ce960229778ac48a8719bc900b6c4f8d0475c6e8b385a6091a25050600280546001600160a01b0319166001600160a01b039290921691909117905560dd565b6001600160a01b038116811460a7575f5ffd5b50565b5f5f6040838503121560ba575f5ffd5b825160c3816094565b602084015190925060d2816094565b809150509250929050565b61450b806100ea5f395ff3fe6080604052600436106101e0575f3560e01c8063116191b6146101e457806318a96c29146102195780631f1b5aba146102585780632b67cde0146102795780632b89610114610298578063323d900f146102b757806339ceb095146103865780633a4ba8bf1461039957806344211693146103b85780634869ac69146103d75780634faac801146103f65780635274887b146104095780635d67c59e146104355780635f3e849f1461045457806365fae35e14610473578063668b4c1f1461049257806367e404ce146104d95780636aa6f457146104f85780636ea6e0a11461052c5780638004add31461054b5780638601872c1461055e5780638725b3f3146105a7578063931efb54146105c6578063947b330a146105e55780639c52a7f114610604578063ac5cbed914610623578063bccbfa8914610642578063bf353dbb14610661578063c05ff1521461069a578063c2b656c3146106b9578063c6526074146106cc578063cee8983d146106fb578063d490e7c214610728578063d4e8be8314610747578063da17f41714610766578063db057f1b146107a7578063db1b3cdc146107ba578063e77772fe146107d9578063eece6c43146107f8578063f60b8b1914610817578063fb59077a14610836578063fd6906ed14610855575b5f5ffd5b3480156101ef575f5ffd5b50600154610203906001600160a01b031681565b60405161021091906134ef565b60405180910390f35b348015610224575f5ffd5b5061023861023336600461355d565b610874565b604080516001600160801b03938416815292909116602083015201610210565b348015610263575f5ffd5b50610277610272366004613672565b61096c565b005b348015610284575f5ffd5b50600454610203906001600160a01b031681565b3480156102a3575f5ffd5b506102776102b23660046136c3565b610a94565b3480156102c2575f5ffd5b5061033e6102d13660046136de565b600760209081525f9283526040808420825291835291819020805482516060810184526001909201546001600160801b03811683526001600160401b03600160801b8204811695840195909552600160c01b9004909316918101919091526001600160a01b039091169082565b604080516001600160a01b03909316835281516001600160801b03166020808501919091528201516001600160401b0390811684830152910151166060820152608001610210565b610277610394366004613720565b610bbe565b3480156103a4575f5ffd5b506102776103b3366004613793565b610c47565b3480156103c3575f5ffd5b506102776103d2366004613812565b610dd5565b3480156103e2575f5ffd5b506102776103f1366004613849565b610e95565b6102776104043660046138a0565b610fdd565b348015610414575f5ffd5b50610428610423366004613939565b6115c4565b604051610210919061397f565b348015610440575f5ffd5b5061027761044f366004613993565b611655565b34801561045f575f5ffd5b5061027761046e3660046139df565b6116c9565b34801561047e575f5ffd5b5061027761048d366004613a1d565b611737565b34801561049d575f5ffd5b506104b16104ac366004613a1d565b6117aa565b604080516001600160401b0390931683526001600160801b0319909116602083015201610210565b3480156104e4575f5ffd5b50600354610203906001600160a01b031681565b348015610503575f5ffd5b506102036105123660046136c3565b60066020525f90815260409020546001600160a01b031681565b348015610537575f5ffd5b50610277610546366004613a46565b611815565b610277610559366004613afa565b6119f3565b348015610569575f5ffd5b5061057d6105783660046136de565b611ac9565b604080516001600160401b0394851681529284166020840152921691810191909152606001610210565b3480156105b2575f5ffd5b5061057d6105c1366004613bb2565b611b34565b3480156105d1575f5ffd5b506102776105e0366004613bed565b611bbd565b3480156105f0575f5ffd5b506102776105ff366004613c72565b611d88565b34801561060f575f5ffd5b5061027761061e366004613a1d565b611e4d565b34801561062e575f5ffd5b5061042861063d366004613cb7565b611ebf565b34801561064d575f5ffd5b5061027761065c366004613ce1565b611f12565b34801561066c575f5ffd5b5061068c61067b366004613a1d565b5f6020819052908152604090205481565b604051908152602001610210565b3480156106a5575f5ffd5b506102036106b43660046136de565b612086565b6102776106c7366004613d24565b6120a2565b3480156106d7575f5ffd5b506106eb6106e63660046136c3565b612180565b6040519015158152602001610210565b348015610706575f5ffd5b5061071a610715366004613dba565b61219f565b604051610210929190613dd5565b348015610733575f5ffd5b50610277610742366004613849565b61220d565b348015610752575f5ffd5b50610277610761366004613dee565b6122f3565b348015610771575f5ffd5b5061079a6107803660046136c3565b60056020525f90815260409020546001600160401b031681565b6040516102109190613e11565b6104286107b5366004613e25565b61243d565b3480156107c5575f5ffd5b506102776107d4366004613e6a565b612cd2565b3480156107e4575f5ffd5b50600254610203906001600160a01b031681565b348015610803575f5ffd5b50610277610812366004613ec0565b612d72565b348015610822575f5ffd5b50610277610831366004613efb565b612e2b565b348015610841575f5ffd5b50610277610850366004613efb565b612f24565b348015610860575f5ffd5b5061042861086f36600461355d565b613046565b5f5f5f61088187876130ee565b6001600160401b038089165f908152600c602090815260408083206001600160801b03198c16845282528083206001600160801b038b811685529083529281902081516060808201845291548086168252600160801b808204881683870152600160c01b918290048816838601528451938401855260018901549687168452860487169483019490945292909304909316928201929092529192509085158061093e575061092e82613142565b801561093e575061093e81613142565b61095a5760405162bfc92160e01b815260040160405180910390fd5b90519051909890975095505050505050565b335f9081526020819052604090205460011461099b5760405163ea8e4eb560e01b815260040160405180910390fd5b5f6109a68484612086565b90505f816001600160a01b0316637f5a7c7b6040518163ffffffff1660e01b8152600401602060405180830381865afa1580156109e5573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610a099190613f36565b90506001600160a01b038116610a3257604051639c9d882360e01b815260040160405180910390fd5b604051637aeba8d560e01b81526001600160a01b03821690637aeba8d590610a609085908790600401613f7f565b5f604051808303815f87803b158015610a77575f5ffd5b505af1158015610a89573d5f5f3e3d5ffd5b505050505050505050565b335f90815260208190526040902054600114610ac35760405163ea8e4eb560e01b815260040160405180910390fd5b6001600160401b038082165f908152600560205260409020805490911615610afe57604051633caf458560e01b815260040160405180910390fd5b80546001600160401b031916426001600160401b03161781556004805460405163388830bd60e11b81526001600160a01b0390911691637110617a91610b4691869101613e11565b6020604051808303815f875af1158015610b62573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b869190613f36565b506040516001600160401b038316907f28d6040dea8c2130b7a53f31f1c59e0771c45cac20965972891b1bdea59a1256905f90a25050565b5f5c6001600160a01b0316610c0557335f805c6001600160a01b0319168217905d50610bf086868686865f8733610fdd565b5f6001600160a01b0319815c16815d50610c3f565b336001600160a01b035f5c1614610c2f57604051630101292160e31b815260040160405180910390fd5b610c3f86868686865f8733610fdd565b505050505050565b335f90815260208190526040902054600114610c765760405163ea8e4eb560e01b815260040160405180910390fd5b5f5f610c818561219f565b6001600160401b03808a165f908152600c602090815260408083206001600160801b03198d16845282528083206001600160801b038c168452909152902080549395509193509091600160801b900481169085161015610cf45760405163957919e960e01b815260040160405180910390fd5b8054600160801b90046001600160401b0316158015610d2257508054600160c01b90046001600160401b0316155b15610d3f5780546001600160c01b03166001600160c01b03191781555b80546001600160801b0386166001600160c01b03199091168117600160801b6001600160401b038781169182029290921784556040805186815260208101949094528301526001600160a01b038516916001600160801b03198a16918b16907f808cd3ba373a28daeb965ce9e1dc2af3beaaa9f9a4e3c3f2431d0378eb6962a99060600160405180910390a45050505050505050565b335f90815260208190526040902054600114610e045760405163ea8e4eb560e01b815260040160405180910390fd5b610e0d82612180565b610e295760405162820f3560e61b815260040160405180910390fd5b6001600160401b0382165f818152600660205260409081902080546001600160a01b0319166001600160a01b038516179055517f7e6e289a79525732885fc1693691e8155df216a64630e31000a81b71e1f592d090610e899084906134ef565b60405180910390a25050565b335f90815260208190526040902054600114610ec45760405163ea8e4eb560e01b815260040160405180910390fd5b5f610ecf85856130ee565b600181018054919250906001600160401b03600160801b90910481169084161015610f0d5760405163957919e960e01b815260040160405180910390fd5b8054600160801b90046001600160401b0316158015610f3b57508054600160c01b90046001600160401b0316155b15610f585780546001600160c01b03166001600160c01b03191781555b80546001600160801b0385166001600160c01b03199091168117600160801b6001600160401b038681169182029290921784556040805193845260208401919091526001600160801b0319881692918916917f50ae94913f401513d2eded2f37844a070743c57ff5148fcfaf081085653a2856910160405180910390a3505050505050565b5f5c6001600160a01b03166112d357335f805c6001600160a01b0319168217905d505f61100a8888612086565b905060035f9054906101000a90046001600160a01b03166001600160a01b0316630a14789a6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561105c573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110809190613fa2565b61ffff168961ffff16036110a75760405163e9e4330360e01b815260040160405180910390fd5b604051630fa1e71360e41b81526001600160a01b0382169063fa1e7130906110db90339061ffff8e16908a90600401613fbd565b602060405180830381865afa1580156110f6573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061111a9190613fe9565b61113757604051632ba542af60e01b815260040160405180910390fd5b60405163887ca24960e01b81526001600160a01b0382169063887ca24990611169903390819030908b90600401614004565b6020604051808303815f875af1158015611185573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111a99190613fe9565b50604051632770a7eb60e21b81526001600160a01b03821690639dc29fac906111d89030908990600401614036565b5f604051808303815f87803b1580156111ef575f5ffd5b505af1158015611201573d5f5f3e3d5ffd5b50505050336001600160a01b0316876001600160801b031916896001600160401b03165f5160206144cb5f395f51905f528c8a8a60405161124493929190614058565b60405180910390a4600354604051631b17a41b60e21b81526001600160a01b0390911690636c5e906c90349061128c908d908d908d908d908d908d908d908d9060040161407d565b5f604051808303818588803b1580156112a3575f5ffd5b505af11580156112b5573d5f5f3e3d5ffd5b505f9450506001600160a01b0319845c169250839150505d506115ba565b336001600160a01b035f5c16146112fd57604051630101292160e31b815260040160405180910390fd5b5f6113088888612086565b905060035f9054906101000a90046001600160a01b03166001600160a01b0316630a14789a6040518163ffffffff1660e01b8152600401602060405180830381865afa15801561135a573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061137e9190613fa2565b61ffff168961ffff16036113a55760405163e9e4330360e01b815260040160405180910390fd5b604051630fa1e71360e41b81526001600160a01b0382169063fa1e7130906113d990339061ffff8e16908a90600401613fbd565b602060405180830381865afa1580156113f4573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906114189190613fe9565b61143557604051632ba542af60e01b815260040160405180910390fd5b60405163887ca24960e01b81526001600160a01b0382169063887ca24990611467903390819030908b90600401614004565b6020604051808303815f875af1158015611483573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906114a79190613fe9565b50604051632770a7eb60e21b81526001600160a01b03821690639dc29fac906114d69030908990600401614036565b5f604051808303815f87803b1580156114ed575f5ffd5b505af11580156114ff573d5f5f3e3d5ffd5b50505050336001600160a01b0316876001600160801b031916896001600160401b03165f5160206144cb5f395f51905f528c8a8a60405161154293929190614058565b60405180910390a4600354604051631b17a41b60e21b81526001600160a01b0390911690636c5e906c90349061158a908d908d908d908d908d908d908d908d9060040161407d565b5f604051808303818588803b1580156115a1575f5ffd5b505af11580156115b3573d5f5f3e3d5ffd5b5050505050505b5050505050505050565b5f5f6115d085856130ee565b905082158061162457506040805160608101825260018301546001600160801b03811682526001600160401b03600160801b820481166020840152600160c01b909104169181019190915261162490613142565b6116405760405162bfc92160e01b815260040160405180910390fd5b600101546001600160801b0316949350505050565b335f908152602081905260409020546001146116845760405163ea8e4eb560e01b815260040160405180910390fd5b5f61168f8585612086565b604051630368a3a560e31b81526001600160a01b038581166004830152848116602483015291925090821690631b451d2890604401610a60565b335f908152602081905260409020546001146116f85760405163ea8e4eb560e01b815260040160405180910390fd5b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b0384160161172c57611727828261317e565b505050565b611727838383613208565b335f908152602081905260409020546001146117665760405163ea8e4eb560e01b815260040160405180910390fd5b6001600160a01b0381165f8181526020819052604080822060019055517fdd0e34038ac38b2a1ce960229778ac48a8719bc900b6c4f8d0475c6e8b385a609190a250565b6001600160a01b0381165f908152600a6020526040902080546001600160401b03811691600160401b90910460801b9082151580156117f257506001600160801b0319821615155b61180f57604051630344039160e61b815260040160405180910390fd5b50915091565b335f908152602081905260409020546001146118445760405163ea8e4eb560e01b815260040160405180910390fd5b61184d87612180565b6118695760405162820f3560e61b815260040160405180910390fd5b600260ff8416101561188e57604051633f78ded760e01b815260040160405180910390fd5b601260ff841611156118b3576040516330e571f960e11b815260040160405180910390fd5b6001600160401b0387165f9081526007602090815260408083206001600160801b03198a1684529091529020546001600160a01b0316156119075760405163019163ff60e11b815260040160405180910390fd5b6002546040516362e92b0760e01b81525f916001600160a01b0316906362e92b079061193d9089908990899089906004016140e4565b6020604051808303815f875af1158015611959573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061197d9190613f36565b90506001600160a01b038216156119e85760405163d4e8be8360e01b81526001600160a01b0382169063d4e8be83906119ba90859060040161411f565b5f604051808303815f87803b1580156119d1575f5ffd5b505af11580156119e3573d5f5f3e3d5ffd5b505050505b6115ba888883612e2b565b336001600160401b038816603089901c61ffff1661ffff167f18910e041c7e37349ae25debc64b0f4f44af0b288a55d48f6c8565a9d76ad88289898989604051611a409493929190614168565b60405180910390a46003546001600160a01b03166363900d623489898989893360601b6001600160601b0319168a8a6040518a63ffffffff1660e01b8152600401611a92989796959493929190614194565b5f604051808303818588803b158015611aa9575f5ffd5b505af1158015611abb573d5f5f3e3d5ffd5b505050505050505050505050565b5f5f5f5f611ad786866130ee565b6001810154604080516060810182526001600160801b03831681526001600160401b03600160801b8404811660208301819052600160c01b909404169181018290529196509450909150611b2a9061334e565b9150509250925092565b6001600160401b038084165f908152600c602090815260408083206001600160801b03198716845282528083206001600160801b038681168552908352818420825160608101845290549182168152600160801b82048616938101849052600160c01b9091049094169084018190529092909190611bb18161334e565b91505093509350939050565b335f90815260208190526040902054600114611bec5760405163ea8e4eb560e01b815260040160405180910390fd5b5f611bf78585612086565b90508280519060200120816001600160a01b03166306fdde036040518163ffffffff1660e01b81526004015f60405180830381865afa158015611c3c573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052611c639190810190614201565b80519060200120141580611ce657508180519060200120816001600160a01b03166395d89b416040518163ffffffff1660e01b81526004015f60405180830381865afa158015611cb5573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052611cdc9190810190614201565b8051906020012014155b611d035760405163d7e605c360e01b815260040160405180910390fd5b6040516304bd623760e11b81526001600160a01b0382169063097ac46e90611d2f908690600401614275565b5f604051808303815f87803b158015611d46575f5ffd5b505af1158015611d58573d5f5f3e3d5ffd5b50506040516304bd623760e11b81526001600160a01b038416925063097ac46e9150610a60908590600401614294565b335f90815260208190526040902054600114611db75760405163ea8e4eb560e01b815260040160405180910390fd5b825f03611dce57611dc98483836116c9565b611e47565b6040516304ade6db60e11b81526001600160a01b038381166004830152602482018590526044820183905285169063095bcdb6906064016020604051808303815f875af1158015611e21573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190611e459190613fe9565b505b50505050565b335f90815260208190526040902054600114611e7c5760405163ea8e4eb560e01b815260040160405180910390fd5b6001600160a01b0381165f81815260208190526040808220829055517f184450df2e323acec0ed3b5c7531b81f9b4cdef7914dfd4c0a4317416bb5251b9190a250565b6001600160a01b0382165f908152600b602090815260408083208484529091528120546001600160801b031690819003611f0c5760405163c97d95cf60e01b815260040160405180910390fd5b92915050565b335f90815260208190526040902054600114611f415760405163ea8e4eb560e01b815260040160405180910390fd5b5f611f4c8585612086565b6040516340c10f1960e01b81529091506001600160a01b038216906340c10f1990611f7d9030908690600401614036565b5f604051808303815f87803b158015611f94575f5ffd5b505af1158015611fa6573d5f5f3e3d5ffd5b50505050806001600160a01b031663a9059cbb611fc285613380565b846040518363ffffffff1660e01b8152600401611fe0929190614036565b6020604051808303815f875af1158015611ffc573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906120209190613fe9565b5061202a83613380565b6001600160a01b0316846001600160801b031916866001600160401b03167f646bf4da76b559478ffb33bb35acfe75c89ebe6b145c823775910ae16b17f84585604051612077919061397f565b60405180910390a45050505050565b5f61209183836130ee565b546001600160a01b03169392505050565b6001600160401b0387165f908152600660205260409020546001600160a01b0316806120e157604051632131eb8160e11b815260040160405180910390fd5b336001600160a01b0382161461210a5760405163ea8e4eb560e01b815260040160405180910390fd5b600354604051632ecc233760e21b81526001600160a01b039091169063bb308cdc903490612148908c908c908c908c908c908c908c906004016142b5565b5f604051808303818588803b15801561215f575f5ffd5b505af1158015612171573d5f5f3e3d5ffd5b50505050505050505050505050565b6001600160401b039081165f9081526005602052604090205416151590565b6001600160801b0381165f908152600960209081526040808320815180830190925280546001600160a01b03168083526001909101549282019290925282916121fb5760405163c97d95cf60e01b815260040160405180910390fd5b80516020909101519094909350915050565b335f9081526020819052604090205460011461223c5760405163ea8e4eb560e01b815260040160405180910390fd5b5f5f6122478461219f565b6001600160401b038881165f818152600c602090815260408083206001600160801b03198d168085529083528184206001600160801b038d16855283529281902080546001600160c01b0316600160c01b968c169687021790558051868152918201949094529496509294506001600160a01b0386169390917fd0c6def17ddcc3d8efe57bf365c0bef197870035a47752f720fc601eff9c0b3d910160405180910390a4505050505050565b335f908152602081905260409020546001146123225760405163ea8e4eb560e01b815260040160405180910390fd5b81666761746577617960c81b0361235357600180546001600160a01b0319166001600160a01b03831617905561240d565b816539b2b73232b960d11b0361238357600380546001600160a01b0319166001600160a01b03831617905561240d565b816b746f6b656e466163746f727960a01b036123b957600280546001600160a01b0319166001600160a01b03831617905561240d565b8170706f6f6c457363726f77466163746f727960781b036123f457600480546001600160a01b0319166001600160a01b03831617905561240d565b604051633db0d5b960e01b815260040160405180910390fd5b817f8fef588b5fc1afbf5b2f06c1a435d513f208da2e6704c3d8f0e0ec91167066ba82604051610e8991906134ef565b5f805c6001600160a01b03166128a657335f805c6001600160a01b0319168217905d506060805f61246e87876133b0565b9050600260ff8216101561249557604051633f78ded760e01b815260040160405180910390fd5b601260ff821611156124ba576040516330e571f960e11b815260040160405180910390fd5b855f03612593575f879050806001600160a01b03166306fdde036040518163ffffffff1660e01b81526004015f60405180830381865afa158015612500573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526125279190810190614201565b9350806001600160a01b03166395d89b416040518163ffffffff1660e01b81526004015f60405180830381865afa158015612564573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f1916820160405261258b9190810190614201565b92505061266c565b604051622b600360e21b81526004810187905287906001600160a01b0382169062ad800c906024015f60405180830381865afa1580156125d5573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526125fc9190810190614201565b604051634e41a1fb60e01b8152600481018990529094506001600160a01b03821690634e41a1fb906024015f60405180830381865afa158015612641573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526126689190810190614201565b9250505b6001600160a01b0387165f908152600b602090815260408083208984529091529020546001600160801b03169350831580156127e357600880546001600160401b0316905f6126ba8361433c565b91906101000a8154816001600160401b0302191690836001600160401b031602179055505061276760035f9054906101000a90046001600160a01b03166001600160a01b0316630a14789a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612732573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906127569190613fa2565b6008546001600160401b03166134c9565b6040805180820182526001600160a01b038b811680835260208084018d81526001600160801b0387165f81815260098452878120965187546001600160a01b03191696169590951786559051600190950194909455908252600b81528382208c835290529190912080546001600160801b031916909117905594505b86886001600160a01b0316866001600160801b03165f5160206144eb5f395f51905f528c8888888860405161281c959493929190614367565b60405180910390a46003546040516346458fc760e11b81526001600160a01b0390911690638c8b1f8e90349061285c908d908a9088908d906004016143b2565b5f604051808303818588803b158015612873575f5ffd5b505af1158015612885573d5f5f3e3d5ffd5b505f9750506001600160a01b0319875c169550869450505050505d50612cca565b336001600160a01b035f5c16146128d057604051630101292160e31b815260040160405180910390fd5b6060805f6128de87876133b0565b9050600260ff8216101561290557604051633f78ded760e01b815260040160405180910390fd5b601260ff8216111561292a576040516330e571f960e11b815260040160405180910390fd5b855f03612a03575f879050806001600160a01b03166306fdde036040518163ffffffff1660e01b81526004015f60405180830381865afa158015612970573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526129979190810190614201565b9350806001600160a01b03166395d89b416040518163ffffffff1660e01b81526004015f60405180830381865afa1580156129d4573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526129fb9190810190614201565b925050612adc565b604051622b600360e21b81526004810187905287906001600160a01b0382169062ad800c906024015f60405180830381865afa158015612a45573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052612a6c9190810190614201565b604051634e41a1fb60e01b8152600481018990529094506001600160a01b03821690634e41a1fb906024015f60405180830381865afa158015612ab1573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052612ad89190810190614201565b9250505b6001600160a01b0387165f908152600b602090815260408083208984529091529020546001600160801b0316935083158015612c1e57600880546001600160401b0316905f612b2a8361433c565b91906101000a8154816001600160401b0302191690836001600160401b0316021790555050612ba260035f9054906101000a90046001600160a01b03166001600160a01b0316630a14789a6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612732573d5f5f3e3d5ffd5b6040805180820182526001600160a01b038b811680835260208084018d81526001600160801b0387165f81815260098452878120965187546001600160a01b03191696169590951786559051600190950194909455908252600b81528382208c835290529190912080546001600160801b031916909117905594505b86886001600160a01b0316866001600160801b03165f5160206144eb5f395f51905f528c88888888604051612c57959493929190614367565b60405180910390a46003546040516346458fc760e11b81526001600160a01b0390911690638c8b1f8e903490612c97908d908a9088908d906004016143b2565b5f604051808303818588803b158015612cae575f5ffd5b505af1158015612cc0573d5f5f3e3d5ffd5b5050505050505050505b949350505050565b335f90815260208190526040902054600114612d015760405163ea8e4eb560e01b815260040160405180910390fd5b6001600160401b0384165f908152600660205260409020546001600160a01b031680612d4057604051632131eb8160e11b815260040160405180910390fd5b604051631c0b2ad560e21b81526001600160a01b0382169063702cab5490610a609088908890889088906004016143e8565b335f90815260208190526040902054600114612da15760405163ea8e4eb560e01b815260040160405180910390fd5b5f612dac84846130ee565b905081816001015f0160186101000a8154816001600160401b0302191690836001600160401b03160217905550826001600160801b031916846001600160401b03167fd566c97f11867171a51ecec2586f08002bff134b1819350c5417d12feca54aee84604051612e1d9190613e11565b60405180910390a350505050565b335f90815260208190526040902054600114612e5a5760405163ea8e4eb560e01b815260040160405180910390fd5b6001600160401b038084165f8181526007602090815260408083206001600160801b0319881680855290835281842080546001600160a01b0389166001600160a01b0319909116811790915582518084018452868152808501838152918652600a9094529382902092518354945160801c600160401b026001600160c01b0319909516961695909517929092179055517fe69d7376db85d5607fd179347a15f31913add0e3ada2b1e5e205120a8f6d9e4490612f179085906134ef565b60405180910390a3505050565b335f90815260208190526040902054600114612f535760405163ea8e4eb560e01b815260040160405180910390fd5b5f612f5e8484612086565b9050806001600160a01b0316637f5a7c7b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015612f9c573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190612fc09190613f36565b6001600160a01b0316826001600160a01b031603612ff157604051632a53f92160e11b815260040160405180910390fd5b60405163d4e8be8360e01b81526001600160a01b0382169063d4e8be839061301d90859060040161411f565b5f604051808303815f87803b158015613034575f5ffd5b505af11580156115ba573d5f5f3e3d5ffd5b6001600160401b038085165f908152600c602090815260408083206001600160801b03198816845282528083206001600160801b038781168552908352818420825160608101845290549182168152600160801b8204861693810193909352600160c01b900490931692810192909252908215806130c857506130c881613142565b6130e45760405162bfc92160e01b815260040160405180910390fd5b5195945050505050565b6001600160401b0382165f9081526007602090815260408083206001600160801b031985168452909152902080546001600160a01b0316611f0c57604051630344039160e61b815260040160405180910390fd5b5f81602001516001600160401b03165f14613172576131608261334e565b6001600160401b031642111592915050565b505f919050565b919050565b604080515f808252602082019092526001600160a01b0384169083906040516131a7919061442a565b5f6040518083038185875af1925050503d805f81146131e1576040519150601f19603f3d011682016040523d82523d5f602084013e6131e6565b606091505b505090508061172757604051630d2fa21160e31b815260040160405180910390fd5b5f836001600160a01b03163b1161323257604051633c11a9c560e21b815260040160405180910390fd5b5f5f846001600160a01b03168484604051602401613251929190613dd5565b60408051601f198184030181529181526020820180516001600160e01b031663a9059cbb60e01b17905251613286919061442a565b5f604051808303815f865af19150503d805f81146132bf576040519150601f19603f3d011682016040523d82523d5f602084013e6132c4565b606091505b50915091508180156132ee5750805115806132ee5750808060200190518101906132ee9190613fe9565b6040805160048152602481019091526020810180516001600160e01b031663fb7f507960e01b179052869163a9059cbb60e01b918491610a89576040516390bfb86560e01b81526004016133459493929190614440565b60405180910390fd5b604081015160208201515f918101906001600160401b039081169082161015611f0c57506001600160401b0392915050565b5f6001600160601b038216156133a95760405163e8bd165960e01b815260040160405180910390fd5b5060601c90565b5f6060825f036133e957506040805160048152602481019091526020810180516001600160e01b031663313ce56760e01b179052613423565b6040516024810184905260440160408051601f198184030181529190526020810180516001600160e01b0316631fa3f33160e11b17905290505b5f5f856001600160a01b03168360405161343d919061442a565b5f60405180830381855afa9150503d805f8114613475576040519150601f19603f3d011682016040523d82523d5f602084013e61347a565b606091505b509150915081801561348e57506020815110155b6134ab576040516366b0142960e01b815260040160405180910390fd5b808060200190518101906134bf9190614490565b9695505050505050565b5f6134e86001600160401b03831661ffff60701b607086901b166144ab565b9392505050565b6001600160a01b0391909116815260200190565b6001600160401b0381168114613517575f5ffd5b50565b80356001600160801b031981168114613179575f5ffd5b6001600160801b0381168114613517575f5ffd5b803561317981613531565b8015158114613517575f5ffd5b5f5f5f5f60808587031215613570575f5ffd5b843561357b81613503565b93506135896020860161351a565b9250604085013561359981613531565b915060608501356135a981613550565b939692955090935050565b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f191681016001600160401b03811182821017156135f0576135f06135b4565b604052919050565b5f6001600160401b03821115613610576136106135b4565b50601f01601f191660200190565b5f82601f83011261362d575f5ffd5b8135602083015f613645613640846135f8565b6135c8565b9050828152858383011115613658575f5ffd5b828260208301375f92810160200192909252509392505050565b5f5f5f60608486031215613684575f5ffd5b833561368f81613503565b925061369d6020850161351a565b915060408401356001600160401b038111156136b7575f5ffd5b611b2a8682870161361e565b5f602082840312156136d3575f5ffd5b81356134e881613503565b5f5f604083850312156136ef575f5ffd5b82356136fa81613503565b91506137086020840161351a565b90509250929050565b61ffff81168114613517575f5ffd5b5f5f5f5f5f5f60c08789031215613735575f5ffd5b863561374081613711565b9550602087013561375081613503565b945061375e6040880161351a565b935060608701359250608087013561377581613531565b915060a087013561378581613531565b809150509295509295509295565b5f5f5f5f5f60a086880312156137a7575f5ffd5b85356137b281613503565b94506137c06020870161351a565b935060408601356137d081613531565b925060608601356137e081613531565b915060808601356137f081613503565b809150509295509295909350565b6001600160a01b0381168114613517575f5ffd5b5f5f60408385031215613823575f5ffd5b823561382e81613503565b9150602083013561383e816137fe565b809150509250929050565b5f5f5f5f6080858703121561385c575f5ffd5b843561386781613503565b93506138756020860161351a565b9250604085013561388581613531565b915060608501356135a981613503565b8035613179816137fe565b5f5f5f5f5f5f5f5f610100898b0312156138b8575f5ffd5b88356138c381613711565b975060208901356138d381613503565b96506138e160408a0161351a565b95506060890135945060808901356138f881613531565b935060a089013561390881613531565b925060c089013561391881613531565b915060e0890135613928816137fe565b809150509295985092959890939650565b5f5f5f6060848603121561394b575f5ffd5b833561395681613503565b92506139646020850161351a565b9150604084013561397481613550565b809150509250925092565b6001600160801b0391909116815260200190565b5f5f5f5f608085870312156139a6575f5ffd5b84356139b181613503565b93506139bf6020860161351a565b925060408501356139cf816137fe565b915060608501356135a9816137fe565b5f5f5f606084860312156139f1575f5ffd5b83356139fc816137fe565b92506020840135613a0c816137fe565b929592945050506040919091013590565b5f60208284031215613a2d575f5ffd5b81356134e8816137fe565b60ff81168114613517575f5ffd5b5f5f5f5f5f5f5f60e0888a031215613a5c575f5ffd5b8735613a6781613503565b9650613a756020890161351a565b955060408801356001600160401b03811115613a8f575f5ffd5b613a9b8a828b0161361e565b95505060608801356001600160401b03811115613ab6575f5ffd5b613ac28a828b0161361e565b9450506080880135613ad381613a38565b925060a0880135915060c0880135613aea816137fe565b8091505092959891949750929550565b5f5f5f5f5f5f5f60c0888a031215613b10575f5ffd5b8735613b1b81613503565b9650613b296020890161351a565b95506040880135945060608801356001600160401b03811115613b4a575f5ffd5b8801601f81018a13613b5a575f5ffd5b80356001600160401b03811115613b6f575f5ffd5b8a6020828401011115613b80575f5ffd5b60209190910194509250613b9660808901613545565b9150613ba460a08901613895565b905092959891949750929550565b5f5f5f60608486031215613bc4575f5ffd5b8335613bcf81613503565b9250613bdd6020850161351a565b9150604084013561397481613531565b5f5f5f5f60808587031215613c00575f5ffd5b8435613c0b81613503565b9350613c196020860161351a565b925060408501356001600160401b03811115613c33575f5ffd5b613c3f8782880161361e565b92505060608501356001600160401b03811115613c5a575f5ffd5b613c668782880161361e565b91505092959194509250565b5f5f5f5f60808587031215613c85575f5ffd5b8435613c90816137fe565b9350602085013592506040850135613ca7816137fe565b9396929550929360600135925050565b5f5f60408385031215613cc8575f5ffd5b8235613cd3816137fe565b946020939093013593505050565b5f5f5f5f60808587031215613cf4575f5ffd5b8435613cff81613503565b9350613d0d6020860161351a565b92506040850135915060608501356135a981613531565b5f5f5f5f5f5f5f60e0888a031215613d3a575f5ffd5b8735613d4581613503565b9650613d536020890161351a565b95506040880135613d6381613531565b945060608801356001600160401b03811115613d7d575f5ffd5b613d898a828b0161361e565b9450506080880135613d9a81613531565b925060a0880135613daa81613550565b915060c0880135613aea816137fe565b5f60208284031215613dca575f5ffd5b81356134e881613531565b6001600160a01b03929092168252602082015260400190565b5f5f60408385031215613dff575f5ffd5b82359150602083013561383e816137fe565b6001600160401b0391909116815260200190565b5f5f5f5f60808587031215613e38575f5ffd5b8435613e4381613711565b93506020850135613e53816137fe565b92506040850135915060608501356135a9816137fe565b5f5f5f5f60808587031215613e7d575f5ffd5b8435613e8881613503565b9350613e966020860161351a565b92506040850135613ea681613531565b915060608501356001600160401b03811115613c5a575f5ffd5b5f5f5f60608486031215613ed2575f5ffd5b8335613edd81613503565b9250613eeb6020850161351a565b9150604084013561397481613503565b5f5f5f60608486031215613f0d575f5ffd5b8335613f1881613503565b9250613f266020850161351a565b91506040840135613974816137fe565b5f60208284031215613f46575f5ffd5b81516134e8816137fe565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b6001600160a01b03831681526040602082018190525f90612cca90830184613f51565b5f60208284031215613fb2575f5ffd5b81516134e881613711565b6001600160a01b0393841681529190921660208201526001600160801b03909116604082015260600190565b5f60208284031215613ff9575f5ffd5b81516134e881613550565b6001600160a01b0394851681529284166020840152921660408201526001600160801b03909116606082015260800190565b6001600160a01b039290921682526001600160801b0316602082015260400190565b61ffff93909316835260208301919091526001600160801b0316604082015260600190565b61ffff9890981688526001600160401b039690961660208801526001600160801b031994909416604087015260608601929092526001600160801b03908116608086015290811660a08501521660c08301526001600160a01b031660e08201526101000190565b608081525f6140f66080830187613f51565b82810360208401526141088187613f51565b60ff95909516604084015250506060015292915050565b63686f6f6b60e01b81526001600160a01b0391909116602082015260400190565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b6001600160801b031985168152602081018490526060604082018190525f906134bf9083018486614140565b6001600160401b03891681526001600160801b0319881660208201526040810187905260e0606082018190525f906141cf9083018789614140565b6080830195909552506001600160801b039290921660a08301526001600160a01b031660c09091015295945050505050565b5f60208284031215614211575f5ffd5b81516001600160401b03811115614226575f5ffd5b8201601f81018413614236575f5ffd5b8051614244613640826135f8565b818152856020838501011115614258575f5ffd5b8160208401602083015e5f91810160200191909152949350505050565b636e616d6560e01b8152604060208201525f6134e86040830184613f51565b651cde5b589bdb60d21b8152604060208201525f6134e86040830184613f51565b6001600160401b03881681526001600160801b0319871660208201526001600160801b038616604082015260e0606082018190525f906142f790830187613f51565b6001600160801b039590951660808301525091151560a08301526001600160a01b031660c090910152949350505050565b634e487b7160e01b5f52601160045260245ffd5b5f6001600160401b0382166002600160401b0319810161435e5761435e614328565b60010192915050565b61ffff8616815260a060208201525f61438360a0830187613f51565b82810360408401526143958187613f51565b60ff95909516606084015250509015156080909101529392505050565b61ffff9490941684526001600160801b0392909216602084015260ff1660408301526001600160a01b0316606082015260800190565b6001600160401b03851681526001600160801b0319841660208201526001600160801b03831660408201526080606082018190525f906134bf90830184613f51565b5f82518060208501845e5f920191825250919050565b6001600160a01b03851681526001600160e01b0319841660208201526080604082018190525f9061447390830185613f51565b82810360608401526144858185613f51565b979650505050505050565b5f602082840312156144a0575f5ffd5b81516134e881613a38565b6001600160801b038181168382160190811115611f0c57611f0c61432856fea16fb530429730804c0ab63e8deb338ca454bd82677d828b46231ccd1ee8c7b26b25100a5b37af8c57023626b9eecad698a5e230a6d0e0d761f5f8999fb0534b000000000000000000000000ce1616505f93215751fbb41efac618b631997c38000000000000000000000000b3c086db30c1be6e40d8775607c3662ab160bda5","name":"Spoke","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/core/spoke/types/Price.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.28;\n\nimport {D18} from \"../../../misc/types/D18.sol\";\n\n/// @dev Price struct that contains a price, the timestamp at which it was computed and the max age of the price.\nstruct Price {\n    D18 price;\n    uint64 computedAt;\n    uint64 maxAge;\n}\n\n/// @dev Checks if a price is valid. Returns false if computedAt is 0. Otherwise checks for block\n/// timestamp <= computedAt + maxAge\nfunction isValid(Price memory price) view returns (bool) {\n    if (price.computedAt != 0) {\n        return block.timestamp <= price.validUntil();\n    } else {\n        return false;\n    }\n}\n\n/// @dev Computes the timestamp until the price is valid. Saturates at uint64.MAX.\nfunction validUntil(Price memory price) pure returns (uint64) {\n    unchecked {\n        uint64 validUntil_ = price.computedAt + price.maxAge;\n        if (validUntil_ < price.computedAt) {\n            return type(uint64).max;\n        }\n        return validUntil_;\n    }\n}\n\nusing {isValid, validUntil} for Price global;\n"},{"file_path":"src/core/types/ShareClassId.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.28;\n\nimport {PoolId} from \"./PoolId.sol\";\n\ntype ShareClassId is bytes16;\n\nfunction isNull(ShareClassId scId) pure returns (bool) {\n    return ShareClassId.unwrap(scId) == 0;\n}\n\nfunction index(ShareClassId scId) pure returns (uint32) {\n    return uint32(uint128(ShareClassId.unwrap(scId)));\n}\n\nfunction equals(ShareClassId left, ShareClassId right) pure returns (bool) {\n    return ShareClassId.unwrap(left) == ShareClassId.unwrap(right);\n}\n\nfunction raw(ShareClassId scId) pure returns (bytes16) {\n    return ShareClassId.unwrap(scId);\n}\n\nfunction newShareClassId(PoolId poolId, uint32 index_) pure returns (ShareClassId scId) {\n    return ShareClassId.wrap(bytes16((uint128(PoolId.unwrap(poolId)) << 64) + index_));\n}\n\nusing {isNull, index, raw, equals as ==} for ShareClassId global;\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    error MulDiv_Overflow();\n    error Uint8_Overflow();\n    error Uint16_Overflow();\n    error Uint32_Overflow();\n    error Uint64_Overflow();\n    error Uint96_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\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    /// @notice Safe type conversion from uint256 to uint16.\n    function toUint16(uint256 value) internal pure returns (uint16) {\n        require(value <= type(uint16).max, Uint16_Overflow());\n        return uint16(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    function toUint96(uint256 value) internal pure returns (uint96) {\n        require(value <= type(uint96).max, Uint96_Overflow());\n        return uint96(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":"lib/forge-std/src/interfaces/IERC165.sol","source_code":"// SPDX-License-Identifier: MIT\npragma solidity >=0.6.2;\n\ninterface IERC165 {\n    /// @notice Query if a contract implements an interface\n    /// @param interfaceID The interface identifier, as specified in ERC-165\n    /// @dev Interface identification is specified in ERC-165. This function\n    /// uses less than 30,000 gas.\n    /// @return `true` if the contract implements `interfaceID` and\n    /// `interfaceID` is not 0xffffffff, `false` otherwise\n    function supportsInterface(bytes4 interfaceID) external view returns (bool);\n}\n"},{"file_path":"src/misc/libraries/SafeTransferLib.sol","source_code":"// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity 0.8.28;\n\nimport {IERC20} from \"../interfaces/IERC20.sol\";\nimport {IERC7751} from \"../interfaces/IERC7751.sol\";\n\n/// @title  Safe Transfer Lib\n/// @author Modified from Uniswap v3 Periphery (libraries/TransferHelper.sol)\nlibrary SafeTransferLib {\n    error NoCode();\n    error SafeTransferFromFailed();\n    error SafeTransferFailed();\n    error SafeApproveFailed();\n    error SafeTransferEthFailed();\n\n    /// @notice Transfers tokens from the targeted address to the given destination\n    /// @notice Errors if transfer fails\n    /// @param token The contract address of the token to be transferred\n    /// @param from The originating address from which the tokens will be transferred\n    /// @param to The destination address of the transfer\n    /// @param value The amount to be transferred\n    function safeTransferFrom(address token, address from, address to, uint256 value) internal {\n        require(address(token).code.length > 0, NoCode());\n\n        (bool success, bytes memory returnData) = token.call(abi.encodeCall(IERC20.transferFrom, (from, to, value)));\n        require(\n            success && (returnData.length == 0 || abi.decode(returnData, (bool))),\n            IERC7751.WrappedError(\n                token, IERC20.transferFrom.selector, returnData, abi.encodeWithSelector(SafeTransferFromFailed.selector)\n            )\n        );\n    }\n\n    /// @notice Transfers tokens from msg.sender to a recipient\n    /// @dev Errors if transfer fails\n    /// @param token The contract address of the token which will be transferred\n    /// @param to The recipient of the transfer\n    /// @param value The value of the transfer\n    function safeTransfer(address token, address to, uint256 value) internal {\n        require(address(token).code.length > 0, NoCode());\n\n        (bool success, bytes memory returnData) = token.call(abi.encodeCall(IERC20.transfer, (to, value)));\n        require(\n            success && (returnData.length == 0 || abi.decode(returnData, (bool))),\n            IERC7751.WrappedError(\n                token, IERC20.transfer.selector, returnData, abi.encodeWithSelector(SafeTransferFailed.selector)\n            )\n        );\n    }\n\n    /// @notice Approves the stipulated contract to spend the given allowance in the given token\n    /// @dev Errors if approval fails\n    /// @param token The contract address of the token to be approved\n    /// @param to The target of the approval\n    /// @param value The amount of the given token the target will be allowed to spend\n    function safeApprove(address token, address to, uint256 value) internal {\n        require(address(token).code.length > 0, NoCode());\n\n        (bool success, bytes memory returnData) = token.call(abi.encodeCall(IERC20.approve, (to, value)));\n        require(\n            success && (returnData.length == 0 || abi.decode(returnData, (bool))),\n            IERC7751.WrappedError(\n                token, IERC20.approve.selector, returnData, abi.encodeWithSelector(SafeApproveFailed.selector)\n            )\n        );\n    }\n\n    /// @notice Transfers ETH to the recipient address\n    /// @dev Fails with `STE`\n    /// @dev Make sure that method that is using this function is protected from reentrancy\n    /// @param to The destination of the transfer\n    /// @param value The value to be transferred\n    function safeTransferETH(address to, uint256 value) internal {\n        (bool success,) = to.call{value: value}(new bytes(0));\n        require(success, SafeTransferEthFailed());\n    }\n}\n"},{"file_path":"src/core/spoke/factories/interfaces/ITokenFactory.sol","source_code":"// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\nimport {IShareToken} from \"../../interfaces/IShareToken.sol\";\n\n/// @title  ITokenFactory\n/// @notice Factory for deploying deterministic share class tokens using CREATE2\n/// @dev    Enables same-address deployments across different EVM chains using salt\ninterface ITokenFactory {\n    event File(bytes32 what, address[] addr);\n\n    error FileUnrecognizedParam();\n\n    /// @notice Updates a contract parameter.\n    /// @param what Name of the parameter to update.\n    function file(bytes32 what, address[] memory data) external;\n\n    /// @notice Used to deploy new share class tokens.\n    /// @dev    In order to have the same address on different EVMs `salt` should be used\n    ///         during creation process.\n    /// @param name Name of the new token.\n    /// @param symbol Symbol of the new token.\n    /// @param decimals Decimals of the new token.\n    /// @param salt Salt used for deterministic deployments.\n    function newToken(string memory name, string memory symbol, uint8 decimals, bytes32 salt)\n        external\n        returns (IShareToken);\n\n    /// @notice Returns the predicted address (using CREATE2)\n    function getAddress(uint8 decimals, bytes32 salt) external view returns (address);\n}\n"},{"file_path":"src/core/spoke/interfaces/IVault.sol","source_code":"// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\nimport {PoolId} from \"../../types/PoolId.sol\";\nimport {ShareClassId} from \"../../types/ShareClassId.sol\";\n\nenum VaultKind {\n    /// @dev Refers to AsyncVault\n    Async,\n    /// @dev not yet supported\n    Sync,\n    /// @dev Refers to SyncDepositVault\n    SyncDepositAsyncRedeem\n}\n\n/// @notice Interface for the all vault contracts\n/// @dev Must be implemented by all vaults\ninterface IVault {\n    /// @notice Identifier of the Centrifuge pool\n    /// @return The pool identifier\n    function poolId() external view returns (PoolId);\n\n    /// @notice Identifier of the share class of the Centrifuge pool\n    /// @return The share class identifier\n    function scId() external view returns (ShareClassId);\n\n    /// @notice Checks whether the vault is partially (a)synchronous\n    /// @return vaultKind_ The kind of the vault\n    function vaultKind() external view returns (VaultKind vaultKind_);\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/core/messaging/interfaces/IMessageHandler.sol","source_code":"// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\n/// @notice Generic interface for entities that handle incoming messages\ninterface IMessageHandler {\n    //----------------------------------------------------------------------------------------------\n    // Incoming\n    //----------------------------------------------------------------------------------------------\n\n    /// @notice Handling incoming messages\n    /// @param centrifugeId Source chain\n    /// @param message Incoming message\n    function handle(uint16 centrifugeId, bytes calldata message) 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/interfaces/IEscrow.sol","source_code":"// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\n/// @title  Escrow for holding assets\ninterface IEscrow {\n    //----------------------------------------------------------------------------------------------\n    // Events\n    //----------------------------------------------------------------------------------------------\n\n    /// @notice Emitted when an authTransferTo is made\n    /// @dev Needed as allowances increase attack surface\n    event AuthTransferTo(address indexed asset, uint256 indexed tokenId, address receiver, uint256 value);\n\n    /// @notice Emitted when the escrow has insufficient balance for an action - virtual or actual balance\n    error InsufficientBalance(address asset, uint256 tokenId, uint256 value, uint256 balance);\n\n    /// @notice Transfers assets from the escrow to a receiver address\n    /// @param asset The address of the asset to transfer\n    /// @param tokenId The token ID of the asset (0 for ERC20, non-zero for ERC6909)\n    /// @param receiver The address receiving the transferred assets\n    /// @param value The amount of assets to transfer\n    function authTransferTo(address asset, uint256 tokenId, address receiver, uint256 value) external;\n}\n"},{"file_path":"src/misc/interfaces/IERC7751.sol","source_code":"// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\n/// [ERC-7751](https://eips.ethereum.org/EIPS/eip-7751): Wrapping of bubbled up reverts\n/// Handling bubbled up reverts using custom errors with additional context.\ninterface IERC7751 {\n    error WrappedError(address target, bytes4 selector, bytes reason, bytes details);\n}\n"},{"file_path":"src/core/spoke/interfaces/ITransferHook.sol","source_code":"// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\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/issuance:         address(0)       -> address(user)\n///           Deposit fulfillment:              address(0)       -> poolEscrow\n///           Deposit claim:                    poolEscrow       -> address(user)\n///           Redeem request:                   address(user)    -> ESCROW_HOOK_ID\n///           Redeem fulfillment:               balanceSheet     -> address(0)\n///           Redeem claim/revocation:          address(user)    -> address(0)\n///           Cross-chain transfer:             address(user)    -> address(uint160(chainId))\n///           Cross-chain execution:            crosschainSource -> address(user)\n///\n///         Endorsed refers to core protocol contracts, which can be retrieved using root.endorsed(addr)\n///         poolEscrow: Pool-specific escrow contract identified via balanceSheet.escrow(poolId)\n///         balanceSheet: Contract that fulfills redemptions and provides pool escrow lookups\n///         crosschainSource: Contract handling cross-chain message execution (spoke)\ninterface ITransferHook is IERC165 {\n    //----------------------------------------------------------------------------------------------\n    // Errors\n    //----------------------------------------------------------------------------------------------\n\n    error TransferBlocked();\n    error InvalidUpdate();\n\n    //----------------------------------------------------------------------------------------------\n    // Callbacks\n    //----------------------------------------------------------------------------------------------\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    //----------------------------------------------------------------------------------------------\n    // View methods\n    //----------------------------------------------------------------------------------------------\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    //----------------------------------------------------------------------------------------------\n    // Administration\n    //----------------------------------------------------------------------------------------------\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/libraries/CastLib.sol","source_code":"// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity 0.8.28;\n\n/// @title  CastLib\nlibrary CastLib {\n    error PrefixNotZero();\n    error SizeNot128();\n\n    function toAddressLeftPadded(bytes32 addr) internal pure returns (address) {\n        require(bytes12(addr) == 0, PrefixNotZero());\n        return address(uint160(uint256(addr)));\n    }\n\n    function toBytes32LeftPadded(address addr) internal pure returns (bytes32) {\n        return bytes32(uint256(uint160(addr)));\n    }\n\n    function toAddress(bytes32 addr) internal pure returns (address) {\n        require(uint96(uint256(addr)) == 0, PrefixNotZero());\n        return address(bytes20(addr));\n    }\n\n    function toBytes32(address addr) internal pure returns (bytes32) {\n        return bytes32(bytes20(addr));\n    }\n\n    /// @dev Adds zero padding\n    function toBytes32(string memory source) internal pure returns (bytes32) {\n        return bytes32(bytes(source));\n    }\n\n    /// @dev Removes zero padding\n    function bytes128ToString(bytes memory _bytes128) internal pure returns (string memory) {\n        require(_bytes128.length == 128, SizeNot128());\n\n        uint8 i = 0;\n        while (i < 128 && _bytes128[i] != 0) {\n            i++;\n        }\n\n        bytes memory bytesArray = new bytes(i);\n\n        for (uint8 j; j < i; j++) {\n            bytesArray[j] = _bytes128[j];\n        }\n\n        return string(bytesArray);\n    }\n\n    function toString(bytes32 _bytes32) internal pure returns (string memory) {\n        uint8 i = 0;\n        while (i < 32 && _bytes32[i] != 0) {\n            i++;\n        }\n        bytes memory bytesArray = new bytes(i);\n        for (i = 0; i < 32 && _bytes32[i] != 0; i++) {\n            bytesArray[i] = _bytes32[i];\n        }\n        return string(bytesArray);\n    }\n}\n"},{"file_path":"src/misc/types/D18.sol","source_code":"// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity 0.8.28;\n\n// Small library to handle fixed point number operations with 18 decimals with static typing support.\n\nimport {MathLib} from \"../libraries/MathLib.sol\";\n\ntype D18 is uint128;\n\nerror D18_DivisionByZero();\n\nusing MathLib for uint256;\n\n/// @dev add two D18 types\nfunction add(D18 d1, D18 d2) pure returns (D18) {\n    return D18.wrap(D18.unwrap(d1) + D18.unwrap(d2));\n}\n\n/// @dev subtract two D18 types\nfunction sub(D18 d1, D18 d2) pure returns (D18) {\n    return D18.wrap(D18.unwrap(d1) - D18.unwrap(d2));\n}\n\n/// @dev Divides one D18 by another one while retaining precision:\n/// - nominator (decimal): 50e18\n/// - denominator (decimal):  2e19\n/// - result (decimal): 25e17\nfunction divD18(D18 d1, D18 d2) pure returns (D18) {\n    return D18.wrap(MathLib.mulDiv(D18.unwrap(d1), 1e18, D18.unwrap(d2)).toUint128());\n}\n\n/// @dev Multiplies one D18 with another one while retaining precision:\n/// - value1 (decimal): 50e18\n/// - value2 (decimal):  2e19\n/// - result (decimal): 100e19\nfunction mulD18(D18 d1, D18 d2) pure returns (D18) {\n    return D18.wrap(MathLib.mulDiv(D18.unwrap(d1), D18.unwrap(d2), 1e18).toUint128());\n}\n\n/// @dev Returns the reciprocal of a D18 decimal, i.e. 1 / d.\n///      Example: if d = 2.0 (2e18 internally), reciprocal(d) = 0.5 (5e17 internally).\nfunction reciprocal(D18 d) pure returns (D18) {\n    uint128 val = D18.unwrap(d);\n    require(val != 0, D18_DivisionByZero());\n    return d18(1e18, val);\n}\n\n/// @dev Multiplies a decimal by an integer. i.e:\n/// - d (decimal):      1_500_000_000_000_000_000\n/// - value (integer):  4_000_000_000_000_000_000\n/// - result (integer): 6_000_000_000_000_000_000\nfunction mulUint128(D18 d, uint128 value, MathLib.Rounding rounding) pure returns (uint128) {\n    return MathLib.mulDiv(D18.unwrap(d), value, 1e18, rounding).toUint128();\n}\n\n/// @dev Multiplies a decimal by an integer. i.e:\n/// - d (decimal):      1_500_000_000_000_000_000\n/// - value (integer):  4_000_000_000_000_000_000\n/// - result (integer): 6_000_000_000_000_000_000\nfunction mulUint256(D18 d, uint256 value, MathLib.Rounding rounding) pure returns (uint256) {\n    return MathLib.mulDiv(D18.unwrap(d), value, 1e18, rounding);\n}\n\n/// @dev  Divides an integer by a decimal, i.e.\n/// @dev  Same as mulDiv for integers, i.e:\n/// - d (decimal):      2_000_000_000_000_000_000\n/// - value (integer):  100_000_000_000_000_000_000\n/// - result (integer): 50_000_000_000_000_000_000\nfunction reciprocalMulUint128(D18 d, uint128 value, MathLib.Rounding rounding) pure returns (uint128) {\n    return MathLib.mulDiv(value, 1e18, d.raw(), rounding).toUint128();\n}\n\n/// @dev  Divides an integer by a decimal, i.e.\n/// @dev  Same as mulDiv for integers, i.e:\n/// - d (decimal):      2_000_000_000_000_000_000\n/// - value (integer):  100_000_000_000_000_000_000\n/// - result (integer): 50_000_000_000_000_000_000\nfunction reciprocalMulUint256(D18 d, uint256 value, MathLib.Rounding rounding) pure returns (uint256) {\n    return MathLib.mulDiv(value, 1e18, d.raw(), rounding);\n}\n\n/// @dev Easy way to construct a decimal number\nfunction d18(uint128 value) pure returns (D18) {\n    return D18.wrap(value);\n}\n\n/// @dev Easy way to construct a decimal number\nfunction d18(uint128 num, uint128 den) pure returns (D18) {\n    return D18.wrap(MathLib.mulDiv(num, 1e18, den).toUint128());\n}\n\nfunction eq(D18 a, D18 b) pure returns (bool) {\n    return D18.unwrap(a) == D18.unwrap(b);\n}\n\nfunction isZero(D18 a) pure returns (bool) {\n    return D18.unwrap(a) == 0;\n}\n\nfunction isNotZero(D18 a) pure returns (bool) {\n    return D18.unwrap(a) != 0;\n}\n\nfunction raw(D18 d) pure returns (uint128) {\n    return D18.unwrap(d);\n}\n\nusing {\n    add as +,\n    sub as -,\n    divD18 as /,\n    eq,\n    mulD18 as *,\n    mulUint128,\n    mulUint256,\n    reciprocalMulUint128,\n    reciprocalMulUint256,\n    reciprocal,\n    raw,\n    isZero,\n    isNotZero\n} for D18 global;\n"},{"file_path":"src/core/interfaces/IRequestManager.sol","source_code":"// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\nimport {PoolId} from \"../types/PoolId.sol\";\nimport {AssetId} from \"../types/AssetId.sol\";\nimport {ShareClassId} from \"../types/ShareClassId.sol\";\n\ninterface IRequestManager {\n    //----------------------------------------------------------------------------------------------\n    // Errors\n    //----------------------------------------------------------------------------------------------\n\n    error UnknownRequestCallbackType();\n\n    //----------------------------------------------------------------------------------------------\n    // Request handling\n    //----------------------------------------------------------------------------------------------\n\n    /// @notice Handles a request callback originating from the Hub side\n    /// @param poolId The pool id\n    /// @param scId The share class id\n    /// @param assetId The asset id\n    /// @param payload The payload to be processed by the request callback\n    function callback(PoolId poolId, ShareClassId scId, AssetId assetId, bytes calldata payload) external;\n}\n"},{"file_path":"src/core/messaging/interfaces/IGatewaySenders.sol","source_code":"// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\nimport {D18} from \"../../../misc/types/D18.sol\";\n\nimport {PoolId} from \"../../types/PoolId.sol\";\nimport {AssetId} from \"../../types/AssetId.sol\";\nimport {ShareClassId} from \"../../types/ShareClassId.sol\";\nimport {VaultUpdateKind} from \"../libraries/MessageLib.sol\";\n\ninterface ILocalCentrifugeId {\n    error CannotBeSentLocally();\n\n    function localCentrifugeId() external view returns (uint16);\n}\n\n/// @notice Interface for dispatch-only gateway\ninterface IScheduleAuthMessageSender {\n    /// @notice Creates and send the message\n    function sendScheduleUpgrade(uint16 centrifugeId, bytes32 target, address refund) external payable;\n\n    /// @notice Creates and send the message\n    function sendCancelUpgrade(uint16 centrifugeId, bytes32 target, address refund) external payable;\n\n    /// @notice Creates and send the message\n    function sendRecoverTokens(\n        uint16 centrifugeId,\n        bytes32 target,\n        bytes32 token,\n        uint256 tokenId,\n        bytes32 to,\n        uint256 amount,\n        address refund\n    ) external payable;\n}\n\n/// @notice Interface for dispatch-only gateway\ninterface IHubMessageSender is ILocalCentrifugeId {\n    /// @notice Creates and send the message\n    function sendNotifyPool(uint16 centrifugeId, PoolId poolId, address refund) external payable;\n\n    /// @notice Creates and send the message\n    function sendNotifyShareClass(\n        uint16 centrifugeId,\n        PoolId poolId,\n        ShareClassId scId,\n        string memory name,\n        string memory symbol,\n        uint8 decimals,\n        bytes32 salt,\n        bytes32 hook,\n        address refund\n    ) external payable;\n\n    /// @notice Creates and send the message\n    function sendNotifyShareMetadata(\n        uint16 centrifugeId,\n        PoolId poolId,\n        ShareClassId scId,\n        string memory name,\n        string memory symbol,\n        address refund\n    ) external payable;\n\n    /// @notice Creates and send the message\n    function sendUpdateShareHook(uint16 centrifugeId, PoolId poolId, ShareClassId scId, bytes32 hook, address refund)\n        external\n        payable;\n\n    /// @notice Creates and send the message\n    function sendNotifyPricePoolPerShare(\n        uint16 chainId,\n        PoolId poolId,\n        ShareClassId scId,\n        D18 pricePoolPerShare,\n        uint64 computedAt,\n        address refund\n    ) external payable;\n\n    /// @notice Creates and send the message\n    function sendNotifyPricePoolPerAsset(\n        PoolId poolId,\n        ShareClassId scId,\n        AssetId assetId,\n        D18 pricePoolPerAsset,\n        address refund\n    ) external payable;\n\n    /// @notice Creates and send the message\n    function sendUpdateRestriction(\n        uint16 centrifugeId,\n        PoolId poolId,\n        ShareClassId scId,\n        bytes calldata payload,\n        uint128 extraGasLimit,\n        address refund\n    ) external payable;\n\n    /// @notice Creates and send the message\n    function sendTrustedContractUpdate(\n        uint16 centrifugeId,\n        PoolId poolId,\n        ShareClassId scId,\n        bytes32 target,\n        bytes calldata payload,\n        uint128 extraGasLimit,\n        address refund\n    ) external payable;\n\n    /// @notice Creates and send the message\n    function sendUpdateVault(\n        PoolId poolId,\n        ShareClassId scId,\n        AssetId assetId,\n        bytes32 vaultOrFactory,\n        VaultUpdateKind kind,\n        uint128 extraGasLimit,\n        address refund\n    ) external payable;\n\n    /// @notice Creates and send the message\n    function sendSetRequestManager(uint16 centrifugeId, PoolId poolId, bytes32 manager, address refund) external payable;\n\n    /// @notice Creates and send the message\n    function sendUpdateBalanceSheetManager(\n        uint16 centrifugeId,\n        PoolId poolId,\n        bytes32 who,\n        bool canManage,\n        address refund\n    ) external payable;\n\n    /// @notice Creates and send the message\n    function sendExecuteTransferShares(\n        uint16 originCentrifugeId,\n        uint16 targetCentrifugeId,\n        PoolId poolId,\n        ShareClassId scId,\n        bytes32 receiver,\n        uint128 amount,\n        uint128 extraGasLimit,\n        address refund\n    ) external payable;\n\n    /// @notice Creates and send the message\n    function sendSetMaxAssetPriceAge(\n        PoolId poolId,\n        ShareClassId scId,\n        AssetId assetId,\n        uint64 maxPriceAge,\n        address refund\n    ) external payable;\n\n    /// @notice Creates and send the message\n    function sendSetMaxSharePriceAge(\n        uint16 centrifugeId,\n        PoolId poolId,\n        ShareClassId scId,\n        uint64 maxPriceAge,\n        address refund\n    ) external payable;\n\n    /// @notice Creates and send the message\n    function sendRequestCallback(\n        PoolId poolId,\n        ShareClassId scId,\n        AssetId assetId,\n        bytes calldata payload,\n        uint128 extraGasLimit,\n        bool unpaidMode,\n        address refund\n    ) external payable;\n\n    /// @notice Creates and send the message\n    function sendSetPoolAdapters(\n        uint16 centrifugeId,\n        PoolId poolId,\n        bytes32[] memory adapters,\n        uint8 threshold,\n        uint8 recoveryIndex,\n        address refund\n    ) external payable;\n\n    /// @notice Creates and send the message\n    function sendUpdateGatewayManager(uint16 centrifugeId, PoolId poolId, bytes32 who, bool canManage, address refund)\n        external\n        payable;\n}\n\n/// @notice Interface for dispatch-only gateway\ninterface ISpokeMessageSender is ILocalCentrifugeId {\n    struct UpdateData {\n        uint128 netAmount;\n        bool isIncrease;\n        bool isSnapshot;\n        uint64 nonce;\n    }\n\n    /// @notice Creates and send the message\n    function sendInitiateTransferShares(\n        uint16 centrifugeId,\n        PoolId poolId,\n        ShareClassId scId,\n        bytes32 receiver,\n        uint128 amount,\n        uint128 extraGasLimit,\n        uint128 remoteExtraGasLimit,\n        address refund\n    ) external payable;\n\n    /// @notice Creates and send the message\n    function sendRegisterAsset(uint16 centrifugeId, AssetId assetId, uint8 decimals, address refund) external payable;\n\n    /// @notice Creates and send the message\n    function sendUpdateHoldingAmount(\n        PoolId poolId,\n        ShareClassId scId,\n        AssetId assetId,\n        UpdateData calldata data,\n        D18 pricePoolPerAsset,\n        uint128 extraGasLimit,\n        address refund\n    ) external payable;\n\n    /// @notice Creates and send the message\n    function sendUpdateShares(\n        PoolId poolId,\n        ShareClassId scId,\n        UpdateData calldata data,\n        uint128 extraGasLimit,\n        address refund\n    ) external payable;\n\n    /// @notice Creates and send the message\n    function sendRequest(\n        PoolId poolId,\n        ShareClassId scId,\n        AssetId assetId,\n        bytes calldata payload,\n        uint128 extraGasLimit,\n        bool unpaidMode,\n        address refund\n    ) external payable;\n\n    /// @notice Creates and sends an UntrustedContractUpdate message\n    /// @param poolId The pool identifier\n    /// @param scId The share class identifier\n    /// @param target The hub-side target contract (as bytes32)\n    /// @param sender The spoke-side initiator (as bytes32)\n    /// @param payload The update payload\n    /// @param extraGasLimit Additional gas for cross-chain execution\n    /// @param refund Address to refund excess payment\n    function sendUntrustedContractUpdate(\n        PoolId poolId,\n        ShareClassId scId,\n        bytes32 target,\n        bytes calldata payload,\n        bytes32 sender,\n        uint128 extraGasLimit,\n        address refund\n    ) external payable;\n}\n"},{"file_path":"src/misc/interfaces/IRecoverable.sol","source_code":"// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\naddress constant ETH_ADDRESS = address(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE);\n\ninterface IRecoverable {\n    /// @notice Used to recover any ERC-20 token.\n    /// @dev    This method is called only by authorized entities\n    /// @param  token It could be 0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\n    ///         to recover locked native ETH or token compatible with ERC20.\n    /// @param  to Receiver of the funds\n    /// @param  amount Amount to send to the receiver.\n    function recoverTokens(address token, address to, uint256 amount) external;\n\n    /// @notice Used to recover any ERC-20 or ERC-6909 token.\n    /// @dev    This method is called only by authorized entities\n    /// @param  token It could be 0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee\n    ///         to recover locked native ETH or token compatible with ERC20 or ERC6909.\n    /// @param  tokenId The token id, i.e. non-zero if the underlying token is ERC6909 and else zero.\n    /// @param  to Receiver of the funds\n    /// @param  amount Amount to send to the receiver.\n    function recoverTokens(address token, uint256 tokenId, address to, uint256 amount) external;\n}\n"},{"file_path":"src/misc/Recoverable.sol","source_code":"// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity 0.8.28;\n\nimport {Auth} from \"./Auth.sol\";\nimport {IERC6909} from \"./interfaces/IERC6909.sol\";\nimport {SafeTransferLib} from \"./libraries/SafeTransferLib.sol\";\nimport {IRecoverable, ETH_ADDRESS} from \"./interfaces/IRecoverable.sol\";\n\n/// @title  Recoverable\n/// @notice Abstract contract that provides emergency token recovery functionality, allowing authorized parties\n///         to retrieve accidentally sent ETH, ERC20, or ERC6909 tokens from the contract to a specified\n///         receiver address.\nabstract contract Recoverable is Auth, IRecoverable {\n    /// @inheritdoc IRecoverable\n    function recoverTokens(address token, address receiver, uint256 amount) public auth {\n        if (token == ETH_ADDRESS) {\n            SafeTransferLib.safeTransferETH(receiver, amount);\n        } else {\n            SafeTransferLib.safeTransfer(token, receiver, amount);\n        }\n    }\n\n    /// @inheritdoc IRecoverable\n    function recoverTokens(address token, uint256 tokenId, address receiver, uint256 amount) external auth {\n        if (tokenId == 0) {\n            recoverTokens(token, receiver, amount);\n        } else {\n            IERC6909(token).transfer(receiver, tokenId, amount);\n        }\n    }\n}\n"},{"file_path":"src/misc/libraries/BytesLib.sol","source_code":"// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity 0.8.28;\n\n/// @title  Bytes Lib\n/// @dev    Bytes tightly packed arrays utility library for ethereum contracts written in Solidity.\n///         The library lets you concatenate, slice and type cast bytes arrays both in memory and storage.\n/// @author Modified from Solidity Bytes Arrays Utils v0.8.0\nlibrary BytesLib {\n    error SliceOverflow();\n    error SliceOutOfBounds();\n\n    function slice(bytes memory _bytes, uint256 _start, uint256 _length) internal pure returns (bytes memory) {\n        unchecked {\n            require(_length + 31 >= _length, SliceOverflow());\n        }\n        require(_bytes.length >= _start + _length, SliceOutOfBounds());\n\n        bytes memory tempBytes;\n\n        assembly {\n            switch iszero(_length)\n            case 0 {\n                // Get a location of some free memory and store it in tempBytes as\n                // Solidity does for memory variables.\n                tempBytes := mload(0x40)\n\n                // The first word of the slice result is potentially a partial\n                // word read from the original array. To read it, we calculate\n                // the length of that partial word and start copying that many\n                // bytes into the array. The first word we copy will start with\n                // data we don't care about, but the last `lengthmod` bytes will\n                // land at the beginning of the contents of the new array. When\n                // we're done copying, we overwrite the full first word with\n                // the actual length of the slice.\n                let lengthmod := and(_length, 31)\n\n                // The multiplication in the next line is necessary\n                // because when slicing multiples of 32 bytes (lengthmod == 0)\n                // the following copy loop was copying the origin's length\n                // and then ending prematurely not copying everything it should.\n                let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod)))\n                let end := add(mc, _length)\n\n                for {\n                    // The multiplication in the next line has the same exact purpose\n                    // as the one above.\n                    let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start)\n                } lt(mc, end) {\n                    mc := add(mc, 0x20)\n                    cc := add(cc, 0x20)\n                } { mstore(mc, mload(cc)) }\n\n                mstore(tempBytes, _length)\n\n                //update free-memory pointer\n                //allocating the array padded to 32 bytes like the compiler does now\n                mstore(0x40, and(add(mc, 31), not(31)))\n            }\n            //if we want a zero-length slice let's just return a zero-length array\n            default {\n                tempBytes := mload(0x40)\n                //zero out the 32 bytes slice we are about to return\n                //we need to do it because Solidity does not garbage collect\n                mstore(tempBytes, 0)\n\n                mstore(0x40, add(tempBytes, 0x20))\n            }\n        }\n\n        return tempBytes;\n    }\n\n    function sliceZeroPadded(bytes memory _bytes, uint256 _start, uint256 _length)\n        internal\n        pure\n        returns (bytes memory)\n    {\n        bool needsPad = _bytes.length < _start + _length;\n        if (!needsPad) return slice(_bytes, _start, _length);\n\n        bytes memory slice_ = slice(_bytes, _start, _bytes.length - _start);\n        bytes memory padding = new bytes(_length + _start - _bytes.length);\n        return bytes.concat(slice_, padding);\n    }\n\n    function toAddress(bytes memory _bytes, uint256 _start) internal pure returns (address) {\n        require(_bytes.length >= _start + 20, SliceOutOfBounds());\n        address tempAddress;\n\n        assembly {\n            tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000)\n        }\n\n        return tempAddress;\n    }\n\n    function toUint8(bytes memory _bytes, uint256 _start) internal pure returns (uint8) {\n        require(_bytes.length >= _start + 1, SliceOutOfBounds());\n        uint8 tempUint;\n\n        assembly {\n            tempUint := mload(add(add(_bytes, 0x1), _start))\n        }\n\n        return tempUint;\n    }\n\n    function toUint16(bytes memory _bytes, uint256 _start) internal pure returns (uint16) {\n        require(_bytes.length >= _start + 2, SliceOutOfBounds());\n        uint16 tempUint;\n\n        assembly {\n            tempUint := mload(add(add(_bytes, 0x2), _start))\n        }\n\n        return tempUint;\n    }\n\n    function toUint32(bytes memory _bytes, uint256 _start) internal pure returns (uint32) {\n        require(_bytes.length >= _start + 4, SliceOutOfBounds());\n        uint32 tempUint;\n\n        assembly {\n            tempUint := mload(add(add(_bytes, 0x4), _start))\n        }\n\n        return tempUint;\n    }\n\n    function toUint64(bytes memory _bytes, uint256 _start) internal pure returns (uint64) {\n        require(_bytes.length >= _start + 8, SliceOutOfBounds());\n        uint64 tempUint;\n\n        assembly {\n            tempUint := mload(add(add(_bytes, 0x8), _start))\n        }\n\n        return tempUint;\n    }\n\n    function toUint128(bytes memory _bytes, uint256 _start) internal pure returns (uint128) {\n        require(_bytes.length >= _start + 16, SliceOutOfBounds());\n        uint128 tempUint;\n\n        assembly {\n            tempUint := mload(add(add(_bytes, 0x10), _start))\n        }\n\n        return tempUint;\n    }\n\n    function toUint256(bytes memory _bytes, uint256 _start) internal pure returns (uint256) {\n        require(_bytes.length >= _start + 32, SliceOutOfBounds());\n        uint256 tempUint;\n\n        assembly {\n            tempUint := mload(add(add(_bytes, 0x20), _start))\n        }\n\n        return tempUint;\n    }\n\n    function toBytes32(bytes memory _bytes, uint256 _start) internal pure returns (bytes32) {\n        require(_bytes.length >= _start + 32, SliceOutOfBounds());\n        bytes32 tempBytes32;\n\n        assembly {\n            tempBytes32 := mload(add(add(_bytes, 0x20), _start))\n        }\n\n        return tempBytes32;\n    }\n\n    function toBytes16(bytes memory _bytes, uint256 _start) internal pure returns (bytes16) {\n        require(_bytes.length >= _start + 16, SliceOutOfBounds());\n        bytes16 tempBytes16;\n\n        assembly {\n            tempBytes16 := mload(add(add(_bytes, 0x20), _start))\n        }\n\n        return tempBytes16;\n    }\n\n    function toBool(bytes memory _bytes, uint256 _start) internal pure returns (bool) {\n        require(_bytes.length > _start, SliceOutOfBounds());\n        return _bytes[_start] != 0;\n    }\n}\n"},{"file_path":"src/core/spoke/interfaces/IShareToken.sol","source_code":"// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\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    //----------------------------------------------------------------------------------------------\n    // Events\n    //----------------------------------------------------------------------------------------------\n\n    event File(bytes32 indexed what, address data);\n    event SetHookData(address indexed user, bytes16 data);\n\n    //----------------------------------------------------------------------------------------------\n    // Errors\n    //----------------------------------------------------------------------------------------------\n\n    error NotAuthorizedOrHook();\n    error ExceedsMaxSupply();\n    error RestrictionsFailed();\n\n    //----------------------------------------------------------------------------------------------\n    // Structs\n    //----------------------------------------------------------------------------------------------\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    //----------------------------------------------------------------------------------------------\n    // Administration\n    //----------------------------------------------------------------------------------------------\n\n    /// @notice Returns the hook that transfers perform callbacks to\n    /// @dev MUST comply to `ITransferHook` interface\n    /// @return The hook contract address\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    /// @param data The new string value\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    /// @param data The new address value\n    function file(bytes32 what, address data) external;\n\n    /// @notice Updates the vault for a given `asset`\n    /// @param asset The asset address\n    /// @param vault_ The vault address\n    function updateVault(address asset, address vault_) external;\n\n    //----------------------------------------------------------------------------------------------\n    // ERC20 overrides\n    //----------------------------------------------------------------------------------------------\n\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    /// @param user The user address\n    /// @return The 16 byte hook data\n    function hookDataOf(address user) external view returns (bytes16);\n\n    /// @notice Update the 16 byte hook data of the given `user`\n    /// @param user The user address\n    /// @param hookData The new hook data\n    function setHookData(address user, bytes16 hookData) external;\n\n    /// @notice Function to mint tokens\n    /// @param user The address to mint tokens to\n    /// @param value The amount of tokens to mint\n    function mint(address user, uint256 value) external;\n\n    /// @notice Function to burn tokens\n    /// @param user The address to burn tokens from\n    /// @param value The amount of tokens to burn\n    function burn(address user, uint256 value) external;\n\n    /// @notice Checks if the tokens can be transferred given the input values\n    /// @param from The sender address\n    /// @param to The recipient address\n    /// @param value The amount to transfer\n    /// @return Whether the transfer is allowed\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    /// @param sender The address initiating the transfer\n    /// @param from The address to transfer from\n    /// @param to The address to transfer to\n    /// @param amount The amount to transfer\n    /// @return Whether the transfer succeeded\n    function authTransferFrom(address sender, address from, address to, uint256 amount) external returns (bool);\n}\n"},{"file_path":"src/core/types/PoolId.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.28;\n\nimport {MathLib} from \"../../misc/libraries/MathLib.sol\";\n\nusing MathLib for uint256;\n\ntype PoolId is uint64;\n\nfunction centrifugeId(PoolId poolId) pure returns (uint16) {\n    return uint16(PoolId.unwrap(poolId) >> 48);\n}\n\nfunction newPoolId(uint16 centrifugeId_, uint48 localPoolId) pure returns (PoolId) {\n    return PoolId.wrap((uint64(centrifugeId_) << 48) | uint64(localPoolId));\n}\n\nfunction isNull(PoolId poolId) pure returns (bool) {\n    return PoolId.unwrap(poolId) == 0;\n}\n\nfunction isEqual(PoolId a, PoolId b) pure returns (bool) {\n    return PoolId.unwrap(a) == PoolId.unwrap(b);\n}\n\nfunction raw(PoolId poolId) pure returns (uint64) {\n    return PoolId.unwrap(poolId);\n}\n\nusing {centrifugeId, isNull, raw, isEqual as ==} for PoolId global;\n"},{"file_path":"src/core/spoke/factories/interfaces/IPoolEscrowFactory.sol","source_code":"// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\nimport {PoolId} from \"../../../types/PoolId.sol\";\nimport {IPoolEscrow} from \"../../interfaces/IPoolEscrow.sol\";\n\n/// @title  IPoolEscrowProvider\n/// @notice Interface for deterministic pool escrow address resolution\ninterface IPoolEscrowProvider {\n    /// @notice Returns the deterministic address of an escrow contract based on a given pool id\n    ///         wrapped into the corresponding interface.\n    ///\n    /// @dev Does not check, whether the escrow was already deployed.\n    function escrow(PoolId poolId) external view returns (IPoolEscrow);\n}\n\n/// @title  IPoolEscrowFactory\n/// @notice Factory for deploying deterministic pool escrow contracts\n/// @dev    Each pool has a unique escrow contract shared across all its share classes\ninterface IPoolEscrowFactory is IPoolEscrowProvider {\n    event DeployPoolEscrow(PoolId indexed poolId, address indexed escrow);\n    event File(bytes32 what, address data);\n\n    error FileUnrecognizedParam();\n    error EscrowAlreadyDeployed();\n\n    /// @notice Deploys new escrow and returns it.\n    /// @dev All share classes of a pool are represented by the same escrow contract.\n    ///\n    /// @param poolId Id of the pool this escrow is deployed for\n    /// @return IPoolEscrow The the newly deployed escrow contract\n    function newEscrow(PoolId poolId) external returns (IPoolEscrow);\n\n    /// @notice Updates contract parameters of type address.\n    function file(bytes32 what, address data) external;\n}\n"},{"file_path":"src/core/spoke/interfaces/IPoolEscrow.sol","source_code":"// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\nimport {IRecoverable} from \"../../../misc/Recoverable.sol\";\nimport {IEscrow} from \"../../../misc/interfaces/IEscrow.sol\";\n\nimport {PoolId} from \"../../types/PoolId.sol\";\nimport {ShareClassId} from \"../../types/ShareClassId.sol\";\n\nstruct Holding {\n    uint128 total;\n    uint128 reserved;\n}\n\n/// @title Per-Pool Escrow separating funds by pool and share class\ninterface IPoolEscrow is IEscrow, IRecoverable {\n    //----------------------------------------------------------------------------------------------\n    // Events\n    //----------------------------------------------------------------------------------------------\n\n    /// @notice Emitted when a deposit is made\n    /// @param asset The address of the deposited asset\n    /// @param tokenId The id of the asset - 0 for ERC20\n    /// @param poolId The id of the pool\n    /// @param scId The id of the share class\n    /// @param value The amount deposited\n    event Deposit(\n        address indexed asset, uint256 indexed tokenId, PoolId indexed poolId, ShareClassId scId, uint128 value\n    );\n\n    /// @notice Emitted when an amount is reserved\n    /// @param asset The address of the reserved asset\n    /// @param tokenId The id of the asset - 0 for ERC20\n    /// @param poolId The id of the pool\n    /// @param scId The id of the share class\n    /// @param caller The address of the manager creating the reservation\n    /// @param reason The reason code for the reservation\n    /// @param delta The delta amount reserved\n    /// @param value The new absolute amount reserved\n    event IncreaseReserve(\n        address indexed asset,\n        uint256 indexed tokenId,\n        PoolId indexed poolId,\n        ShareClassId scId,\n        address caller,\n        uint32 reason,\n        uint128 delta,\n        uint128 value\n    );\n\n    /// @notice Emitted when an amount is unreserved\n    /// @param asset The address of the reserved asset\n    /// @param tokenId The id of the asset - 0 for ERC20\n    /// @param poolId The id of the pool\n    /// @param scId The id of the share class\n    /// @param caller The address of the manager that created the reservation\n    /// @param reason The reason code that was used when reserving\n    /// @param delta The delta amount unreserved\n    /// @param value The new absolute amount reserved\n    event DecreaseReserve(\n        address indexed asset,\n        uint256 indexed tokenId,\n        PoolId indexed poolId,\n        ShareClassId scId,\n        address caller,\n        uint32 reason,\n        uint128 delta,\n        uint128 value\n    );\n\n    /// @notice Emitted when a withdraw is made\n    /// @param asset The address of the withdrawn asset\n    /// @param tokenId The id of the asset - 0 for ERC20\n    /// @param poolId The id of the pool\n    /// @param scId The id of the share class\n    /// @param receiver The address receiving the withdrawn assets\n    /// @param value The amount withdrawn\n    event Withdraw(\n        address indexed asset,\n        uint256 indexed tokenId,\n        PoolId indexed poolId,\n        ShareClassId scId,\n        address receiver,\n        uint128 value\n    );\n\n    /// @notice Emitted when ETH is transferred to the escrow\n    /// @param who The address that sent the ETH\n    /// @param amount The amount transferred\n    event ReceiveNativeTokens(address who, uint256 amount);\n\n    //----------------------------------------------------------------------------------------------\n    // Errors\n    //----------------------------------------------------------------------------------------------\n\n    /// @notice Dispatched when the balance of the escrow did not increase sufficiently\n    error InsufficientDeposit();\n\n    /// @notice Dispatched when the outstanding reserved amount is insufficient for the decrease\n    error InsufficientReserve();\n\n    //----------------------------------------------------------------------------------------------\n    // Functions\n    //----------------------------------------------------------------------------------------------\n\n    /// @notice Deposits `value` of `asset` in underlying `poolId` and given `scId`\n    /// @dev NOTE: Must ensure balance sufficiency, i.e. that the depositing amount does not exceed the balance of escrow\n    /// @param scId The id of the share class\n    /// @param asset The address of the asset to be deposited\n    /// @param tokenId The id of the asset - 0 for ERC20\n    /// @param value The amount to deposit\n    function deposit(ShareClassId scId, address asset, uint256 tokenId, uint128 value) external;\n\n    /// @notice Withdraws `value` of `asset` in underlying `poolId` and given `scId`\n    /// @dev If wasNoted is true, funds were already added to 'total' (decrements total and emits event)\n    ///      If wasNoted is false, funds are in 'reserved' only (just transfers, no accounting change)\n    /// @param scId The id of the share class\n    /// @param asset The address of the asset to be withdrawn\n    /// @param tokenId The id of the asset - 0 for ERC20\n    /// @param receiver The address receiving the withdrawn assets\n    /// @param value The amount to withdraw\n    function withdraw(ShareClassId scId, address asset, uint256 tokenId, address receiver, uint128 value) external;\n\n    /// @notice Increases the reserved amount of `value` for `asset` in underlying `poolId` and given `scId`\n    /// @dev Reserves funds in a specific bucket identified by caller and reason\n    /// @param scId The id of the share class\n    /// @param asset The address of the asset to be reserved\n    /// @param tokenId The id of the asset - 0 for ERC20\n    /// @param value The amount to reserve\n    /// @param caller The address of the manager creating the reservation (passed by BalanceSheet)\n    /// @param reason The reason code (1=DEPOSIT, 2=REDEEM)\n    function reserve(ShareClassId scId, address asset, uint256 tokenId, uint128 value, address caller, uint32 reason)\n        external;\n\n    /// @notice Decreases the reserved amount of `value` for `asset` in underlying `poolId` and given `scId`\n    /// @dev Unreserves funds from a specific bucket. MUST fail if bucket has insufficient funds.\n    /// @param scId The id of the share class\n    /// @param asset The address of the asset to be unreserved\n    /// @param tokenId The id of the asset - 0 for ERC20\n    /// @param value The amount to decrease\n    /// @param caller The address of the manager that created the reservation\n    /// @param reason The reason code that was used when reserving\n    function unreserve(ShareClassId scId, address asset, uint256 tokenId, uint128 value, address caller, uint32 reason)\n        external;\n\n    /// @notice Provides the available balance of `asset` in underlying `poolId` and given `scId`\n    /// @dev MUST return the balance minus the reserved amount\n    /// @param scId The id of the share class\n    /// @param asset The address of the asset to be checked\n    /// @param tokenId The id of the asset - 0 for ERC20\n    /// @return The available balance\n    function availableBalanceOf(ShareClassId scId, address asset, uint256 tokenId) external view returns (uint128);\n}\n"},{"file_path":"src/core/messaging/interfaces/IGateway.sol","source_code":"// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\nimport {IMessageHandler} from \"./IMessageHandler.sol\";\n\nimport {IRecoverable} from \"../../../misc/interfaces/IRecoverable.sol\";\n\nimport {PoolId} from \"../../types/PoolId.sol\";\n\n// Reserved gas amount for processing a message failure (assuming the worst case)\nuint256 constant PROCESS_FAIL_MESSAGE_GAS = 35_000;\n\n// Max length for a supported message. Note that a batch can use several messages with this length.\nuint256 constant MESSAGE_MAX_LENGTH = 1_000;\n\n// Max length of an error that happens when processing a message.\nuint16 constant ERR_MAX_LENGTH = 32 * 4; // enough for most errors\n\n/// @notice Interface for dispatch-only gateway\ninterface IGateway is IMessageHandler, IRecoverable {\n    //----------------------------------------------------------------------------------------------\n    // Structs\n    //----------------------------------------------------------------------------------------------\n\n    struct Underpaid {\n        uint128 gasLimit;\n        uint64 counter;\n    }\n\n    //----------------------------------------------------------------------------------------------\n    // Events\n    //----------------------------------------------------------------------------------------------\n\n    event File(bytes32 indexed what, address addr);\n    event UpdateManager(PoolId poolId, address who, bool canManage);\n    event BlockOutgoing(uint16 centrifugeId, PoolId poolId, bool isBlocked);\n    event PrepareMessage(uint16 indexed centrifugeId, PoolId poolId, bytes message);\n    event UnderpaidBatch(uint16 indexed centrifugeId, bytes batch, bytes32 batchHash);\n    event RepayBatch(uint16 indexed centrifugeId, bytes batch);\n    event ExecuteMessage(uint16 indexed centrifugeId, bytes32 messageHash);\n    event FailMessage(uint16 indexed centrifugeId, bytes32 messageHash, bytes error);\n    event SetRefundAddress(PoolId poolId, IRecoverable refund);\n    event DepositSubsidy(PoolId indexed poolId, address indexed sender, uint256 amount);\n    event WithdrawSubsidy(PoolId indexed poolId, address indexed sender, uint256 amount);\n\n    //----------------------------------------------------------------------------------------------\n    // Errors\n    //----------------------------------------------------------------------------------------------\n\n    /// @notice Dispatched when the `what` parameter of `file()` is not supported by the implementation.\n    error FileUnrecognizedParam();\n\n    /// @notice Dispatched when the batch is ended without starting it.\n    error NoBatched();\n\n    /// @notice Dispatched when the gateway is paused.\n    error Paused();\n\n    /// @notice Dispatched when the gateway tries to send an empty message.\n    error EmptyMessage();\n\n    /// @notice Dispatched when the message exceeds MESSAGE_MAX_LENGTH.\n    error TooLongMessage();\n\n    /// @notice Dispatched when a message that has not failed is retried.\n    error NotFailedMessage();\n\n    /// @notice Dispatched when a batch that has not been underpaid is repaid.\n    error NotUnderpaidBatch();\n\n    /// @notice Dispatched when the content of a batch doesn't belong to the same pool\n    error MalformedBatch();\n\n    /// @notice Dispatched when a message is sent but the gateway is blocked for sending messages\n    error OutgoingBlocked();\n\n    /// @notice Dispatched when an account is not valid to withdraw subsidized pool funds\n    error CannotRefund();\n\n    /// @notice Dispatched when there is not enough gas to send the message\n    error NotEnoughGas();\n\n    /// @notice Dispatched when the batch requires more gas than the destination chain can execute in a single transaction\n    error BatchTooExpensive();\n\n    /// @notice Dispatched when a message was batched but there was a payment for it\n    error NotPayable();\n\n    /// @notice Dispatched when the callback fails with no error\n    error CallFailedWithEmptyRevert();\n\n    /// @notice Dispatched when the callback is called inside the callback\n    error CallbackIsLocked();\n\n    /// @notice Dispatched when the user doesn't call lockCallback()\n    error CallbackWasNotLocked();\n\n    /// @notice Dispatched when the callback was not from the sender\n    error CallbackWasNotFromSender();\n\n    /// @notice Dispatched when there is not enough msg.value to send to the callback\n    error NotEnoughValueForCallback();\n\n    /// @notice Dispatched when trying to create a batch during the send loop\n    error ReentrantBatchCreation();\n\n    //----------------------------------------------------------------------------------------------\n    // Administration\n    //----------------------------------------------------------------------------------------------\n\n    /// @notice Used to update an address (state variable) on very rare occasions\n    /// @param what The name of the variable to be updated\n    /// @param data New address\n    function file(bytes32 what, address data) external;\n\n    /// @notice Configures a manager address for a pool\n    /// @param poolId PoolId associated to the adapters\n    /// @param who Manager address\n    /// @param canManage If enabled as manager\n    function updateManager(PoolId poolId, address who, bool canManage) external;\n\n    /// @notice Indicates if the gateway for a determined pool can send messages or not\n    /// @param centrifugeId Centrifuge ID associated to this block\n    /// @param poolId PoolId associated to this block\n    /// @param canSend If can send messages or not\n    function blockOutgoing(uint16 centrifugeId, PoolId poolId, bool canSend) external;\n\n    //----------------------------------------------------------------------------------------------\n    // Message handling\n    //----------------------------------------------------------------------------------------------\n\n    /// @notice Repay an underpaid batch\n    /// @param centrifugeId The destination chain\n    /// @param batch The batch to repay\n    /// @param refund Address to refund excess payment\n    function repay(uint16 centrifugeId, bytes memory batch, address refund) external payable;\n\n    /// @notice Retry a failed message\n    /// @param centrifugeId The destination chain\n    /// @param message The message to retry\n    function retry(uint16 centrifugeId, bytes memory message) external;\n\n    /// @notice Handling outgoing messages\n    /// @param centrifugeId Destination chain\n    /// @param message The message to send\n    /// @param unpaidMode Tells if storing the message as unpaid if not enough funds\n    /// @param refund Address to refund excess payment\n    function send(uint16 centrifugeId, bytes calldata message, bool unpaidMode, address refund) external payable;\n\n    //----------------------------------------------------------------------------------------------\n    // Batching\n    //----------------------------------------------------------------------------------------------\n\n    /// @notice Automatic batching of cross-chain transactions through a callback.\n    ///         Any cross-chain transactions triggered in this callback will automatically be batched.\n    /// @dev    Should be used like:\n    ///         ```\n    ///         contract Integration {\n    ///             IGateway gateway;\n    ///\n    ///             function doSomething(PoolId poolId) external {\n    ///                 gateway.withBatch(abi.encodeWithSelector(Integration.callback.selector, poolId));\n    ///             }\n    ///\n    ///             function callback(PoolId poolId) external {\n    ///                 // Avoid reentrancy to the callback and ensure it's called from withBatch in the same contract:\n    ///                 gateway.lockCallback();\n    ///\n    ///                 // Call several hub, balance sheet, or spoke methods that trigger cross-chain transactions\n    ///             }\n    ///         }\n    ///         ```\n    ///\n    ///         NOTE: inside callback, `msgSender` should be used instead of msg.sender\n    /// @param  callbackData encoding data for the callback method\n    /// @param  callbackValue msg.value to send to the callback\n    /// @param  refund Address to refund excess payment\n    function withBatch(bytes memory callbackData, uint256 callbackValue, address refund) external payable;\n\n    /// @notice Same as withBatch(..), but without sending any msg.value to the callback\n    function withBatch(bytes memory callbackData, address refund) external payable;\n\n    /// @notice Ensures the callback is called by withBatch in the same contract.\n    /// @dev calling this at the very beginning inside the multicall means:\n    ///         - The callback is called from the gateway under `withBatch`.\n    ///         - The callback is called from the same contract, because withBatch uses `msg.sender` as target for the callback\n    ///         - The callback that uses this can only be called once inside withBatch scope. No reentrancy.\n    function lockCallback() external;\n\n    //----------------------------------------------------------------------------------------------\n    // View methods\n    //----------------------------------------------------------------------------------------------\n\n    /// @notice Returns the current gateway batching level\n    /// @return Whether the gateway is currently batching\n    function isBatching() external view returns (bool);\n}\n"},{"file_path":"src/misc/ReentrancyProtection.sol","source_code":"// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity ^0.8.28;\n\n// NOTE: This file has warning disabled due https://github.com/ethereum/solidity/issues/14359\n// If perform any change on it, please ensure no other warnings appears\n\n/// @title  ReentrancyProtection\n/// @notice Abstract contract that implements reentrancy protection using transient storage.\nabstract contract ReentrancyProtection {\n    /// @notice Dispatched when there is a re-entrancy issue\n    error UnauthorizedSender();\n\n    address private transient _initiator;\n\n    /// @dev The method is protected for reentrancy issues.\n    modifier protected() {\n        if (_initiator == address(0)) {\n            // Single call re-entrancy lock\n            _initiator = msg.sender;\n            _;\n            _initiator = address(0);\n        } else {\n            // Multicall re-entrancy lock\n            require(msg.sender == _initiator, UnauthorizedSender());\n            _;\n        }\n    }\n}\n"},{"file_path":"src/core/types/AssetId.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.28;\n\n/// @dev Composite Id of the centrifugeId (uint16) where the asset resides\n///      and a local counter (uint64) that is part of the contract that registers the asset.\ntype AssetId is uint128;\n\nfunction isNull(AssetId assetId) pure returns (bool) {\n    return AssetId.unwrap(assetId) == 0;\n}\n\nfunction raw(AssetId assetId) pure returns (uint128) {\n    return AssetId.unwrap(assetId);\n}\n\nfunction centrifugeId(AssetId assetId) pure returns (uint16) {\n    return uint16(AssetId.unwrap(assetId) >> 112);\n}\n\nfunction newAssetId(uint16 centrifugeId_, uint64 counter) pure returns (AssetId) {\n    return AssetId.wrap((uint128(centrifugeId_) << 112) + counter);\n}\n\nfunction newAssetId(uint32 isoCode) pure returns (AssetId) {\n    return AssetId.wrap(isoCode);\n}\n\nfunction eq(AssetId a, AssetId b) pure returns (bool) {\n    return a.raw() == b.raw();\n}\n\nusing {isNull, raw, centrifugeId, eq as ==} for AssetId global;\n"},{"file_path":"src/core/messaging/interfaces/IGatewayHandlers.sol","source_code":"// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\nimport {D18} from \"../../../misc/types/D18.sol\";\n\nimport {PoolId} from \"../../types/PoolId.sol\";\nimport {AssetId} from \"../../types/AssetId.sol\";\nimport {ShareClassId} from \"../../types/ShareClassId.sol\";\nimport {VaultUpdateKind} from \"../libraries/MessageLib.sol\";\nimport {IRequestManager} from \"../../interfaces/IRequestManager.sol\";\n\n//--------------------------------------------------------------------------------------------------\n// Hub Handlers\n//--------------------------------------------------------------------------------------------------\n\n/// @notice Interface for Hub methods called by messages\ninterface IHubGatewayHandler {\n    /// @notice Tells that an asset was already registered in Vaults, in order to perform the corresponding register.\n    function registerAsset(AssetId assetId, uint8 decimals) external;\n\n    /// @notice Handles a request originating from the Spoke side.\n    /// @param  poolId The pool id\n    /// @param  scId The share class id\n    /// @param  assetId The asset id\n    /// @param  payload The request payload to be processed\n    function request(PoolId poolId, ShareClassId scId, AssetId assetId, bytes calldata payload) external;\n\n    /// @notice Update a holding by request from Vaults.\n    function updateHoldingAmount(\n        uint16 centrifugeId,\n        PoolId poolId,\n        ShareClassId scId,\n        AssetId assetId,\n        uint128 amount,\n        D18 pricePoolPerAsset,\n        bool isIncrease,\n        bool isSnapshot,\n        uint64 nonce\n    ) external;\n\n    /// @notice Forward an initiated share transfer to the destination chain.\n    function initiateTransferShares(\n        uint16 originCentrifugeId,\n        uint16 targetCentrifugeId,\n        PoolId poolId,\n        ShareClassId scId,\n        bytes32 receiver,\n        uint128 amount,\n        uint128 extraGasLimit,\n        address refund\n    ) external payable;\n\n    /// @notice Updates the total issuance of shares by request from vaults.\n    function updateShares(\n        uint16 centrifugeId,\n        PoolId poolId,\n        ShareClassId scId,\n        uint128 amount,\n        bool isIssuance,\n        bool isSnapshot,\n        uint64 nonce\n    ) external;\n}\n\n//--------------------------------------------------------------------------------------------------\n// Spoke Handlers\n//--------------------------------------------------------------------------------------------------\n\n/// @notice Interface for spoke related methods called by messages\ninterface ISpokeGatewayHandler {\n    /// @notice    New pool details from an existing Centrifuge pool are added.\n    /// @param     poolId The pool id\n    function addPool(PoolId poolId) external;\n\n    /// @notice     New share class details from an existing Centrifuge pool are added.\n    function addShareClass(\n        PoolId poolId,\n        ShareClassId scId,\n        string memory tokenName,\n        string memory tokenSymbol,\n        uint8 decimals,\n        bytes32 salt,\n        address hook\n    ) external;\n\n    /// @notice Updates the request manager for a pool\n    /// @param  poolId The centrifuge pool id\n    /// @param  manager The new request manager address\n    function setRequestManager(PoolId poolId, IRequestManager manager) external;\n\n    /// @notice   Updates the tokenName and tokenSymbol of a share class token\n    function updateShareMetadata(PoolId poolId, ShareClassId scId, string memory tokenName, string memory tokenSymbol)\n        external;\n\n    /// @notice  Updates the price (pool currency amount per share class token) of a share class token\n    /// @param  poolId The pool id\n    /// @param  scId The share class id\n    /// @param  price The price of pool currency per share class token.\n    /// @param  computedAt The timestamp when the price was computed\n    function updatePricePoolPerShare(PoolId poolId, ShareClassId scId, D18 price, uint64 computedAt) external;\n\n    /// @notice  Updates the price (pool currency amount per asset unit) of an asset\n    /// @param  poolId The pool id\n    /// @param  scId The share class id\n    /// @param  assetId The asset id\n    /// @param  price The price of pool currency per asset unit.\n    /// @param  computedAt The timestamp when the price was computed\n    function updatePricePoolPerAsset(PoolId poolId, ShareClassId scId, AssetId assetId, D18 price, uint64 computedAt)\n        external;\n\n    /// @notice Updates the hook of a share class token\n    /// @param  poolId The centrifuge pool id\n    /// @param  scId The share class id\n    /// @param  hook The new hook address\n    function updateShareHook(PoolId poolId, ShareClassId scId, address hook) external;\n\n    /// @notice Updates the restrictions on a share class token for a specific user\n    /// @param  poolId The centrifuge pool id\n    /// @param  scId The share class id\n    /// @param  update The restriction update in the form of a bytes array indicating\n    ///                the restriction to be updated, the user to be updated, and a validUntil timestamp.\n    function updateRestriction(PoolId poolId, ShareClassId scId, bytes memory update) external;\n\n    /// @notice Mints share class tokens to a recipient\n    function executeTransferShares(PoolId poolId, ShareClassId scId, bytes32 receiver, uint128 amount) external;\n\n    /// @notice Updates the max price age of an asset\n    /// @param  poolId The centrifuge pool id\n    /// @param  scId The share class id\n    /// @param  assetId The asset id\n    /// @param  maxPriceAge new max price age value\n    function setMaxAssetPriceAge(PoolId poolId, ShareClassId scId, AssetId assetId, uint64 maxPriceAge) external;\n\n    /// @notice Updates the max price age of a share\n    /// @param  poolId The centrifuge pool id\n    /// @param  scId The share class id\n    /// @param  maxPriceAge new max price age value\n    function setMaxSharePriceAge(PoolId poolId, ShareClassId scId, uint64 maxPriceAge) external;\n\n    /// @notice Handles a request callback originating from the Hub side.\n    /// @dev    Results from a Spoke-to-Hub-request as second order callback from the Hub.\n    /// @param  poolId The pool id\n    /// @param  scId The share class id\n    /// @param  assetId The asset id\n    /// @param  payload The payload to be processed by the request callback\n    function requestCallback(PoolId poolId, ShareClassId scId, AssetId assetId, bytes memory payload) external;\n}\n\n/// @notice Interface for the update contract method, called by message\ninterface IContractUpdateGatewayHandler {\n    /// @notice Updates the target address. Generic update function from Hub to Spoke\n    /// @param  poolId The centrifuge pool id\n    /// @param  scId The share class id\n    /// @param  target The target address to be called\n    /// @param  update The payload to be processed by the target address\n    function trustedCall(PoolId poolId, ShareClassId scId, address target, bytes memory update) external;\n\n    /// @notice Updates the target address. Generic update function from Spoke to Hub\n    /// @param  poolId The centrifuge pool id\n    /// @param  scId The share class id\n    /// @param  target The target address to be called\n    /// @param  update The payload to be processed by the target address\n    function untrustedCall(\n        PoolId poolId,\n        ShareClassId scId,\n        address target,\n        bytes memory update,\n        uint16 centrifugeId,\n        bytes32 sender\n    ) external;\n}\n\n/// @notice Interface for methods implemented by a balance sheet\ninterface IBalanceSheetGatewayHandler {\n    function updateManager(PoolId poolId, address who, bool canManage) external;\n}\n\n/// @notice Interface for VaultRegistry methods called by messages\ninterface IVaultRegistryGatewayHandler {\n    /// @notice Updates a vault based on VaultUpdateKind\n    /// @param  poolId The centrifuge pool id\n    /// @param  scId The share class id\n    /// @param  assetId The asset id\n    /// @param  vaultOrFactory The address of the vault or the factory, depending on the kind value\n    /// @param  kind The kind of action applied\n    function updateVault(\n        PoolId poolId,\n        ShareClassId scId,\n        AssetId assetId,\n        address vaultOrFactory,\n        VaultUpdateKind kind\n    ) external;\n}\n"},{"file_path":"src/misc/interfaces/IERC6909.sol","source_code":"// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\nimport {IERC165} from \"forge-std/interfaces/IERC165.sol\";\n\ninterface IERC6909 is IERC165 {\n    error EmptyOwner();\n    error EmptyAmount();\n    error InvalidTokenId();\n    error InsufficientBalance(address owner, uint256 tokenId);\n    error InsufficientAllowance(address sender, uint256 tokenId);\n\n    event OperatorSet(address indexed owner, address indexed operator, bool approved);\n    event Approval(address indexed owner, address indexed spender, uint256 indexed tokenId, uint256 amount);\n    event Transfer(address caller, address indexed from, address indexed to, uint256 indexed tokenId, uint256 amount);\n\n    /// @notice           Owner balance of a tokenId.\n    /// @param owner      The address of the owner.\n    /// @param tokenId    The id of the token.\n    /// @return amount    The balance of the token.\n    function balanceOf(address owner, uint256 tokenId) external view returns (uint256 amount);\n\n    /// @notice           Spender allowance of a tokenId.\n    /// @param owner      The address of the owner.\n    /// @param spender    The address of the spender.\n    /// @param tokenId    The id of the token.\n    /// @return amount    The allowance of the token.\n    function allowance(address owner, address spender, uint256 tokenId) external view returns (uint256 amount);\n\n    /// @notice           Checks if a spender is approved by an owner as an operator.\n    /// @param owner      The address of the owner.\n    /// @param spender    The address of the spender.\n    /// @return approved  The approval status.\n    function isOperator(address owner, address spender) external view returns (bool approved);\n\n    /// @notice           Transfers an amount of a tokenId from the caller to a receiver.\n    /// @param receiver   The address of the receiver.\n    /// @param tokenId    The id of the token.\n    /// @param amount     The amount of the token.\n    /// @return bool      True, always, unless the function reverts.\n    function transfer(address receiver, uint256 tokenId, uint256 amount) external returns (bool);\n\n    /// @notice           Transfers an amount of a tokenId from a sender to a receiver.\n    /// @param sender     The address of the sender.\n    /// @param receiver   The address of the receiver.\n    /// @param tokenId    The id of the token.\n    /// @param amount     The amount of the token.\n    /// @return bool      True, always, unless the function reverts.\n    function transferFrom(address sender, address receiver, uint256 tokenId, uint256 amount) external returns (bool);\n\n    /// @notice           Approves an amount of a tokenId to a spender.\n    /// @param spender    The address of the spender.\n    /// @param tokenId    The id of the token.\n    /// @param amount     The amount of the token.\n    /// @return bool      True, always.\n    function approve(address spender, uint256 tokenId, uint256 amount) external returns (bool);\n\n    /// @notice           Sets or removes an operator for the caller.\n    /// @param operator   The address of the operator.\n    /// @param approved   The approval status.\n    /// @return bool      True, always.\n    function setOperator(address operator, bool approved) external returns (bool);\n}\n\ninterface IERC6909URIExt {\n    event TokenURISet(uint256 indexed tokenId, string uri);\n    event ContractURISet(address indexed target, string uri);\n\n    error EmptyURI();\n\n    /// @return uri     Returns the common token URI.\n    function contractURI() external view returns (string memory);\n\n    /// @dev            Returns empty string if tokenId does not exist.\n    ///                 MAY implemented to throw MissingURI(tokenId) error.\n    /// @param tokenId  The token to query URI for.\n    /// @return uri     A string representing the uri for the specific tokenId.\n    function tokenURI(uint256 tokenId) external view returns (string memory);\n}\n\ninterface IERC6909NFT is IERC6909, IERC6909URIExt {\n    error UnknownTokenId(address owner, uint256 tokenId);\n    error LessThanMinimalDecimal(uint8 minimal, uint8 actual);\n\n    /// @notice             Provide URI for a specific tokenId.\n    /// @param tokenId      Token Id.\n    /// @param URI          URI to a document defining the collection as a whole.\n    function setTokenURI(uint256 tokenId, string memory URI) external;\n\n    /// @dev                Optional method to set up the contract URI if needed.\n    /// @param URI          URI to a document defining the collection as a whole.\n    function setContractURI(string memory URI) external;\n\n    /// @notice             Mint new tokens for a given owner and sets tokenURI.\n    /// @dev                For non-fungible tokens, call with amount = 1, for fungible it could be any amount.\n    ///                     TokenId is auto incremented by one.\n    ///\n    /// @param owner        Creates supply of a given tokenId by amount for owner.\n    /// @param tokenURI     URI fortestBurningToken the newly minted token.\n    /// @return tokenId     Id of the newly minted token.\n    function mint(address owner, string memory tokenURI) external returns (uint256 tokenId);\n\n    /// @notice             Destroy supply of a given tokenId by amount.\n    /// @dev                The msg.sender MUST be the owner.\n    ///\n    /// @param tokenId      Item which have reduced supply.\n    function burn(uint256 tokenId) external;\n}\n\n/// @notice Extension of ERC6909 Standard for tracking total supply\ninterface IERC6909TotalSupplyExt {\n    /// @notice         The totalSupply for a token id.\n    ///\n    /// @param tokenId  Id of the token\n    /// @return supply  Total supply for a given `tokenId`\n    function totalSupply(uint256 tokenId) external returns (uint256 supply);\n}\n\ninterface IERC6909Decimals {\n    /// @notice             Used to retrieve the decimals of an asset\n    /// @dev                address is used but the value corresponds to a AssetId\n    function decimals(uint256 assetId) external view returns (uint8);\n}\n\ninterface IERC6909MetadataExt is IERC6909Decimals {\n    /// @notice             Used to retrieve the decimals of an asset\n    /// @dev                address is used but the value corresponds to a AssetId\n    function decimals(uint256 assetId) external view returns (uint8);\n\n    /// @notice             Used to retrieve the name of an asset\n    /// @dev                address is used but the value corresponds to a AssetId\n    function name(uint256 assetId) external view returns (string memory);\n\n    /// @notice             Used to retrieve the symbol of an asset\n    /// @dev                address is used but the value corresponds to a AssetId\n    function symbol(uint256 assetId) external view returns (string memory);\n}\n\ninterface IERC6909Fungible is IERC6909 {\n    /// @notice             Mint new tokens for a specific tokenid and assign them to an owner\n    ///\n    /// @param owner        Creates supply of a given `tokenId` by `amount` for owner.\n    /// @param tokenId      Id of the item\n    /// @param amount       Adds `amount` to the total supply of the given `tokenId`\n    function mint(address owner, uint256 tokenId, uint256 amount) external;\n\n    /// @notice             Destroy supply of a given tokenId by amount.\n    /// @dev                The msg.sender MUST be the owner.\n    ///\n    /// @param owner        Owner of the `tokenId`\n    /// @param tokenId      Id of the item.\n    /// @param amount       Subtract `amount` from the total supply of the given `tokenId`\n    function burn(address owner, uint256 tokenId, uint256 amount) external;\n\n    /// @notice             Enforces a transfer from `spender` point of view.\n    ///\n    ///\n    /// @param sender       The owner of the `tokenId`\n    /// @param receiver     Address of the receiving party\n    /// @param tokenId      Token Id\n    /// @param amount       Amount to be transferred\n    function authTransferFrom(address sender, address receiver, uint256 tokenId, uint256 amount) external returns (bool);\n}\n\n/// @dev  A factory contract to deploy new collateral contracts implementing IERC6909.\ninterface IERC6909Factory {\n    /// Events\n    event NewTokenDeployment(address indexed owner, address instance);\n\n    /// @notice       Deploys new install of a contract that implements IERC6909.\n    /// @dev          Factory should deploy deterministically if possible.\n    ///\n    /// @param owner  Owner of the deployed collateral contract which has initial full rights.\n    /// @param salt   Used to make a deterministic deployment.\n    /// @return       An address of the newly deployed contract.\n    function deploy(address owner, bytes32 salt) external returns (address);\n\n    /// @notice       Generates a new deterministic address based on the owner and the salt.\n    ///\n    /// @param owner  Owner of the deployed collateral contract which has initial full rights.\n    /// @param salt   Used to make a deterministic deployment.\n    /// @return       An address of the newly deployed contract.\n    function previewAddress(address owner, bytes32 salt) external returns (address);\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/core/spoke/factories/interfaces/IVaultFactory.sol","source_code":"// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\nimport {PoolId} from \"../../../types/PoolId.sol\";\nimport {IVault} from \"../../interfaces/IVault.sol\";\nimport {IShareToken} from \"../../interfaces/IShareToken.sol\";\nimport {ShareClassId} from \"../../../types/ShareClassId.sol\";\n\n/// @title  IVaultFactory\n/// @notice Factory for deploying vault contracts for pool share classes\n/// @dev    Creates vaults linking pool IDs, share class IDs, assets, and tokens\ninterface IVaultFactory {\n    error UnsupportedTokenId();\n\n    /// @notice Deploys new vault for `poolId`, `scId` and `asset`.\n    ///\n    /// @param poolId Id of the pool. Id is one of the already supported pools.\n    /// @param scId Id of the share class token. Id is one of the already supported share class tokens.\n    /// @param asset Address of the underlying asset that is getting deposited inside the pool.\n    /// @param asset Token id of the underlying asset that is getting deposited inside the pool.\n    ///              I.e. zero if asset corresponds to ERC20 or non-zero if asset corresponds to ERC6909.\n    /// @param token Address of the share class token that is getting issues against the deposited asset.\n    function newVault(PoolId poolId, ShareClassId scId, address asset, uint256 tokenId, IShareToken token)\n        external\n        returns (IVault);\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    /// @param target The address to check for ward status\n    /// @return The ward status (1 if ward, 0 if not)\n    function wards(address target) external view returns (uint256);\n\n    /// @notice Make user a ward (give them admin access)\n    /// @param user The address to grant ward status to\n    function rely(address user) external;\n\n    /// @notice Remove user as a ward (remove admin access)\n    /// @param user The address to remove ward status from\n    function deny(address user) external;\n}\n"},{"file_path":"src/core/messaging/libraries/MessageLib.sol","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.28;\n\nimport {CastLib} from \"../../../misc/libraries/CastLib.sol\";\nimport {MathLib} from \"../../../misc/libraries/MathLib.sol\";\nimport {BytesLib} from \"../../../misc/libraries/BytesLib.sol\";\n\nimport {PoolId} from \"../../types/PoolId.sol\";\n\nenum MessageType {\n    /// @dev Placeholder for null message type\n    _Invalid,\n    // -- Pool independent messages\n    ScheduleUpgrade,\n    CancelUpgrade,\n    RecoverTokens,\n    RegisterAsset,\n    SetPoolAdapters,\n    // -- Pool dependent messages\n    NotifyPool,\n    NotifyShareClass,\n    NotifyPricePoolPerShare,\n    NotifyPricePoolPerAsset,\n    NotifyShareMetadata,\n    UpdateShareHook,\n    InitiateTransferShares,\n    ExecuteTransferShares,\n    UpdateRestriction,\n    UpdateVault,\n    UpdateBalanceSheetManager,\n    UpdateGatewayManager,\n    UpdateHoldingAmount,\n    UpdateShares,\n    SetMaxAssetPriceAge,\n    SetMaxSharePriceAge,\n    Request,\n    RequestCallback,\n    SetRequestManager,\n    TrustedContractUpdate,\n    UntrustedContractUpdate\n}\n\n/// @dev Used internally in the UpdateVault message (not represent a submessage)\nenum VaultUpdateKind {\n    DeployAndLink,\n    Link,\n    Unlink\n}\n\nlibrary MessageLib {\n    using MessageLib for bytes;\n    using BytesLib for bytes;\n    using CastLib for *;\n    using MathLib for *;\n\n    error UnknownMessageType();\n\n    /// @dev Encode all message lengths in this constant to avoid a large list of if/elseif checks\n    /// and reduce generated bytecode.\n    /// If the message has some dynamic part, will be added later in `messageLength()`.\n    // forgefmt: disable-next-item\n    uint256 constant MESSAGE_LENGTHS_1 =\n        (33  << uint8(MessageType.ScheduleUpgrade) * 8) +\n        (33  << uint8(MessageType.CancelUpgrade) * 8) +\n        (161 << uint8(MessageType.RecoverTokens) * 8) +\n        (18  << uint8(MessageType.RegisterAsset) * 8) +\n        (13  << uint8(MessageType.SetPoolAdapters) * 8) +\n        (9   << uint8(MessageType.NotifyPool) * 8) +\n        (250 << uint8(MessageType.NotifyShareClass) * 8) +\n        (49  << uint8(MessageType.NotifyPricePoolPerShare) * 8) +\n        (65  << uint8(MessageType.NotifyPricePoolPerAsset) * 8) +\n        (185 << uint8(MessageType.NotifyShareMetadata) * 8) +\n        (57  << uint8(MessageType.UpdateShareHook) * 8) +\n        (107  << uint8(MessageType.InitiateTransferShares) * 8) +\n        (89  << uint8(MessageType.ExecuteTransferShares) * 8) +\n        (41  << uint8(MessageType.UpdateRestriction) * 8) +\n        (90  << uint8(MessageType.UpdateVault) * 8) +\n        (42  << uint8(MessageType.UpdateBalanceSheetManager) * 8) +\n        (42  << uint8(MessageType.UpdateGatewayManager) * 8) +\n        (107  << uint8(MessageType.UpdateHoldingAmount) * 8) +\n        (75  << uint8(MessageType.UpdateShares) * 8) +\n        (49  << uint8(MessageType.SetMaxAssetPriceAge) * 8) +\n        (33  << uint8(MessageType.SetMaxSharePriceAge) * 8) +\n        (57  << uint8(MessageType.Request) * 8) +\n        (57  << uint8(MessageType.RequestCallback) * 8) +\n        (41  << uint8(MessageType.SetRequestManager) * 8) +\n        (73  << uint8(MessageType.TrustedContractUpdate) * 8) +\n        (105  << uint8(MessageType.UntrustedContractUpdate) * 8);\n\n    function messageType(bytes memory message) internal pure returns (MessageType) {\n        return MessageType(message.toUint8(0));\n    }\n\n    function messageCode(bytes memory message) internal pure returns (uint8) {\n        return message.toUint8(0);\n    }\n\n    function messageLength(bytes memory message) internal pure returns (uint16 length) {\n        uint8 kind = message.toUint8(0);\n        require(kind <= uint8(type(MessageType).max), UnknownMessageType());\n\n        length = uint16(uint8(bytes32(MESSAGE_LENGTHS_1)[31 - kind]));\n\n        // Special treatment for messages with dynamic size:\n        if (kind == uint8(MessageType.UpdateRestriction)) {\n            length += 2 + message.toUint16(length); //payloadLength\n        } else if (kind == uint8(MessageType.TrustedContractUpdate)) {\n            length += 2 + message.toUint16(length); //payloadLength\n        } else if (kind == uint8(MessageType.UntrustedContractUpdate)) {\n            length += 2 + message.toUint16(length); //payloadLength\n        } else if (kind == uint8(MessageType.Request)) {\n            length += 2 + message.toUint16(length); //payloadLength\n        } else if (kind == uint8(MessageType.RequestCallback)) {\n            length += 2 + message.toUint16(length); //payloadLength\n        } else if (kind == uint8(MessageType.SetPoolAdapters)) {\n            length += message.toUint16(11) * 32; // message with variable length\n        }\n    }\n\n    function messagePoolId(bytes memory message) internal pure returns (PoolId poolId) {\n        uint8 kind = message.toUint8(0);\n\n        // All messages from NotifyPool to the end contains a PoolId in position 1.\n        if (kind >= uint8(MessageType.NotifyPool)) {\n            return PoolId.wrap(message.toUint64(1));\n        }\n\n        return PoolId.wrap(0);\n    }\n\n    function messageExtraGasLimit(bytes memory message) internal pure returns (uint128) {\n        uint8 kind = message.toUint8(0);\n\n        if (kind == uint8(MessageType.InitiateTransferShares)) {\n            return message.toUint128(91);\n        } else if (kind == uint8(MessageType.ExecuteTransferShares)) {\n            return message.toUint128(73);\n        } else if (kind == uint8(MessageType.UpdateRestriction)) {\n            return message.toUint128(25);\n        } else if (kind == uint8(MessageType.TrustedContractUpdate)) {\n            return message.toUint128(57);\n        } else if (kind == uint8(MessageType.UntrustedContractUpdate)) {\n            return message.toUint128(89);\n        } else if (kind == uint8(MessageType.Request)) {\n            return message.toUint128(41);\n        } else if (kind == uint8(MessageType.RequestCallback)) {\n            return message.toUint128(41);\n        } else if (kind == uint8(MessageType.UpdateVault)) {\n            return message.toUint128(74);\n        } else if (kind == uint8(MessageType.UpdateHoldingAmount)) {\n            return message.toUint128(91);\n        } else if (kind == uint8(MessageType.UpdateShares)) {\n            return message.toUint128(59);\n        }\n\n        return 0;\n    }\n\n    //---------------------------------------\n    //    ScheduleUpgrade\n    //---------------------------------------\n\n    struct ScheduleUpgrade {\n        bytes32 target;\n    }\n\n    function deserializeScheduleUpgrade(bytes memory data) internal pure returns (ScheduleUpgrade memory) {\n        require(messageType(data) == MessageType.ScheduleUpgrade, UnknownMessageType());\n        return ScheduleUpgrade({target: data.toBytes32(1)});\n    }\n\n    function serialize(ScheduleUpgrade memory t) internal pure returns (bytes memory) {\n        return abi.encodePacked(MessageType.ScheduleUpgrade, t.target);\n    }\n\n    //---------------------------------------\n    //    CancelUpgrade\n    //---------------------------------------\n\n    struct CancelUpgrade {\n        bytes32 target;\n    }\n\n    function deserializeCancelUpgrade(bytes memory data) internal pure returns (CancelUpgrade memory) {\n        require(messageType(data) == MessageType.CancelUpgrade, UnknownMessageType());\n        return CancelUpgrade({target: data.toBytes32(1)});\n    }\n\n    function serialize(CancelUpgrade memory t) internal pure returns (bytes memory) {\n        return abi.encodePacked(MessageType.CancelUpgrade, t.target);\n    }\n\n    //---------------------------------------\n    //    RecoverTokens\n    //---------------------------------------\n\n    struct RecoverTokens {\n        bytes32 target;\n        bytes32 token;\n        uint256 tokenId;\n        bytes32 to;\n        uint256 amount;\n    }\n\n    function deserializeRecoverTokens(bytes memory data) internal pure returns (RecoverTokens memory) {\n        require(messageType(data) == MessageType.RecoverTokens, UnknownMessageType());\n        return RecoverTokens({\n            target: data.toBytes32(1),\n            token: data.toBytes32(33),\n            tokenId: data.toUint256(65),\n            to: data.toBytes32(97),\n            amount: data.toUint256(129)\n        });\n    }\n\n    function serialize(RecoverTokens memory t) internal pure returns (bytes memory) {\n        return abi.encodePacked(MessageType.RecoverTokens, t.target, t.token, t.tokenId, t.to, t.amount);\n    }\n\n    //---------------------------------------\n    //    RegisterAsset\n    //---------------------------------------\n\n    struct RegisterAsset {\n        uint128 assetId;\n        uint8 decimals;\n    }\n\n    function deserializeRegisterAsset(bytes memory data) internal pure returns (RegisterAsset memory) {\n        require(messageType(data) == MessageType.RegisterAsset, UnknownMessageType());\n        return RegisterAsset({assetId: data.toUint128(1), decimals: data.toUint8(17)});\n    }\n\n    function serialize(RegisterAsset memory t) internal pure returns (bytes memory) {\n        return abi.encodePacked(MessageType.RegisterAsset, t.assetId, t.decimals);\n    }\n\n    //---------------------------------------\n    //   SetPoolAdapters\n    //---------------------------------------\n\n    struct SetPoolAdapters {\n        uint64 poolId;\n        uint8 threshold;\n        uint8 recoveryIndex;\n        bytes32[] adapterList;\n    }\n\n    function deserializeSetPoolAdapters(bytes memory data) internal pure returns (SetPoolAdapters memory) {\n        require(messageType(data) == MessageType.SetPoolAdapters, UnknownMessageType());\n\n        uint16 length = data.toUint16(11);\n        bytes32[] memory adapterList = new bytes32[](length);\n        for (uint256 i; i < length; i++) {\n            adapterList[i] = data.toBytes32(13 + i * 32);\n        }\n\n        return SetPoolAdapters({\n            poolId: data.toUint64(1),\n            threshold: data.toUint8(9),\n            recoveryIndex: data.toUint8(10),\n            adapterList: adapterList\n        });\n    }\n\n    function serialize(SetPoolAdapters memory t) internal pure returns (bytes memory) {\n        return abi.encodePacked(\n            MessageType.SetPoolAdapters,\n            t.poolId,\n            t.threshold,\n            t.recoveryIndex,\n            t.adapterList.length.toUint16(),\n            t.adapterList\n        );\n    }\n\n    //---------------------------------------\n    //    NotifyPool\n    //---------------------------------------\n\n    struct NotifyPool {\n        uint64 poolId;\n    }\n\n    function deserializeNotifyPool(bytes memory data) internal pure returns (NotifyPool memory) {\n        require(messageType(data) == MessageType.NotifyPool, UnknownMessageType());\n        return NotifyPool({poolId: data.toUint64(1)});\n    }\n\n    function serialize(NotifyPool memory t) internal pure returns (bytes memory) {\n        return abi.encodePacked(MessageType.NotifyPool, t.poolId);\n    }\n\n    //---------------------------------------\n    //    NotifyShareClass\n    //---------------------------------------\n\n    struct NotifyShareClass {\n        uint64 poolId;\n        bytes16 scId;\n        string name; // Fixed to 128 bytes\n        bytes32 symbol; // utf8\n        uint8 decimals;\n        bytes32 salt;\n        bytes32 hook;\n    }\n\n    function deserializeNotifyShareClass(bytes memory data) internal pure returns (NotifyShareClass memory) {\n        require(messageType(data) == MessageType.NotifyShareClass, UnknownMessageType());\n        return NotifyShareClass({\n            poolId: data.toUint64(1),\n            scId: data.toBytes16(9),\n            name: data.slice(25, 128).bytes128ToString(),\n            symbol: data.toBytes32(153),\n            decimals: data.toUint8(185),\n            salt: data.toBytes32(186),\n            hook: data.toBytes32(218)\n        });\n    }\n\n    function serialize(NotifyShareClass memory t) internal pure returns (bytes memory) {\n        return abi.encodePacked(\n            MessageType.NotifyShareClass,\n            t.poolId,\n            t.scId,\n            bytes(t.name).sliceZeroPadded(0, 128),\n            t.symbol,\n            t.decimals,\n            t.salt,\n            t.hook\n        );\n    }\n\n    //---------------------------------------\n    //    NotifyPricePoolPerShare\n    //---------------------------------------\n\n    struct NotifyPricePoolPerShare {\n        uint64 poolId;\n        bytes16 scId;\n        uint128 price;\n        uint64 timestamp;\n    }\n\n    function deserializeNotifyPricePoolPerShare(bytes memory data)\n        internal\n        pure\n        returns (NotifyPricePoolPerShare memory)\n    {\n        require(messageType(data) == MessageType.NotifyPricePoolPerShare, UnknownMessageType());\n        return NotifyPricePoolPerShare({\n            poolId: data.toUint64(1), scId: data.toBytes16(9), price: data.toUint128(25), timestamp: data.toUint64(41)\n        });\n    }\n\n    function serialize(NotifyPricePoolPerShare memory t) internal pure returns (bytes memory) {\n        return abi.encodePacked(MessageType.NotifyPricePoolPerShare, t.poolId, t.scId, t.price, t.timestamp);\n    }\n\n    //---------------------------------------\n    //    NotifyPricePoolPerAsset\n    //---------------------------------------\n\n    struct NotifyPricePoolPerAsset {\n        uint64 poolId;\n        bytes16 scId;\n        uint128 assetId;\n        uint128 price;\n        uint64 timestamp;\n    }\n\n    function deserializeNotifyPricePoolPerAsset(bytes memory data)\n        internal\n        pure\n        returns (NotifyPricePoolPerAsset memory)\n    {\n        require(messageType(data) == MessageType.NotifyPricePoolPerAsset, UnknownMessageType());\n        return NotifyPricePoolPerAsset({\n            poolId: data.toUint64(1),\n            scId: data.toBytes16(9),\n            assetId: data.toUint128(25),\n            price: data.toUint128(41),\n            timestamp: data.toUint64(57)\n        });\n    }\n\n    function serialize(NotifyPricePoolPerAsset memory t) internal pure returns (bytes memory) {\n        return abi.encodePacked(MessageType.NotifyPricePoolPerAsset, t.poolId, t.scId, t.assetId, t.price, t.timestamp);\n    }\n\n    //---------------------------------------\n    //    NotifyShareMetadata\n    //---------------------------------------\n\n    struct NotifyShareMetadata {\n        uint64 poolId;\n        bytes16 scId;\n        string name; // Fixed to 128 bytes\n        bytes32 symbol; // utf8\n    }\n\n    function deserializeNotifyShareMetadata(bytes memory data) internal pure returns (NotifyShareMetadata memory) {\n        require(messageType(data) == MessageType.NotifyShareMetadata, UnknownMessageType());\n        return NotifyShareMetadata({\n            poolId: data.toUint64(1),\n            scId: data.toBytes16(9),\n            name: data.slice(25, 128).bytes128ToString(),\n            symbol: data.toBytes32(153)\n        });\n    }\n\n    function serialize(NotifyShareMetadata memory t) internal pure returns (bytes memory) {\n        return abi.encodePacked(\n            MessageType.NotifyShareMetadata, t.poolId, t.scId, bytes(t.name).sliceZeroPadded(0, 128), t.symbol\n        );\n    }\n\n    //---------------------------------------\n    //    UpdateShareHook\n    //---------------------------------------\n\n    struct UpdateShareHook {\n        uint64 poolId;\n        bytes16 scId;\n        bytes32 hook;\n    }\n\n    function deserializeUpdateShareHook(bytes memory data) internal pure returns (UpdateShareHook memory) {\n        require(messageType(data) == MessageType.UpdateShareHook, UnknownMessageType());\n        return UpdateShareHook({poolId: data.toUint64(1), scId: data.toBytes16(9), hook: data.toBytes32(25)});\n    }\n\n    function serialize(UpdateShareHook memory t) internal pure returns (bytes memory) {\n        return abi.encodePacked(MessageType.UpdateShareHook, t.poolId, t.scId, t.hook);\n    }\n\n    //---------------------------------------\n    //    InitiateTransferShares\n    //---------------------------------------\n\n    struct InitiateTransferShares {\n        uint64 poolId;\n        bytes16 scId;\n        uint16 centrifugeId;\n        bytes32 receiver;\n        uint128 amount;\n        uint128 remoteExtraGasLimit;\n        uint128 extraGasLimit;\n    }\n\n    function deserializeInitiateTransferShares(bytes memory data)\n        internal\n        pure\n        returns (InitiateTransferShares memory)\n    {\n        require(messageType(data) == MessageType.InitiateTransferShares, UnknownMessageType());\n        return InitiateTransferShares({\n            poolId: data.toUint64(1),\n            scId: data.toBytes16(9),\n            centrifugeId: data.toUint16(25),\n            receiver: data.toBytes32(27),\n            amount: data.toUint128(59),\n            remoteExtraGasLimit: data.toUint128(75),\n            extraGasLimit: data.toUint128(91)\n        });\n    }\n\n    function serialize(InitiateTransferShares memory t) internal pure returns (bytes memory) {\n        return abi.encodePacked(\n            MessageType.InitiateTransferShares,\n            t.poolId,\n            t.scId,\n            t.centrifugeId,\n            t.receiver,\n            t.amount,\n            t.remoteExtraGasLimit,\n            t.extraGasLimit\n        );\n    }\n\n    //---------------------------------------\n    //    ExecuteTransferShares\n    //---------------------------------------\n\n    struct ExecuteTransferShares {\n        uint64 poolId;\n        bytes16 scId;\n        bytes32 receiver;\n        uint128 amount;\n        uint128 extraGasLimit;\n    }\n\n    function deserializeExecuteTransferShares(bytes memory data) internal pure returns (ExecuteTransferShares memory) {\n        require(messageType(data) == MessageType.ExecuteTransferShares, UnknownMessageType());\n        return ExecuteTransferShares({\n            poolId: data.toUint64(1),\n            scId: data.toBytes16(9),\n            receiver: data.toBytes32(25),\n            amount: data.toUint128(57),\n            extraGasLimit: data.toUint128(73)\n        });\n    }\n\n    function serialize(ExecuteTransferShares memory t) internal pure returns (bytes memory) {\n        return\n            abi.encodePacked(MessageType.ExecuteTransferShares, t.poolId, t.scId, t.receiver, t.amount, t.extraGasLimit);\n    }\n\n    //---------------------------------------\n    //    UpdateRestriction\n    //---------------------------------------\n\n    struct UpdateRestriction {\n        uint64 poolId;\n        bytes16 scId;\n        uint128 extraGasLimit;\n        bytes payload; // As sequence of bytes\n    }\n\n    function deserializeUpdateRestriction(bytes memory data) internal pure returns (UpdateRestriction memory) {\n        require(messageType(data) == MessageType.UpdateRestriction, UnknownMessageType());\n\n        uint16 payloadLength = data.toUint16(41);\n        return UpdateRestriction({\n            poolId: data.toUint64(1),\n            scId: data.toBytes16(9),\n            extraGasLimit: data.toUint128(25),\n            payload: data.slice(43, payloadLength)\n        });\n    }\n\n    function serialize(UpdateRestriction memory t) internal pure returns (bytes memory) {\n        return abi.encodePacked(\n            MessageType.UpdateRestriction, t.poolId, t.scId, t.extraGasLimit, t.payload.length.toUint16(), t.payload\n        );\n    }\n\n    //---------------------------------------\n    //    TrustedContractUpdate\n    //---------------------------------------\n\n    struct TrustedContractUpdate {\n        uint64 poolId;\n        bytes16 scId;\n        bytes32 target;\n        uint128 extraGasLimit;\n        bytes payload; // As sequence of bytes\n    }\n\n    function deserializeTrustedContractUpdate(bytes memory data) internal pure returns (TrustedContractUpdate memory) {\n        require(messageType(data) == MessageType.TrustedContractUpdate, UnknownMessageType());\n        uint16 payloadLength = data.toUint16(73);\n        return TrustedContractUpdate({\n            poolId: data.toUint64(1),\n            scId: data.toBytes16(9),\n            target: data.toBytes32(25),\n            extraGasLimit: data.toUint128(57),\n            payload: data.slice(75, payloadLength)\n        });\n    }\n\n    function serialize(TrustedContractUpdate memory t) internal pure returns (bytes memory) {\n        return abi.encodePacked(\n            MessageType.TrustedContractUpdate,\n            t.poolId,\n            t.scId,\n            t.target,\n            t.extraGasLimit,\n            t.payload.length.toUint16(),\n            t.payload\n        );\n    }\n\n    //---------------------------------------\n    //    UntrustedContractUpdate\n    //---------------------------------------\n\n    struct UntrustedContractUpdate {\n        uint64 poolId;\n        bytes16 scId;\n        bytes32 target;\n        bytes32 sender;\n        uint128 extraGasLimit;\n        bytes payload; // As sequence of bytes\n    }\n\n    function deserializeUntrustedContractUpdate(bytes memory data)\n        internal\n        pure\n        returns (UntrustedContractUpdate memory)\n    {\n        require(messageType(data) == MessageType.UntrustedContractUpdate, UnknownMessageType());\n        uint16 payloadLength = data.toUint16(105);\n        return UntrustedContractUpdate({\n            poolId: data.toUint64(1),\n            scId: data.toBytes16(9),\n            target: data.toBytes32(25),\n            sender: data.toBytes32(57),\n            extraGasLimit: data.toUint128(89),\n            payload: data.slice(107, payloadLength)\n        });\n    }\n\n    function serialize(UntrustedContractUpdate memory t) internal pure returns (bytes memory) {\n        return abi.encodePacked(\n            MessageType.UntrustedContractUpdate,\n            t.poolId,\n            t.scId,\n            t.target,\n            t.sender,\n            t.extraGasLimit,\n            t.payload.length.toUint16(),\n            t.payload\n        );\n    }\n\n    //---------------------------------------\n    //    Request\n    //---------------------------------------\n\n    struct Request {\n        uint64 poolId;\n        bytes16 scId;\n        uint128 assetId;\n        uint128 extraGasLimit;\n        bytes payload; // As sequence of bytes\n    }\n\n    function deserializeRequest(bytes memory data) internal pure returns (Request memory) {\n        require(messageType(data) == MessageType.Request, UnknownMessageType());\n        uint16 payloadLength = data.toUint16(57);\n        return Request({\n            poolId: data.toUint64(1),\n            scId: data.toBytes16(9),\n            assetId: data.toUint128(25),\n            extraGasLimit: data.toUint128(41),\n            payload: data.slice(59, payloadLength)\n        });\n    }\n\n    function serialize(Request memory t) internal pure returns (bytes memory) {\n        return abi.encodePacked(\n            MessageType.Request, t.poolId, t.scId, t.assetId, t.extraGasLimit, t.payload.length.toUint16(), t.payload\n        );\n    }\n\n    //---------------------------------------\n    //    RequestCallback\n    //---------------------------------------\n\n    struct RequestCallback {\n        uint64 poolId;\n        bytes16 scId;\n        uint128 assetId;\n        uint128 extraGasLimit;\n        bytes payload; // As sequence of bytes\n    }\n\n    function deserializeRequestCallback(bytes memory data) internal pure returns (RequestCallback memory) {\n        require(messageType(data) == MessageType.RequestCallback, UnknownMessageType());\n        uint16 payloadLength = data.toUint16(57);\n        return RequestCallback({\n            poolId: data.toUint64(1),\n            scId: data.toBytes16(9),\n            assetId: data.toUint128(25),\n            extraGasLimit: data.toUint128(41),\n            payload: data.slice(59, payloadLength)\n        });\n    }\n\n    function serialize(RequestCallback memory t) internal pure returns (bytes memory) {\n        return abi.encodePacked(\n            MessageType.RequestCallback,\n            t.poolId,\n            t.scId,\n            t.assetId,\n            t.extraGasLimit,\n            t.payload.length.toUint16(),\n            t.payload\n        );\n    }\n\n    //---------------------------------------\n    //   VaultUpdate\n    //---------------------------------------\n\n    struct UpdateVault {\n        uint64 poolId;\n        bytes16 scId;\n        uint128 assetId;\n        bytes32 vaultOrFactory;\n        uint8 kind; // VaultUpdateKind\n        uint128 extraGasLimit;\n    }\n\n    function deserializeUpdateVault(bytes memory data) internal pure returns (UpdateVault memory) {\n        require(messageType(data) == MessageType.UpdateVault, UnknownMessageType());\n        return UpdateVault({\n            poolId: data.toUint64(1),\n            scId: data.toBytes16(9),\n            assetId: data.toUint128(25),\n            vaultOrFactory: data.toBytes32(41),\n            kind: data.toUint8(73),\n            extraGasLimit: data.toUint128(74)\n        });\n    }\n\n    function serialize(UpdateVault memory t) internal pure returns (bytes memory) {\n        return abi.encodePacked(\n            MessageType.UpdateVault, t.poolId, t.scId, t.assetId, t.vaultOrFactory, t.kind, t.extraGasLimit\n        );\n    }\n\n    //---------------------------------------\n    //   SetRequestManager\n    //---------------------------------------\n\n    struct SetRequestManager {\n        uint64 poolId;\n        bytes32 manager;\n    }\n\n    function deserializeSetRequestManager(bytes memory data) internal pure returns (SetRequestManager memory) {\n        require(messageType(data) == MessageType.SetRequestManager, UnknownMessageType());\n        return SetRequestManager({poolId: data.toUint64(1), manager: data.toBytes32(9)});\n    }\n\n    function serialize(SetRequestManager memory t) internal pure returns (bytes memory) {\n        return abi.encodePacked(MessageType.SetRequestManager, t.poolId, t.manager);\n    }\n\n    //---------------------------------------\n    //   UpdateBalanceSheetManager\n    //---------------------------------------\n\n    struct UpdateBalanceSheetManager {\n        uint64 poolId;\n        bytes32 who;\n        bool canManage;\n    }\n\n    function deserializeUpdateBalanceSheetManager(bytes memory data)\n        internal\n        pure\n        returns (UpdateBalanceSheetManager memory)\n    {\n        require(messageType(data) == MessageType.UpdateBalanceSheetManager, UnknownMessageType());\n        return UpdateBalanceSheetManager({poolId: data.toUint64(1), who: data.toBytes32(9), canManage: data.toBool(41)});\n    }\n\n    function serialize(UpdateBalanceSheetManager memory t) internal pure returns (bytes memory) {\n        return abi.encodePacked(MessageType.UpdateBalanceSheetManager, t.poolId, t.who, t.canManage);\n    }\n\n    //---------------------------------------\n    //    UpdateHoldingAmount\n    //---------------------------------------\n\n    struct UpdateHoldingAmount {\n        uint64 poolId;\n        bytes16 scId;\n        uint128 assetId;\n        uint128 amount;\n        uint128 pricePoolPerAsset;\n        uint64 timestamp;\n        bool isIncrease;\n        bool isSnapshot;\n        uint64 nonce;\n        uint128 extraGasLimit;\n    }\n\n    function deserializeUpdateHoldingAmount(bytes memory data) internal pure returns (UpdateHoldingAmount memory h) {\n        require(messageType(data) == MessageType.UpdateHoldingAmount, UnknownMessageType());\n\n        return UpdateHoldingAmount({\n            poolId: data.toUint64(1),\n            scId: data.toBytes16(9),\n            assetId: data.toUint128(25),\n            amount: data.toUint128(41),\n            pricePoolPerAsset: data.toUint128(57),\n            timestamp: data.toUint64(73),\n            isIncrease: data.toBool(81),\n            isSnapshot: data.toBool(82),\n            nonce: data.toUint64(83),\n            extraGasLimit: data.toUint128(91)\n        });\n    }\n\n    function serialize(UpdateHoldingAmount memory t) internal pure returns (bytes memory) {\n        return abi.encodePacked(\n            MessageType.UpdateHoldingAmount,\n            t.poolId,\n            t.scId,\n            t.assetId,\n            t.amount,\n            t.pricePoolPerAsset,\n            t.timestamp,\n            t.isIncrease,\n            t.isSnapshot,\n            t.nonce,\n            t.extraGasLimit\n        );\n    }\n\n    //---------------------------------------\n    //    UpdateShares\n    //---------------------------------------\n\n    struct UpdateShares {\n        uint64 poolId;\n        bytes16 scId;\n        uint128 shares;\n        uint64 timestamp;\n        bool isIssuance;\n        bool isSnapshot;\n        uint64 nonce;\n        uint128 extraGasLimit;\n    }\n\n    function deserializeUpdateShares(bytes memory data) internal pure returns (UpdateShares memory) {\n        require(messageType(data) == MessageType.UpdateShares, UnknownMessageType());\n\n        return UpdateShares({\n            poolId: data.toUint64(1),\n            scId: data.toBytes16(9),\n            shares: data.toUint128(25),\n            timestamp: data.toUint64(41),\n            isIssuance: data.toBool(49),\n            isSnapshot: data.toBool(50),\n            nonce: data.toUint64(51),\n            extraGasLimit: data.toUint128(59)\n        });\n    }\n\n    function serialize(UpdateShares memory t) internal pure returns (bytes memory) {\n        return abi.encodePacked(\n            MessageType.UpdateShares,\n            t.poolId,\n            t.scId,\n            t.shares,\n            t.timestamp,\n            t.isIssuance,\n            t.isSnapshot,\n            t.nonce,\n            t.extraGasLimit\n        );\n    }\n\n    //---------------------------------------\n    //   SetMaxAssetPriceAge\n    //---------------------------------------\n\n    struct SetMaxAssetPriceAge {\n        uint64 poolId;\n        bytes16 scId;\n        uint128 assetId;\n        uint64 maxPriceAge;\n    }\n\n    function deserializeSetMaxAssetPriceAge(bytes memory data) internal pure returns (SetMaxAssetPriceAge memory) {\n        require(messageType(data) == MessageType.SetMaxAssetPriceAge, UnknownMessageType());\n        return SetMaxAssetPriceAge({\n            poolId: data.toUint64(1),\n            scId: data.toBytes16(9),\n            assetId: data.toUint128(25),\n            maxPriceAge: data.toUint64(41)\n        });\n    }\n\n    function serialize(SetMaxAssetPriceAge memory t) internal pure returns (bytes memory) {\n        return abi.encodePacked(MessageType.SetMaxAssetPriceAge, t.poolId, t.scId, t.assetId, t.maxPriceAge);\n    }\n\n    //---------------------------------------\n    //   SetMaxSharePriceAge\n    //---------------------------------------\n\n    struct SetMaxSharePriceAge {\n        uint64 poolId;\n        bytes16 scId;\n        uint64 maxPriceAge;\n    }\n\n    function deserializeSetMaxSharePriceAge(bytes memory data) internal pure returns (SetMaxSharePriceAge memory) {\n        require(messageType(data) == MessageType.SetMaxSharePriceAge, UnknownMessageType());\n        return SetMaxSharePriceAge({poolId: data.toUint64(1), scId: data.toBytes16(9), maxPriceAge: data.toUint64(25)});\n    }\n\n    function serialize(SetMaxSharePriceAge memory t) internal pure returns (bytes memory) {\n        return abi.encodePacked(MessageType.SetMaxSharePriceAge, t.poolId, t.scId, t.maxPriceAge);\n    }\n\n    //---------------------------------------\n    //   UpdateGatewayManager\n    //---------------------------------------\n\n    struct UpdateGatewayManager {\n        uint64 poolId;\n        bytes32 who;\n        bool canManage;\n    }\n\n    function deserializeUpdateGatewayManager(bytes memory data) internal pure returns (UpdateGatewayManager memory) {\n        require(messageType(data) == MessageType.UpdateGatewayManager, UnknownMessageType());\n        return UpdateGatewayManager({poolId: data.toUint64(1), who: data.toBytes32(9), canManage: data.toBool(41)});\n    }\n\n    function serialize(UpdateGatewayManager memory t) internal pure returns (bytes memory) {\n        return abi.encodePacked(MessageType.UpdateGatewayManager, t.poolId, t.who, t.canManage);\n    }\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/core/spoke/interfaces/ISpoke.sol","source_code":"// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\nimport {IShareToken} from \"./IShareToken.sol\";\nimport {IVault, VaultKind} from \"./IVault.sol\";\n\nimport {D18} from \"../../../misc/types/D18.sol\";\n\nimport {Price} from \"../types/Price.sol\";\nimport {PoolId} from \"../../types/PoolId.sol\";\nimport {AssetId} from \"../../types/AssetId.sol\";\nimport {ShareClassId} from \"../../types/ShareClassId.sol\";\nimport {IRequestManager} from \"../../interfaces/IRequestManager.sol\";\nimport {IVaultFactory} from \"../factories/interfaces/IVaultFactory.sol\";\n\n/// @dev Centrifuge pools\nstruct Pool {\n    /// @dev Timestamp of pool creation\n    uint64 createdAt;\n}\n\n/// @dev Each Centrifuge pool is associated to 1 or more share classes\nstruct ShareClassDetails {\n    IShareToken shareToken;\n    /// @dev Each share class has an individual price per share class unit in pool denomination (POOL_UNIT/SHARE_UNIT)\n    Price pricePoolPerShare;\n}\n\n/// @dev Eech share token maps to a pool and share class\nstruct TokenDetails {\n    PoolId poolId;\n    ShareClassId scId;\n}\n\nstruct AssetIdKey {\n    /// @dev The address of the asset\n    address asset;\n    /// @dev The ERC6909 token id or 0, if the underlying asset is an ERC20\n    uint256 tokenId;\n}\n\ninterface ISpoke {\n    //----------------------------------------------------------------------------------------------\n    // Events\n    //----------------------------------------------------------------------------------------------\n\n    event File(bytes32 indexed what, address data);\n    event RegisterAsset(\n        uint16 centrifugeId,\n        AssetId indexed assetId,\n        address indexed asset,\n        uint256 indexed tokenId,\n        string name,\n        string symbol,\n        uint8 decimals,\n        bool isInitialization\n    );\n    event AddPool(PoolId indexed poolId);\n    event AddShareClass(PoolId indexed poolId, ShareClassId indexed scId, IShareToken token);\n    event DeployVault(\n        PoolId indexed poolId,\n        ShareClassId indexed scId,\n        address indexed asset,\n        uint256 tokenId,\n        IVaultFactory factory,\n        IVault vault,\n        VaultKind kind\n    );\n    event SetRequestManager(PoolId indexed poolId, IRequestManager manager);\n    event UpdateAssetPrice(\n        PoolId indexed poolId,\n        ShareClassId indexed scId,\n        address indexed asset,\n        uint256 tokenId,\n        D18 price,\n        uint64 computedAt\n    );\n    event UpdateSharePrice(PoolId indexed poolId, ShareClassId indexed scId, D18 price, uint64 computedAt);\n    event InitiateTransferShares(\n        uint16 centrifugeId,\n        PoolId indexed poolId,\n        ShareClassId indexed scId,\n        address indexed sender,\n        bytes32 destinationAddress,\n        uint128 amount\n    );\n    event ExecuteTransferShares(\n        PoolId indexed poolId, ShareClassId indexed scId, address indexed receiver, uint128 amount\n    );\n    event LinkVault(\n        PoolId indexed poolId, ShareClassId indexed scId, address indexed asset, uint256 tokenId, IVault vault\n    );\n    event UnlinkVault(\n        PoolId indexed poolId, ShareClassId indexed scId, address indexed asset, uint256 tokenId, IVault vault\n    );\n    event UpdateMaxSharePriceAge(PoolId indexed poolId, ShareClassId indexed scId, uint64 maxPriceAge);\n    event UpdateMaxAssetPriceAge(\n        PoolId indexed poolId, ShareClassId indexed scId, address indexed asset, uint256 tokenId, uint64 maxPriceAge\n    );\n    event UntrustedContractUpdate(\n        uint16 indexed centrifugeId,\n        PoolId indexed poolId,\n        ShareClassId scId,\n        bytes32 target,\n        bytes payload,\n        address indexed sender\n    );\n\n    //----------------------------------------------------------------------------------------------\n    // Errors\n    //----------------------------------------------------------------------------------------------\n\n    error FileUnrecognizedParam();\n    error TooFewDecimals();\n    error TooManyDecimals();\n    error PoolAlreadyAdded();\n    error InvalidPool();\n    error ShareClassAlreadyRegistered();\n    error InvalidHook();\n    error OldMetadata();\n    error CannotSetOlderPrice();\n    error OldHook();\n    error UnknownVault();\n    error UnknownAsset();\n    error MalformedVaultUpdateMessage();\n    error InvalidFactory();\n    error InvalidPrice();\n    error AssetMissingDecimals();\n    error ShareTokenDoesNotExist();\n    error LocalTransferNotAllowed();\n    error CrossChainTransferNotAllowed();\n    error ShareTokenTransferFailed();\n    error TransferFromFailed();\n    error InvalidRequestManager();\n    error RequestManagerNotSet();\n    error InvalidManager();\n    error InvalidVault();\n    error AlreadyLinkedVault();\n    error AlreadyUnlinkedVault();\n\n    //----------------------------------------------------------------------------------------------\n    // Administration\n    //----------------------------------------------------------------------------------------------\n\n    /// @notice Updates a contract parameter\n    /// @param what Accepts a bytes32 representation of 'gateway', 'investmentManager', 'tokenFactory', or 'gasService'\n    /// @param data The new address\n    function file(bytes32 what, address data) external;\n\n    /// @notice Links a share token to a pool and share class\n    /// @param poolId The pool identifier\n    /// @param scId The share class identifier\n    /// @param shareToken The share token contract\n    function linkToken(PoolId poolId, ShareClassId scId, IShareToken shareToken) external;\n\n    /// @notice Updates a share token's vault reference for a specific asset\n    /// @param poolId The pool ID\n    /// @param scId The share class ID\n    /// @param asset The asset address\n    /// @param vault The vault address to set (or address(0) to unset)\n    function setShareTokenVault(PoolId poolId, ShareClassId scId, address asset, address vault) external;\n\n    //----------------------------------------------------------------------------------------------\n    // Outgoing methods\n    //----------------------------------------------------------------------------------------------\n\n    /// @notice Transfers share class tokens to a cross-chain recipient address\n    /// @dev To transfer to evm chains, pad a 20 byte evm address with 12 bytes of 0\n    /// @param centrifugeId The destination chain id\n    /// @param poolId The centrifuge pool id\n    /// @param scId The share class id\n    /// @param receiver A bytes32 representation of the receiver address\n    /// @param amount The amount of tokens to transfer\n    /// @param extraGasLimit Extra gas limit used for computation on the intermediary hub\n    /// @param remoteExtraGasLimit Extra gas limit used for computation in the destination chain\n    /// @param refund Address to refund the excess of the payment\n    function crosschainTransferShares(\n        uint16 centrifugeId,\n        PoolId poolId,\n        ShareClassId scId,\n        bytes32 receiver,\n        uint128 amount,\n        uint128 extraGasLimit,\n        uint128 remoteExtraGasLimit,\n        address refund\n    ) external payable;\n\n    /// @notice Transfers share class tokens to a cross-chain recipient address (legacy)\n    /// @dev Maintained for retrocompatibility. New implementers should use the above\n    /// @param centrifugeId The centrifuge id of chain to where the shares are transferred\n    /// @param poolId The centrifuge pool id\n    /// @param scId The share class id\n    /// @param receiver A bytes32 representation of the receiver address\n    /// @param amount The amount of tokens to transfer\n    /// @param remoteExtraGasLimit Extra gas limit used for computation in the destination chain\n    function crosschainTransferShares(\n        uint16 centrifugeId,\n        PoolId poolId,\n        ShareClassId scId,\n        bytes32 receiver,\n        uint128 amount,\n        uint128 remoteExtraGasLimit\n    ) external payable;\n\n    /// @notice Registers an ERC-20 or ERC-6909 asset in another chain.\n    /// @dev `decimals()` MUST return a `uint8` value between 2 and 18.\n    /// @dev `name()` and `symbol()` MAY return no values.\n    ///\n    /// @param centrifugeId The centrifuge id of chain to where the shares are transferred\n    /// @param asset The address of the asset to be registered\n    /// @param tokenId The token id corresponding to the asset, i.e. zero if ERC20 or non-zero if ERC6909.\n    /// @param refund Address to refund the excess of the payment\n    /// @return assetId The underlying internal uint128 assetId.\n    function registerAsset(uint16 centrifugeId, address asset, uint256 tokenId, address refund)\n        external\n        payable\n        returns (AssetId assetId);\n\n    /// @notice Initiates an update to a hub-side contract from spoke\n    /// @param poolId The pool identifier\n    /// @param scId The share class identifier\n    /// @param target The hub-side target contract (as bytes32 for cross-chain compatibility)\n    /// @param payload The update payload\n    /// @param extraGasLimit Additional gas for cross-chain execution\n    /// @param refund Address to refund excess payment\n    /// @dev Permissionless by choice, forwards caller's address to recipient for permission validation\n    function updateContract(\n        PoolId poolId,\n        ShareClassId scId,\n        bytes32 target,\n        bytes calldata payload,\n        uint128 extraGasLimit,\n        address refund\n    ) external payable;\n\n    /// @notice Handles a request originating from the Spoke side\n    /// @param poolId The pool id\n    /// @param scId The share class id\n    /// @param assetId The asset id\n    /// @param payload The request payload to be processed\n    /// @param extraGasLimit Additional gas stipend for cross-chain execution\n    /// @param unpaid Whether to allow unpaid mode\n    /// @param refund Address to refund excess payment\n    function request(\n        PoolId poolId,\n        ShareClassId scId,\n        AssetId assetId,\n        bytes memory payload,\n        uint128 extraGasLimit,\n        bool unpaid,\n        address refund\n    ) external payable;\n\n    //----------------------------------------------------------------------------------------------\n    // View methods\n    //----------------------------------------------------------------------------------------------\n\n    /// @notice Returns the asset address and tokenId associated with a given asset id.\n    /// @dev Reverts if asset id does not exist\n    ///\n    /// @param assetId The underlying internal uint128 assetId.\n    /// @return asset The address of the asset linked to the given asset id.\n    /// @return tokenId The token id corresponding to the asset, i.e. zero if ERC20 or non-zero if ERC6909.\n    function idToAsset(AssetId assetId) external view returns (address asset, uint256 tokenId);\n\n    /// @notice Returns assetId given the asset address and tokenId.\n    /// @dev Reverts if asset id does not exist\n    ///\n    /// @param asset The address of the asset linked to the given asset id.\n    /// @param tokenId The token id corresponding to the asset, i.e. zero if ERC20 or non-zero if ERC6909.\n    /// @return assetId The underlying internal uint128 assetId.\n    function assetToId(address asset, uint256 tokenId) external view returns (AssetId assetId);\n\n    /// @notice Returns poolId and shareClassId given a share token address\n    /// @dev Reverts if share token does not exist\n    ///\n    /// @param shareToken_ The address of the share token\n    /// @return poolId The pool id associated with the share token\n    /// @return scId The share class id associated with the share token\n    function shareTokenDetails(address shareToken_) external view returns (PoolId poolId, ShareClassId scId);\n\n    /// @notice Returns whether the given pool id is active\n    /// @param poolId The pool id\n    /// @return Whether the pool is active\n    function isPoolActive(PoolId poolId) external view returns (bool);\n\n    /// @notice Returns the share class token for a given pool and share class id\n    /// @dev Reverts if share class does not exists\n    /// @param poolId The pool id\n    /// @param scId The share class id\n    /// @return The address of the share token\n    function shareToken(PoolId poolId, ShareClassId scId) external view returns (IShareToken);\n\n    /// @notice Returns the price per share for a given pool and share class\n    /// @dev The provided price is defined as POOL_UNIT/SHARE_UNIT\n    /// @dev Conditionally checks if price is valid\n    /// @param poolId The pool id\n    /// @param scId The share class id\n    /// @param checkValidity Whether to check if the price is valid\n    /// @return price The pool price per share\n    function pricePoolPerShare(PoolId poolId, ShareClassId scId, bool checkValidity) external view returns (D18 price);\n\n    /// @notice Returns the price per asset for a given pool, share class and the underlying asset id\n    /// @dev The provided price is defined as POOL_UNIT/ASSET_UNIT\n    /// @dev Conditionally checks if price is valid\n    /// @param poolId The pool id\n    /// @param scId The share class id\n    /// @param assetId The asset id for which we want to know the POOL_UNIT/ASSET_UNIT\n    /// @param checkValidity Whether to check if the price is valid\n    /// @return price The pool price per asset unit\n    function pricePoolPerAsset(PoolId poolId, ShareClassId scId, AssetId assetId, bool checkValidity)\n        external\n        view\n        returns (D18 price);\n\n    /// @notice Returns both prices per pool for a given pool, share class and the underlying asset id\n    /// @dev The provided prices are defined as POOL_UNIT/ASSET_UNIT and POOL_UNIT/SHARE_UNIT\n    /// @dev Conditionally checks if prices are valid\n    /// @param poolId The pool id\n    /// @param scId The share class id\n    /// @param assetId The asset id for which we want to know pool price per asset\n    /// @param checkValidity Whether to check if the prices are valid\n    /// @return pricePoolPerAsset The pool price per asset unit, i.e. POOL_UNIT/ASSET_UNIT\n    /// @return pricePoolPerShare The pool price per share unit, i.e. POOL_UNIT/SHARE_UNIT\n    function pricesPoolPer(PoolId poolId, ShareClassId scId, AssetId assetId, bool checkValidity)\n        external\n        view\n        returns (D18 pricePoolPerAsset, D18 pricePoolPerShare);\n\n    /// @notice Returns the age related markers for a share class price\n    /// @param poolId The pool id\n    /// @param scId The share class id\n    /// @return computedAt The timestamp when this price was computed\n    /// @return maxAge The maximum age this price is allowed to have\n    /// @return validUntil The timestamp until this price is valid\n    function markersPricePoolPerShare(PoolId poolId, ShareClassId scId)\n        external\n        view\n        returns (uint64 computedAt, uint64 maxAge, uint64 validUntil);\n\n    /// @notice Returns the age related markers for an asset price\n    /// @param poolId The pool id\n    /// @param scId The share class id\n    /// @param assetId The asset id for which we want to know pool price per asset\n    /// @return computedAt The timestamp when this price was computed\n    /// @return maxAge The maximum age this price is allowed to have\n    /// @return validUntil The timestamp until this price is valid\n    function markersPricePoolPerAsset(PoolId poolId, ShareClassId scId, AssetId assetId)\n        external\n        view\n        returns (uint64 computedAt, uint64 maxAge, uint64 validUntil);\n\n    /// @notice Returns the request manager for a given pool\n    /// @param poolId The pool id\n    /// @return manager The request manager for the pool\n    function requestManager(PoolId poolId) external view returns (IRequestManager manager);\n}\n"}],"certified":false,"conflicting_implementations":null,"abi":[{"inputs":[{"internalType":"contract ITokenFactory","name":"tokenFactory_","type":"address"},{"internalType":"address","name":"deployer","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AlreadyLinkedVault","type":"error"},{"inputs":[],"name":"AlreadyUnlinkedVault","type":"error"},{"inputs":[],"name":"AssetMissingDecimals","type":"error"},{"inputs":[],"name":"CannotSetOlderPrice","type":"error"},{"inputs":[],"name":"CrossChainTransferNotAllowed","type":"error"},{"inputs":[],"name":"FileUnrecognizedParam","type":"error"},{"inputs":[],"name":"InvalidFactory","type":"error"},{"inputs":[],"name":"InvalidHook","type":"error"},{"inputs":[],"name":"InvalidManager","type":"error"},{"inputs":[],"name":"InvalidPool","type":"error"},{"inputs":[],"name":"InvalidPrice","type":"error"},{"inputs":[],"name":"InvalidRequestManager","type":"error"},{"inputs":[],"name":"InvalidVault","type":"error"},{"inputs":[],"name":"LocalTransferNotAllowed","type":"error"},{"inputs":[],"name":"MalformedVaultUpdateMessage","type":"error"},{"inputs":[],"name":"NoCode","type":"error"},{"inputs":[],"name":"NotAuthorized","type":"error"},{"inputs":[],"name":"OldHook","type":"error"},{"inputs":[],"name":"OldMetadata","type":"error"},{"inputs":[],"name":"PoolAlreadyAdded","type":"error"},{"inputs":[],"name":"PrefixNotZero","type":"error"},{"inputs":[],"name":"RequestManagerNotSet","type":"error"},{"inputs":[],"name":"SafeTransferEthFailed","type":"error"},{"inputs":[],"name":"ShareClassAlreadyRegistered","type":"error"},{"inputs":[],"name":"ShareTokenDoesNotExist","type":"error"},{"inputs":[],"name":"ShareTokenTransferFailed","type":"error"},{"inputs":[],"name":"TooFewDecimals","type":"error"},{"inputs":[],"name":"TooManyDecimals","type":"error"},{"inputs":[],"name":"TransferFromFailed","type":"error"},{"inputs":[],"name":"UnauthorizedSender","type":"error"},{"inputs":[],"name":"UnknownAsset","type":"error"},{"inputs":[],"name":"UnknownVault","type":"error"},{"inputs":[{"internalType":"address","name":"target","type":"address"},{"internalType":"bytes4","name":"selector","type":"bytes4"},{"internalType":"bytes","name":"reason","type":"bytes"},{"internalType":"bytes","name":"details","type":"bytes"}],"name":"WrappedError","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"PoolId","name":"poolId","type":"uint64"}],"name":"AddPool","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"PoolId","name":"poolId","type":"uint64"},{"indexed":true,"internalType":"ShareClassId","name":"scId","type":"bytes16"},{"indexed":false,"internalType":"contract IShareToken","name":"token","type":"address"}],"name":"AddShareClass","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"}],"name":"Deny","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"PoolId","name":"poolId","type":"uint64"},{"indexed":true,"internalType":"ShareClassId","name":"scId","type":"bytes16"},{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"contract IVaultFactory","name":"factory","type":"address"},{"indexed":false,"internalType":"contract IVault","name":"vault","type":"address"},{"indexed":false,"internalType":"enum VaultKind","name":"kind","type":"uint8"}],"name":"DeployVault","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"PoolId","name":"poolId","type":"uint64"},{"indexed":true,"internalType":"ShareClassId","name":"scId","type":"bytes16"},{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"uint128","name":"amount","type":"uint128"}],"name":"ExecuteTransferShares","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":false,"internalType":"uint16","name":"centrifugeId","type":"uint16"},{"indexed":true,"internalType":"PoolId","name":"poolId","type":"uint64"},{"indexed":true,"internalType":"ShareClassId","name":"scId","type":"bytes16"},{"indexed":true,"internalType":"address","name":"sender","type":"address"},{"indexed":false,"internalType":"bytes32","name":"destinationAddress","type":"bytes32"},{"indexed":false,"internalType":"uint128","name":"amount","type":"uint128"}],"name":"InitiateTransferShares","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"PoolId","name":"poolId","type":"uint64"},{"indexed":true,"internalType":"ShareClassId","name":"scId","type":"bytes16"},{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"contract IVault","name":"vault","type":"address"}],"name":"LinkVault","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint16","name":"centrifugeId","type":"uint16"},{"indexed":true,"internalType":"AssetId","name":"assetId","type":"uint128"},{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"string","name":"name","type":"string"},{"indexed":false,"internalType":"string","name":"symbol","type":"string"},{"indexed":false,"internalType":"uint8","name":"decimals","type":"uint8"},{"indexed":false,"internalType":"bool","name":"isInitialization","type":"bool"}],"name":"RegisterAsset","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"}],"name":"Rely","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"PoolId","name":"poolId","type":"uint64"},{"indexed":false,"internalType":"contract IRequestManager","name":"manager","type":"address"}],"name":"SetRequestManager","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"PoolId","name":"poolId","type":"uint64"},{"indexed":true,"internalType":"ShareClassId","name":"scId","type":"bytes16"},{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"contract IVault","name":"vault","type":"address"}],"name":"UnlinkVault","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint16","name":"centrifugeId","type":"uint16"},{"indexed":true,"internalType":"PoolId","name":"poolId","type":"uint64"},{"indexed":false,"internalType":"ShareClassId","name":"scId","type":"bytes16"},{"indexed":false,"internalType":"bytes32","name":"target","type":"bytes32"},{"indexed":false,"internalType":"bytes","name":"payload","type":"bytes"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"UntrustedContractUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"PoolId","name":"poolId","type":"uint64"},{"indexed":true,"internalType":"ShareClassId","name":"scId","type":"bytes16"},{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"D18","name":"price","type":"uint128"},{"indexed":false,"internalType":"uint64","name":"computedAt","type":"uint64"}],"name":"UpdateAssetPrice","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"PoolId","name":"poolId","type":"uint64"},{"indexed":true,"internalType":"ShareClassId","name":"scId","type":"bytes16"},{"indexed":true,"internalType":"address","name":"asset","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"},{"indexed":false,"internalType":"uint64","name":"maxPriceAge","type":"uint64"}],"name":"UpdateMaxAssetPriceAge","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"PoolId","name":"poolId","type":"uint64"},{"indexed":true,"internalType":"ShareClassId","name":"scId","type":"bytes16"},{"indexed":false,"internalType":"uint64","name":"maxPriceAge","type":"uint64"}],"name":"UpdateMaxSharePriceAge","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"PoolId","name":"poolId","type":"uint64"},{"indexed":true,"internalType":"ShareClassId","name":"scId","type":"bytes16"},{"indexed":false,"internalType":"D18","name":"price","type":"uint128"},{"indexed":false,"internalType":"uint64","name":"computedAt","type":"uint64"}],"name":"UpdateSharePrice","type":"event"},{"inputs":[{"internalType":"PoolId","name":"poolId","type":"uint64"}],"name":"addPool","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"PoolId","name":"poolId","type":"uint64"},{"internalType":"ShareClassId","name":"scId","type":"bytes16"},{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"address","name":"hook","type":"address"}],"name":"addShareClass","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"assetToId","outputs":[{"internalType":"AssetId","name":"assetId","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"centrifugeId","type":"uint16"},{"internalType":"PoolId","name":"poolId","type":"uint64"},{"internalType":"ShareClassId","name":"scId","type":"bytes16"},{"internalType":"bytes32","name":"receiver","type":"bytes32"},{"internalType":"uint128","name":"amount","type":"uint128"},{"internalType":"uint128","name":"remoteExtraGasLimit","type":"uint128"}],"name":"crosschainTransferShares","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint16","name":"centrifugeId","type":"uint16"},{"internalType":"PoolId","name":"poolId","type":"uint64"},{"internalType":"ShareClassId","name":"scId","type":"bytes16"},{"internalType":"bytes32","name":"receiver","type":"bytes32"},{"internalType":"uint128","name":"amount","type":"uint128"},{"internalType":"uint128","name":"extraGasLimit","type":"uint128"},{"internalType":"uint128","name":"remoteExtraGasLimit","type":"uint128"},{"internalType":"address","name":"refund","type":"address"}],"name":"crosschainTransferShares","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"deny","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"PoolId","name":"poolId","type":"uint64"},{"internalType":"ShareClassId","name":"scId","type":"bytes16"},{"internalType":"bytes32","name":"receiver","type":"bytes32"},{"internalType":"uint128","name":"amount","type":"uint128"}],"name":"executeTransferShares","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":"gateway","outputs":[{"internalType":"contract IGateway","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"AssetId","name":"assetId","type":"uint128"}],"name":"idToAsset","outputs":[{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"PoolId","name":"poolId","type":"uint64"}],"name":"isPoolActive","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"PoolId","name":"poolId","type":"uint64"},{"internalType":"ShareClassId","name":"scId","type":"bytes16"},{"internalType":"contract IShareToken","name":"shareToken_","type":"address"}],"name":"linkToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"PoolId","name":"poolId","type":"uint64"},{"internalType":"ShareClassId","name":"scId","type":"bytes16"},{"internalType":"AssetId","name":"assetId","type":"uint128"}],"name":"markersPricePoolPerAsset","outputs":[{"internalType":"uint64","name":"computedAt","type":"uint64"},{"internalType":"uint64","name":"maxAge","type":"uint64"},{"internalType":"uint64","name":"validUntil","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"PoolId","name":"poolId","type":"uint64"},{"internalType":"ShareClassId","name":"scId","type":"bytes16"}],"name":"markersPricePoolPerShare","outputs":[{"internalType":"uint64","name":"computedAt","type":"uint64"},{"internalType":"uint64","name":"maxAge","type":"uint64"},{"internalType":"uint64","name":"validUntil","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"PoolId","name":"","type":"uint64"}],"name":"pool","outputs":[{"internalType":"uint64","name":"createdAt","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"poolEscrowFactory","outputs":[{"internalType":"contract IPoolEscrowFactory","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"PoolId","name":"poolId","type":"uint64"},{"internalType":"ShareClassId","name":"scId","type":"bytes16"},{"internalType":"AssetId","name":"assetId","type":"uint128"},{"internalType":"bool","name":"checkValidity","type":"bool"}],"name":"pricePoolPerAsset","outputs":[{"internalType":"D18","name":"price","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"PoolId","name":"poolId","type":"uint64"},{"internalType":"ShareClassId","name":"scId","type":"bytes16"},{"internalType":"bool","name":"checkValidity","type":"bool"}],"name":"pricePoolPerShare","outputs":[{"internalType":"D18","name":"price","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"PoolId","name":"poolId","type":"uint64"},{"internalType":"ShareClassId","name":"scId","type":"bytes16"},{"internalType":"AssetId","name":"assetId","type":"uint128"},{"internalType":"bool","name":"checkValidity","type":"bool"}],"name":"pricesPoolPer","outputs":[{"internalType":"D18","name":"pricePoolPerAsset_","type":"uint128"},{"internalType":"D18","name":"pricePoolPerShare_","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"recoverTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"recoverTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"centrifugeId","type":"uint16"},{"internalType":"address","name":"asset","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"address","name":"refund","type":"address"}],"name":"registerAsset","outputs":[{"internalType":"AssetId","name":"assetId","type":"uint128"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"rely","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"PoolId","name":"poolId","type":"uint64"},{"internalType":"ShareClassId","name":"scId","type":"bytes16"},{"internalType":"AssetId","name":"assetId","type":"uint128"},{"internalType":"bytes","name":"payload","type":"bytes"},{"internalType":"uint128","name":"extraGasLimit","type":"uint128"},{"internalType":"bool","name":"unpaid","type":"bool"},{"internalType":"address","name":"refund","type":"address"}],"name":"request","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"PoolId","name":"poolId","type":"uint64"},{"internalType":"ShareClassId","name":"scId","type":"bytes16"},{"internalType":"AssetId","name":"assetId","type":"uint128"},{"internalType":"bytes","name":"payload","type":"bytes"}],"name":"requestCallback","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"PoolId","name":"","type":"uint64"}],"name":"requestManager","outputs":[{"internalType":"contract IRequestManager","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"sender","outputs":[{"internalType":"contract ISpokeMessageSender","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"PoolId","name":"poolId","type":"uint64"},{"internalType":"ShareClassId","name":"scId","type":"bytes16"},{"internalType":"AssetId","name":"assetId","type":"uint128"},{"internalType":"uint64","name":"maxPriceAge","type":"uint64"}],"name":"setMaxAssetPriceAge","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"PoolId","name":"poolId","type":"uint64"},{"internalType":"ShareClassId","name":"scId","type":"bytes16"},{"internalType":"uint64","name":"maxPriceAge","type":"uint64"}],"name":"setMaxSharePriceAge","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"PoolId","name":"poolId","type":"uint64"},{"internalType":"contract IRequestManager","name":"manager","type":"address"}],"name":"setRequestManager","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"PoolId","name":"poolId","type":"uint64"},{"internalType":"ShareClassId","name":"scId","type":"bytes16"},{"internalType":"address","name":"asset","type":"address"},{"internalType":"address","name":"vault","type":"address"}],"name":"setShareTokenVault","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"PoolId","name":"","type":"uint64"},{"internalType":"ShareClassId","name":"","type":"bytes16"}],"name":"shareClass","outputs":[{"internalType":"contract IShareToken","name":"shareToken","type":"address"},{"components":[{"internalType":"D18","name":"price","type":"uint128"},{"internalType":"uint64","name":"computedAt","type":"uint64"},{"internalType":"uint64","name":"maxAge","type":"uint64"}],"internalType":"struct Price","name":"pricePoolPerShare","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"PoolId","name":"poolId","type":"uint64"},{"internalType":"ShareClassId","name":"scId","type":"bytes16"}],"name":"shareToken","outputs":[{"internalType":"contract IShareToken","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"shareToken_","type":"address"}],"name":"shareTokenDetails","outputs":[{"internalType":"PoolId","name":"poolId","type":"uint64"},{"internalType":"ShareClassId","name":"scId","type":"bytes16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokenFactory","outputs":[{"internalType":"contract ITokenFactory","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"PoolId","name":"poolId","type":"uint64"},{"internalType":"ShareClassId","name":"scId","type":"bytes16"},{"internalType":"bytes32","name":"target","type":"bytes32"},{"internalType":"bytes","name":"payload","type":"bytes"},{"internalType":"uint128","name":"extraGasLimit","type":"uint128"},{"internalType":"address","name":"refund","type":"address"}],"name":"updateContract","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"PoolId","name":"poolId","type":"uint64"},{"internalType":"ShareClassId","name":"scId","type":"bytes16"},{"internalType":"AssetId","name":"assetId","type":"uint128"},{"internalType":"D18","name":"price","type":"uint128"},{"internalType":"uint64","name":"computedAt","type":"uint64"}],"name":"updatePricePoolPerAsset","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"PoolId","name":"poolId","type":"uint64"},{"internalType":"ShareClassId","name":"scId","type":"bytes16"},{"internalType":"D18","name":"price","type":"uint128"},{"internalType":"uint64","name":"computedAt","type":"uint64"}],"name":"updatePricePoolPerShare","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"PoolId","name":"poolId","type":"uint64"},{"internalType":"ShareClassId","name":"scId","type":"bytes16"},{"internalType":"bytes","name":"update","type":"bytes"}],"name":"updateRestriction","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"PoolId","name":"poolId","type":"uint64"},{"internalType":"ShareClassId","name":"scId","type":"bytes16"},{"internalType":"address","name":"hook","type":"address"}],"name":"updateShareHook","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"PoolId","name":"poolId","type":"uint64"},{"internalType":"ShareClassId","name":"scId","type":"bytes16"},{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"symbol","type":"string"}],"name":"updateShareMetadata","outputs":[],"stateMutability":"nonpayable","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":"000000000000000000000000ce1616505f93215751fbb41efac618b631997c38000000000000000000000000b3c086db30c1be6e40d8775607c3662ab160bda5"}