{"file_path":"src/core/messaging/MessageDispatcher.sol","creation_status":"success","source_code":"// SPDX-License-Identifier: BUSL-1.1\npragma solidity 0.8.28;\n\nimport {IGateway} from \"./interfaces/IGateway.sol\";\nimport {IMultiAdapter} from \"./interfaces/IMultiAdapter.sol\";\nimport {IScheduleAuth} from \"./interfaces/IScheduleAuth.sol\";\nimport {ITokenRecoverer} from \"./interfaces/ITokenRecoverer.sol\";\nimport {IMessageDispatcher} from \"./interfaces/IMessageDispatcher.sol\";\nimport {MessageLib, VaultUpdateKind} from \"./libraries/MessageLib.sol\";\nimport {ISpokeMessageSender, IHubMessageSender, IScheduleAuthMessageSender} from \"./interfaces/IGatewaySenders.sol\";\nimport {\n    ISpokeGatewayHandler,\n    IBalanceSheetGatewayHandler,\n    IHubGatewayHandler,\n    IContractUpdateGatewayHandler,\n    IVaultRegistryGatewayHandler\n} from \"./interfaces/IGatewayHandlers.sol\";\n\nimport {Auth} from \"../../misc/Auth.sol\";\nimport {D18} from \"../../misc/types/D18.sol\";\nimport {CastLib} from \"../../misc/libraries/CastLib.sol\";\nimport {MathLib} from \"../../misc/libraries/MathLib.sol\";\nimport {BytesLib} from \"../../misc/libraries/BytesLib.sol\";\nimport {IRecoverable} from \"../../misc/interfaces/IRecoverable.sol\";\n\nimport {PoolId} from \"../types/PoolId.sol\";\nimport {AssetId} from \"../types/AssetId.sol\";\nimport {ShareClassId} from \"../types/ShareClassId.sol\";\nimport {IRequestManager} from \"../interfaces/IRequestManager.sol\";\n\n/// @title  MessageDispatcher\n/// @notice This contract serializes and dispatches outgoing cross-chain messages, handling both local and\n///         remote destinations by either directly invoking local handlers or routing through the gateway.\ncontract MessageDispatcher is Auth, IMessageDispatcher {\n    using CastLib for *;\n    using MessageLib for *;\n    using BytesLib for bytes;\n    using MathLib for uint256;\n\n    PoolId internal constant GLOBAL_POOL = PoolId.wrap(0);\n    uint16 public immutable localCentrifugeId;\n\n    IGateway public gateway;\n    IMultiAdapter public multiAdapter;\n    ISpokeGatewayHandler public spoke;\n    IScheduleAuth public immutable scheduleAuth;\n    IHubGatewayHandler public hubHandler;\n    ITokenRecoverer public tokenRecoverer;\n    IBalanceSheetGatewayHandler public balanceSheet;\n    IVaultRegistryGatewayHandler public vaultRegistry;\n    IContractUpdateGatewayHandler public contractUpdater;\n\n    constructor(uint16 localCentrifugeId_, IScheduleAuth scheduleAuth_, IGateway gateway_, address deployer)\n        Auth(deployer)\n    {\n        localCentrifugeId = localCentrifugeId_;\n        scheduleAuth = scheduleAuth_;\n        gateway = gateway_;\n    }\n\n    //----------------------------------------------------------------------------------------------\n    // Administration\n    //----------------------------------------------------------------------------------------------\n\n    /// @inheritdoc IMessageDispatcher\n    function file(bytes32 what, address data) external auth {\n        if (what == \"hubHandler\") hubHandler = IHubGatewayHandler(data);\n        else if (what == \"spoke\") spoke = ISpokeGatewayHandler(data);\n        else if (what == \"gateway\") gateway = IGateway(data);\n        else if (what == \"balanceSheet\") balanceSheet = IBalanceSheetGatewayHandler(data);\n        else if (what == \"vaultRegistry\") vaultRegistry = IVaultRegistryGatewayHandler(data);\n        else if (what == \"contractUpdater\") contractUpdater = IContractUpdateGatewayHandler(data);\n        else if (what == \"tokenRecoverer\") tokenRecoverer = ITokenRecoverer(data);\n        else revert FileUnrecognizedParam();\n\n        emit File(what, data);\n    }\n\n    //----------------------------------------------------------------------------------------------\n    // Outgoing\n    //----------------------------------------------------------------------------------------------\n\n    /// @inheritdoc IHubMessageSender\n    function sendNotifyPool(uint16 centrifugeId, PoolId poolId, address refund) external payable auth {\n        if (centrifugeId == localCentrifugeId) {\n            spoke.addPool(poolId);\n            _refund(refund);\n        } else {\n            _send(centrifugeId, MessageLib.NotifyPool({poolId: poolId.raw()}).serialize(), false, refund);\n        }\n    }\n\n    /// @inheritdoc IHubMessageSender\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 auth {\n        if (centrifugeId == localCentrifugeId) {\n            spoke.addShareClass(poolId, scId, name, symbol, decimals, salt, hook.toAddress());\n            _refund(refund);\n        } else {\n            _send(\n                centrifugeId,\n                MessageLib.NotifyShareClass({\n                        poolId: poolId.raw(),\n                        scId: scId.raw(),\n                        name: name,\n                        symbol: symbol.toBytes32(),\n                        decimals: decimals,\n                        salt: salt,\n                        hook: hook\n                    }).serialize(),\n                false,\n                refund\n            );\n        }\n    }\n\n    /// @inheritdoc IHubMessageSender\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 auth {\n        if (centrifugeId == localCentrifugeId) {\n            spoke.updateShareMetadata(poolId, scId, name, symbol);\n            _refund(refund);\n        } else {\n            _send(\n                centrifugeId,\n                MessageLib.NotifyShareMetadata({\n                        poolId: poolId.raw(), scId: scId.raw(), name: name, symbol: symbol.toBytes32()\n                    }).serialize(),\n                false,\n                refund\n            );\n        }\n    }\n\n    /// @inheritdoc IHubMessageSender\n    function sendUpdateShareHook(uint16 centrifugeId, PoolId poolId, ShareClassId scId, bytes32 hook, address refund)\n        external\n        payable\n        auth\n    {\n        if (centrifugeId == localCentrifugeId) {\n            spoke.updateShareHook(poolId, scId, hook.toAddress());\n            _refund(refund);\n        } else {\n            _send(\n                centrifugeId,\n                MessageLib.UpdateShareHook({poolId: poolId.raw(), scId: scId.raw(), hook: hook}).serialize(),\n                false,\n                refund\n            );\n        }\n    }\n\n    /// @inheritdoc IHubMessageSender\n    function sendNotifyPricePoolPerShare(\n        uint16 chainId,\n        PoolId poolId,\n        ShareClassId scId,\n        D18 pricePoolPerShare,\n        uint64 computedAt,\n        address refund\n    ) external payable auth {\n        if (chainId == localCentrifugeId) {\n            spoke.updatePricePoolPerShare(poolId, scId, pricePoolPerShare, computedAt);\n            _refund(refund);\n        } else {\n            _send(\n                chainId,\n                MessageLib.NotifyPricePoolPerShare({\n                        poolId: poolId.raw(), scId: scId.raw(), price: pricePoolPerShare.raw(), timestamp: computedAt\n                    }).serialize(),\n                false,\n                refund\n            );\n        }\n    }\n\n    /// @inheritdoc IHubMessageSender\n    function sendNotifyPricePoolPerAsset(\n        PoolId poolId,\n        ShareClassId scId,\n        AssetId assetId,\n        D18 pricePoolPerAsset,\n        address refund\n    ) external payable auth {\n        uint64 timestamp = block.timestamp.toUint64();\n        if (assetId.centrifugeId() == localCentrifugeId) {\n            spoke.updatePricePoolPerAsset(poolId, scId, assetId, pricePoolPerAsset, timestamp);\n            _refund(refund);\n        } else {\n            _send(\n                assetId.centrifugeId(),\n                MessageLib.NotifyPricePoolPerAsset({\n                        poolId: poolId.raw(),\n                        scId: scId.raw(),\n                        assetId: assetId.raw(),\n                        price: pricePoolPerAsset.raw(),\n                        timestamp: timestamp\n                    }).serialize(),\n                false,\n                refund\n            );\n        }\n    }\n\n    /// @inheritdoc IHubMessageSender\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 auth {\n        if (centrifugeId == localCentrifugeId) {\n            spoke.updateRestriction(poolId, scId, payload);\n            _refund(refund);\n        } else {\n            _send(\n                centrifugeId,\n                MessageLib.UpdateRestriction({\n                        poolId: poolId.raw(), scId: scId.raw(), extraGasLimit: extraGasLimit, payload: payload\n                    }).serialize(),\n                false,\n                refund\n            );\n        }\n    }\n\n    /// @inheritdoc IHubMessageSender\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 auth {\n        if (centrifugeId == localCentrifugeId) {\n            contractUpdater.trustedCall(poolId, scId, target.toAddress(), payload);\n            _refund(refund);\n        } else {\n            _send(\n                centrifugeId,\n                MessageLib.TrustedContractUpdate({\n                        poolId: poolId.raw(),\n                        scId: scId.raw(),\n                        target: target,\n                        extraGasLimit: extraGasLimit,\n                        payload: payload\n                    }).serialize(),\n                false,\n                refund\n            );\n        }\n    }\n\n    /// @inheritdoc IHubMessageSender\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 auth {\n        if (assetId.centrifugeId() == localCentrifugeId) {\n            vaultRegistry.updateVault(poolId, scId, assetId, vaultOrFactory.toAddress(), kind);\n            _refund(refund);\n        } else {\n            _send(\n                assetId.centrifugeId(),\n                MessageLib.UpdateVault({\n                        poolId: poolId.raw(),\n                        scId: scId.raw(),\n                        assetId: assetId.raw(),\n                        vaultOrFactory: vaultOrFactory,\n                        kind: uint8(kind),\n                        extraGasLimit: extraGasLimit\n                    }).serialize(),\n                false,\n                refund\n            );\n        }\n    }\n\n    /// @inheritdoc IHubMessageSender\n    function sendSetRequestManager(uint16 centrifugeId, PoolId poolId, bytes32 manager, address refund)\n        external\n        payable\n        auth\n    {\n        if (centrifugeId == localCentrifugeId) {\n            spoke.setRequestManager(poolId, IRequestManager(manager.toAddress()));\n            _refund(refund);\n        } else {\n            _send(\n                centrifugeId,\n                MessageLib.SetRequestManager({poolId: poolId.raw(), manager: manager}).serialize(),\n                false,\n                refund\n            );\n        }\n    }\n\n    /// @inheritdoc IHubMessageSender\n    function sendUpdateBalanceSheetManager(\n        uint16 centrifugeId,\n        PoolId poolId,\n        bytes32 who,\n        bool canManage,\n        address refund\n    ) external payable auth {\n        if (centrifugeId == localCentrifugeId) {\n            balanceSheet.updateManager(poolId, who.toAddress(), canManage);\n            _refund(refund);\n        } else {\n            _send(\n                centrifugeId,\n                MessageLib.UpdateBalanceSheetManager({poolId: poolId.raw(), who: who, canManage: canManage})\n                    .serialize(),\n                false,\n                refund\n            );\n        }\n    }\n\n    /// @inheritdoc IHubMessageSender\n    function sendSetMaxAssetPriceAge(\n        PoolId poolId,\n        ShareClassId scId,\n        AssetId assetId,\n        uint64 maxPriceAge,\n        address refund\n    ) external payable auth {\n        if (assetId.centrifugeId() == localCentrifugeId) {\n            spoke.setMaxAssetPriceAge(poolId, scId, assetId, maxPriceAge);\n            _refund(refund);\n        } else {\n            _send(\n                assetId.centrifugeId(),\n                MessageLib.SetMaxAssetPriceAge({\n                        poolId: poolId.raw(), scId: scId.raw(), assetId: assetId.raw(), maxPriceAge: maxPriceAge\n                    }).serialize(),\n                false,\n                refund\n            );\n        }\n    }\n\n    /// @inheritdoc IHubMessageSender\n    function sendSetMaxSharePriceAge(\n        uint16 centrifugeId,\n        PoolId poolId,\n        ShareClassId scId,\n        uint64 maxPriceAge,\n        address refund\n    ) external payable auth {\n        if (centrifugeId == localCentrifugeId) {\n            spoke.setMaxSharePriceAge(poolId, scId, maxPriceAge);\n            _refund(refund);\n        } else {\n            _send(\n                centrifugeId,\n                MessageLib.SetMaxSharePriceAge({poolId: poolId.raw(), scId: scId.raw(), maxPriceAge: maxPriceAge})\n                    .serialize(),\n                false,\n                refund\n            );\n        }\n    }\n\n    /// @inheritdoc IScheduleAuthMessageSender\n    function sendScheduleUpgrade(uint16 centrifugeId, bytes32 target, address refund) external payable auth {\n        if (centrifugeId == localCentrifugeId) {\n            scheduleAuth.scheduleRely(target.toAddress());\n            _refund(refund);\n        } else {\n            _send(centrifugeId, MessageLib.ScheduleUpgrade({target: target}).serialize(), false, refund);\n        }\n    }\n\n    /// @inheritdoc IScheduleAuthMessageSender\n    function sendCancelUpgrade(uint16 centrifugeId, bytes32 target, address refund) external payable auth {\n        if (centrifugeId == localCentrifugeId) {\n            scheduleAuth.cancelRely(target.toAddress());\n            _refund(refund);\n        } else {\n            _send(centrifugeId, MessageLib.CancelUpgrade({target: target}).serialize(), false, refund);\n        }\n    }\n\n    /// @inheritdoc IScheduleAuthMessageSender\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 auth {\n        if (centrifugeId == localCentrifugeId) {\n            tokenRecoverer.recoverTokens(\n                IRecoverable(target.toAddress()), token.toAddress(), tokenId, to.toAddress(), amount\n            );\n            _refund(refund);\n        } else {\n            _send(\n                centrifugeId,\n                MessageLib.RecoverTokens({target: target, token: token, tokenId: tokenId, to: to, amount: amount})\n                    .serialize(),\n                false,\n                refund\n            );\n        }\n    }\n\n    /// @inheritdoc ISpokeMessageSender\n    function sendInitiateTransferShares(\n        uint16 targetCentrifugeId,\n        PoolId poolId,\n        ShareClassId scId,\n        bytes32 receiver,\n        uint128 amount,\n        uint128 extraGasLimit,\n        uint128 remoteExtraGasLimit,\n        address refund\n    ) external payable auth {\n        if (poolId.centrifugeId() == localCentrifugeId) {\n            hubHandler.initiateTransferShares{value: msg.value}(\n                localCentrifugeId, targetCentrifugeId, poolId, scId, receiver, amount, remoteExtraGasLimit, refund\n            );\n        } else {\n            _send(\n                poolId.centrifugeId(),\n                MessageLib.InitiateTransferShares({\n                        centrifugeId: targetCentrifugeId,\n                        poolId: poolId.raw(),\n                        scId: scId.raw(),\n                        receiver: receiver,\n                        amount: amount,\n                        remoteExtraGasLimit: remoteExtraGasLimit,\n                        extraGasLimit: extraGasLimit\n                    }).serialize(),\n                false,\n                refund\n            );\n        }\n    }\n\n    /// @inheritdoc IHubMessageSender\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 auth {\n        if (targetCentrifugeId == localCentrifugeId) {\n            // Spoke chain X => Hub chain Y => Spoke chain Y\n            spoke.executeTransferShares(poolId, scId, receiver, amount);\n            _refund(refund);\n        } else {\n            _send(\n                targetCentrifugeId,\n                MessageLib.ExecuteTransferShares({\n                        poolId: poolId.raw(),\n                        scId: scId.raw(),\n                        receiver: receiver,\n                        amount: amount,\n                        extraGasLimit: extraGasLimit\n                    }).serialize(),\n                originCentrifugeId != localCentrifugeId,\n                refund\n            );\n        }\n    }\n\n    /// @inheritdoc ISpokeMessageSender\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 auth {\n        if (poolId.centrifugeId() == localCentrifugeId) {\n            hubHandler.updateHoldingAmount(\n                localCentrifugeId,\n                poolId,\n                scId,\n                assetId,\n                data.netAmount,\n                pricePoolPerAsset,\n                data.isIncrease,\n                data.isSnapshot,\n                data.nonce\n            );\n            _refund(refund);\n        } else {\n            _send(\n                poolId.centrifugeId(),\n                MessageLib.UpdateHoldingAmount({\n                        poolId: poolId.raw(),\n                        scId: scId.raw(),\n                        assetId: assetId.raw(),\n                        amount: data.netAmount,\n                        pricePoolPerAsset: pricePoolPerAsset.raw(),\n                        timestamp: uint64(block.timestamp),\n                        isIncrease: data.isIncrease,\n                        isSnapshot: data.isSnapshot,\n                        nonce: data.nonce,\n                        extraGasLimit: extraGasLimit\n                    }).serialize(),\n                false,\n                refund\n            );\n        }\n    }\n\n    /// @inheritdoc ISpokeMessageSender\n    function sendUpdateShares(\n        PoolId poolId,\n        ShareClassId scId,\n        UpdateData calldata data,\n        uint128 extraGasLimit,\n        address refund\n    ) external payable auth {\n        if (poolId.centrifugeId() == localCentrifugeId) {\n            hubHandler.updateShares(\n                localCentrifugeId, poolId, scId, data.netAmount, data.isIncrease, data.isSnapshot, data.nonce\n            );\n            _refund(refund);\n        } else {\n            _send(\n                poolId.centrifugeId(),\n                MessageLib.UpdateShares({\n                        poolId: poolId.raw(),\n                        scId: scId.raw(),\n                        shares: data.netAmount,\n                        timestamp: uint64(block.timestamp),\n                        isIssuance: data.isIncrease,\n                        isSnapshot: data.isSnapshot,\n                        nonce: data.nonce,\n                        extraGasLimit: extraGasLimit\n                    }).serialize(),\n                false,\n                refund\n            );\n        }\n    }\n\n    /// @inheritdoc ISpokeMessageSender\n    function sendRegisterAsset(uint16 centrifugeId, AssetId assetId, uint8 decimals, address refund)\n        external\n        payable\n        auth\n    {\n        if (centrifugeId == localCentrifugeId) {\n            hubHandler.registerAsset(assetId, decimals);\n            _refund(refund);\n        } else {\n            _send(\n                centrifugeId,\n                MessageLib.RegisterAsset({assetId: assetId.raw(), decimals: decimals}).serialize(),\n                false,\n                refund\n            );\n        }\n    }\n\n    /// @inheritdoc ISpokeMessageSender\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 auth {\n        if (poolId.centrifugeId() == localCentrifugeId) {\n            hubHandler.request(poolId, scId, assetId, payload);\n            _refund(refund);\n        } else {\n            _send(\n                poolId.centrifugeId(),\n                MessageLib.Request({\n                        poolId: poolId.raw(),\n                        scId: scId.raw(),\n                        assetId: assetId.raw(),\n                        extraGasLimit: extraGasLimit,\n                        payload: payload\n                    }).serialize(),\n                unpaidMode,\n                refund\n            );\n        }\n    }\n\n    /// @inheritdoc ISpokeMessageSender\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 auth {\n        uint16 hubCentrifugeId = poolId.centrifugeId();\n\n        if (hubCentrifugeId == localCentrifugeId) {\n            contractUpdater.untrustedCall(poolId, scId, target.toAddress(), payload, localCentrifugeId, sender);\n            _refund(refund);\n        } else {\n            _send(\n                hubCentrifugeId,\n                MessageLib.UntrustedContractUpdate({\n                        poolId: poolId.raw(),\n                        scId: scId.raw(),\n                        target: target,\n                        sender: sender,\n                        extraGasLimit: extraGasLimit,\n                        payload: payload\n                    }).serialize(),\n                false,\n                refund\n            );\n        }\n    }\n\n    /// @inheritdoc IHubMessageSender\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 auth {\n        if (assetId.centrifugeId() == localCentrifugeId) {\n            spoke.requestCallback(poolId, scId, assetId, payload);\n            _refund(refund);\n        } else {\n            _send(\n                assetId.centrifugeId(),\n                MessageLib.RequestCallback({\n                        poolId: poolId.raw(),\n                        scId: scId.raw(),\n                        assetId: assetId.raw(),\n                        extraGasLimit: extraGasLimit,\n                        payload: payload\n                    }).serialize(),\n                unpaidMode,\n                refund\n            );\n        }\n    }\n\n    /// @inheritdoc IHubMessageSender\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 auth {\n        if (centrifugeId == localCentrifugeId) {\n            revert CannotBeSentLocally();\n        } else {\n            _send(\n                centrifugeId,\n                MessageLib.SetPoolAdapters({\n                        poolId: poolId.raw(), threshold: threshold, recoveryIndex: recoveryIndex, adapterList: adapters\n                    }).serialize(),\n                false,\n                refund\n            );\n        }\n    }\n\n    function sendUpdateGatewayManager(uint16 centrifugeId, PoolId poolId, bytes32 who, bool canManage, address refund)\n        external\n        payable\n        auth\n    {\n        if (centrifugeId == localCentrifugeId) {\n            gateway.updateManager(poolId, who.toAddress(), canManage);\n            _refund(refund);\n        } else {\n            _send(\n                centrifugeId,\n                MessageLib.UpdateGatewayManager({poolId: poolId.raw(), who: who, canManage: canManage}).serialize(),\n                false,\n                refund\n            );\n        }\n    }\n\n    function _send(uint16 centrifugeId, bytes memory message, bool unpaidMode, address refund) internal {\n        gateway.send{value: msg.value}(centrifugeId, message, unpaidMode, refund);\n    }\n\n    function _refund(address refund) internal {\n        if (msg.value > 0) {\n            (bool success,) = payable(refund).call{value: msg.value}(\"\");\n            require(success, CannotRefund());\n        }\n    }\n}\n","deployed_bytecode":"0x6080604052600436106101ca575f3560e01c80630a14789a146101ce578063116191b6146102195780631906c4a4146102455780631e840e451461027857806322285cf61461028d578063229d6f96146102ac578063268808c6146102bf57806332b05d53146102de578063351a4dd2146102f15780633daa8497146103045780634285d94c1461032357806347bfbcc6146103365780634c4d5a741461035557806353b6642414610368578063573178b41461037b5780635ffb48621461038e578063606436a3146103a157806363900d62146103b457806365fae35e146103c75780636c5e906c146103e65780637161b3f0146103f95780637a626bb71461040c578063862a05ef1461041f5780638c06200e146104325780638c5a29b4146104455780638c8b1f8e146104585780639c52a7f11461046b578063a2f965d51461048a578063a578b9ec1461049d578063ab1632f4146104b0578063bb308cdc146104cf578063bf353dbb146104e2578063cdd7b38a1461051b578063cfc32cc71461053a578063d4e8be831461054d578063dbb6d9d01461056c578063eae1ecdf1461057f578063ed15d96014610592578063f34b1f04146105b1578063ff69f205146105c4575b5f5ffd5b3480156101d9575f5ffd5b506102017f000000000000000000000000000000000000000000000000000000000000000181565b60405161ffff90911681526020015b60405180910390f35b348015610224575f5ffd5b50600154610238906001600160a01b031681565b60405161021091906130c5565b348015610250575f5ffd5b506102387f0000000000000000000000007ed48c31f2fdc40d37407cbabf0870b2b688368f81565b61028b6102863660046131df565b6105d7565b005b348015610298575f5ffd5b50600654610238906001600160a01b031681565b61028b6102ba3660046132ad565b61070c565b3480156102ca575f5ffd5b50600554610238906001600160a01b031681565b61028b6102ec366004613314565b61096c565b61028b6102ff366004613356565b610a6c565b34801561030f575f5ffd5b50600454610238906001600160a01b031681565b61028b6103313660046133b2565b610b94565b348015610341575f5ffd5b50600354610238906001600160a01b031681565b61028b6103633660046134a4565b610c54565b61028b610376366004613502565b610d9d565b61028b610389366004613581565b61100c565b61028b61039c3660046135da565b611107565b61028b6103af36600461366a565b611205565b61028b6103c236600461370f565b6113a3565b3480156103d2575f5ffd5b5061028b6103e1366004613787565b611555565b61028b6103f43660046137a0565b6115c8565b61028b610407366004613824565b61177c565b61028b61041a366004613866565b611878565b61028b61042d3660046138dd565b6119a5565b61028b61044036600461392d565b611ab2565b61028b6104533660046139b2565b611bdb565b61028b6104663660046139ff565b611d50565b348015610476575f5ffd5b5061028b610485366004613787565b611e2d565b61028b610498366004613a47565b611e9f565b61028b6104ab366004613b0f565b611fe2565b3480156104bb575f5ffd5b50600254610238906001600160a01b031681565b61028b6104dd36600461366a565b612132565b3480156104ed575f5ffd5b5061050d6104fc366004613787565b5f6020819052908152604090205481565b604051908152602001610210565b348015610526575f5ffd5b50600754610238906001600160a01b031681565b61028b610548366004613b73565b612283565b348015610558575f5ffd5b5061028b610567366004613bf2565b6123ba565b61028b61057a366004613824565b6125b0565b61028b61058d366004613c1c565b61266a565b34801561059d575f5ffd5b50600854610238906001600160a01b031681565b61028b6105bf366004613c1c565b612737565b61028b6105d2366004613c4c565b6127e8565b335f908152602081905260409020546001146106065760405163ea8e4eb560e01b815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000161ffff168661ffff16036106a6576003546040516324c7bed560e21b81526001600160a01b039091169063931efb549061066b908890889088908890600401613cd6565b5f604051808303815f87803b158015610682575f5ffd5b505af1158015610694573d5f5f3e3d5ffd5b505050506106a1816128d7565b610704565b610704866106fd60405180608001604052806106c88a6001600160401b031690565b6001600160401b031681526001600160801b031989166020820152604081018890526060016106f687612951565b9052612961565b5f846129b0565b505050505050565b335f9081526020819052604090205460011461073b5760405163ea8e4eb560e01b815260040160405180910390fd5b61ffff7f0000000000000000000000000000000000000000000000000000000000000001811690603087901c1661ffff1603610885576004546001600160a01b031663778158cc7f000000000000000000000000000000000000000000000000000000000000000187876107b26020890189613d26565b6107c260408a0160208b01613d41565b6107d260608b0160408c01613d41565b6107e260808c0160608d01613d5a565b6040516001600160e01b031960e08a901b16815261ffff90971660048801526001600160401b0395861660248801526001600160801b031990941660448701526001600160801b03909216606486015215156084850152151560a48401521660c482015260e4015b5f604051808303815f87803b158015610861575f5ffd5b505af1158015610873573d5f5f3e3d5ffd5b50505050610880816128d7565b610965565b61096561ffff603087901c166106fd6040518061010001604052806108b08a6001600160401b031690565b6001600160401b031681526020016001600160801b031989166001600160801b03191681526020908101906108e790890189613d26565b6001600160801b03168152602001426001600160401b031681526020018760200160208101906109179190613d41565b1515815260200161092e6060890160408a01613d41565b151581526020016109456080890160608a01613d5a565b6001600160401b03168152602001866001600160801b0316815250612a11565b5050505050565b335f9081526020819052604090205460011461099b5760405163ea8e4eb560e01b815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000161ffff168361ffff1603610a3a57600354604051632b89610160e01b81526001600160401b03841660048201526001600160a01b0390911690632b896101906024015b5f604051808303815f87803b158015610a16575f5ffd5b505af1158015610a28573d5f5f3e3d5ffd5b50505050610a35816128d7565b505050565b610a35836106fd6040518060200160405280610a5c876001600160401b031690565b6001600160401b03169052612a4f565b335f90815260208190526040902054600114610a9b5760405163ea8e4eb560e01b815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000161ffff168461ffff1603610b56576003546001600160a01b0316634421169384610ae585612a67565b6040516001600160e01b031960e085901b1681526001600160401b0390921660048301526001600160a01b031660248201526044015b5f604051808303815f87803b158015610b32575f5ffd5b505af1158015610b44573d5f5f3e3d5ffd5b50505050610b51816128d7565b610b8e565b610b8e846106fd6040518060400160405280610b78886001600160401b031690565b6001600160401b03168152602001869052612a97565b50505050565b335f90815260208190526040902054600114610bc35760405163ea8e4eb560e01b815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000161ffff168661ffff1603610c0b576040516322bc1cf360e01b815260040160405180910390fd5b610704866106fd6040518060800160405280610c2d8a6001600160401b031690565b6001600160401b0316815260ff808916602083015287166040820152606001889052612ab4565b335f90815260208190526040902054600114610c835760405163ea8e4eb560e01b815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000161ffff168761ffff1603610d61576005546001600160a01b031663109037c0610ccc88612a67565b610cd588612a67565b87610cdf88612a67565b60405160e086901b6001600160e01b03191681526001600160a01b0394851660048201529284166024840152604483019190915290911660648201526084810185905260a4015b5f604051808303815f87803b158015610d3d575f5ffd5b505af1158015610d4f573d5f5f3e3d5ffd5b50505050610d5c816128d7565b610d94565b610d94876106fd6040518060a001604052808a815260200189815260200188815260200187815260200186815250612aee565b50505050505050565b335f90815260208190526040902054600114610dcc5760405163ea8e4eb560e01b815260040160405180910390fd5b61ffff7f0000000000000000000000000000000000000000000000000000000000000001811690603089901c1661ffff1603610ef6576004546001600160a01b0316630646affc7f0000000000000000000000000000000000000000000000000000000000000001898989610e4460208b018b613d26565b89610e5560408d0160208e01613d41565b610e6560608e0160408f01613d41565b8d6060016020810190610e789190613d5a565b6040516001600160e01b031960e08c901b16815261ffff90991660048a01526001600160401b0397881660248a01526001600160801b031990961660448901526001600160801b0394851660648901529284166084880152921660a486015290151560c4850152151560e48401521661010482015261012401610d26565b610d9461ffff603089901c166106fd604051806101400160405280610f218c6001600160401b031690565b6001600160401b031681526020016001600160801b03198b166001600160801b03191681526020016001600160801b038a166001600160801b03168152602090810190610f70908a018a613d26565b6001600160801b03168152602001610f8e886001600160801b031690565b6001600160801b03168152602001426001600160401b03168152602001886020016020810190610fbe9190613d41565b15158152602001610fd560608a0160408b01613d41565b15158152602001610fec60808a0160608b01613d5a565b6001600160401b03168152602001866001600160801b0316815250612b1f565b335f9081526020819052604090205460011461103b5760405163ea8e4eb560e01b815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000161ffff168561ffff16036110bb5760035460405163eece6c4360e01b81526001600160401b0380871660048301526001600160801b031986166024830152841660448201526001600160a01b039091169063eece6c439060640161084a565b610965856106fd60405180606001604052806110dd896001600160401b031690565b6001600160401b0390811682526001600160801b0319891660208301528716604090910152612b69565b335f908152602081905260409020546001146111365760405163ea8e4eb560e01b815260040160405180910390fd5b61ffff7f0000000000000000000000000000000000000000000000000000000000000001811690607085901c1661ffff16036111a257600354604051636a4873e160e11b81526001600160a01b039091169063d490e7c29061084a908890889088908890600401613d75565b61096561ffff607085901c166106fd60405180608001604052806111cc8a6001600160401b031690565b6001600160401b0390811682526001600160801b03198a1660208301526001600160801b03891660408301528716606090910152612b8e565b335f908152602081905260409020546001146112345760405163ea8e4eb560e01b815260040160405180910390fd5b61ffff7f0000000000000000000000000000000000000000000000000000000000000001811690607088901c1661ffff16036112dd576003546040516336c6cf3760e21b81526001600160a01b039091169063db1b3cdc906112a2908b908b908b908b908b90600401613ddb565b5f604051808303815f87803b1580156112b9575f5ffd5b505af11580156112cb573d5f5f3e3d5ffd5b505050506112d8816128d7565b611399565b61139961ffff607088901c166113926040518060a001604052806113078d6001600160401b031690565b6001600160401b031681526020016001600160801b03198c166001600160801b03191681526020016001600160801b038b166001600160801b03168152602001876001600160801b0316815260200189898080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152505050915250612bb9565b84846129b0565b5050505050505050565b335f908152602081905260409020546001146113d25760405163ea8e4eb560e01b815260040160405180910390fd5b61ffff603089901c8116907f00000000000000000000000000000000000000000000000000000000000000011681036114a2576008546001600160a01b03166324f500a08a8a6114218b612a67565b8a8a7f00000000000000000000000000000000000000000000000000000000000000018b6040518863ffffffff1660e01b81526004016114679796959493929190613e1e565b5f604051808303815f87803b15801561147e575f5ffd5b505af1158015611490573d5f5f3e3d5ffd5b5050505061149d826128d7565b61154a565b61154a816115436040518060c001604052806114c48e6001600160401b031690565b6001600160401b031681526020016001600160801b03198d166001600160801b03191681526020018b8152602001888152602001876001600160801b031681526020018a8a8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152505050915250612bf9565b5f856129b0565b505050505050505050565b335f908152602081905260409020546001146115845760405163ea8e4eb560e01b815260040160405180910390fd5b6001600160a01b0381165f8181526020819052604080822060019055517fdd0e34038ac38b2a1ce960229778ac48a8719bc900b6c4f8d0475c6e8b385a609190a250565b335f908152602081905260409020546001146115f75760405163ea8e4eb560e01b815260040160405180910390fd5b61ffff7f0000000000000000000000000000000000000000000000000000000000000001811690603089901c1661ffff16036117015760048054604051630fb3791160e01b815261ffff7f0000000000000000000000000000000000000000000000000000000000000001811693820193909352918a1660248301526001600160401b03891660448301526001600160801b031988166064830152608482018790526001600160801b0380871660a4840152841660c48301526001600160a01b0383811660e48401521690630fb37911903490610104015f604051808303818588803b1580156116e5575f5ffd5b505af11580156116f7573d5f5f3e3d5ffd5b5050505050611399565b61139961ffff603089901c166106fd6040518060e0016040528061172b8c6001600160401b031690565b6001600160401b031681526001600160801b03198b16602082015261ffff8d166040820152606081018a90526001600160801b03898116608083015287811660a0830152881660c090910152612c3f565b335f908152602081905260409020546001146117ab5760405163ea8e4eb560e01b815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000161ffff168561ffff1603611837576001546001600160a01b031663a6fd509b856117f586612a67565b6040516001600160e01b031960e085901b1681526001600160401b0390921660048301526001600160a01b03166024820152841515604482015260640161084a565b610965856106fd6040518060600160405280611859896001600160401b031690565b6001600160401b03168152602001878152602001861515815250612c78565b335f908152602081905260409020546001146118a75760405163ea8e4eb560e01b815260040160405180910390fd5b61ffff7f0000000000000000000000000000000000000000000000000000000000000001811690607087901c1661ffff160361191b576007546001600160a01b031663b3cfb8178888886118fa89612a67565b886040518663ffffffff1660e01b8152600401610d26959493929190613e8f565b610d9461ffff607087901c166106fd6040518060c001604052806119458c6001600160401b031690565b6001600160401b031681526001600160801b03198b1660208201526001600160801b038a1660408201526060810189905260800187600281111561198b5761198b613e7b565b60ff168152602001866001600160801b0316815250612c9d565b335f908152602081905260409020546001146119d45760405163ea8e4eb560e01b815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000161ffff168561ffff1603611a6a576003546001600160a01b031663fb59077a8585611a1f86612a67565b6040516001600160e01b031960e086901b1681526001600160401b0390931660048401526001600160801b031990911660248301526001600160a01b0316604482015260640161084a565b610965856106fd6040518060600160405280611a8c896001600160401b031690565b6001600160401b031681526001600160801b031988166020820152604001869052612cd4565b335f90815260208190526040902054600114611ae15760405163ea8e4eb560e01b815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000161ffff168761ffff1603611b4657600354604051630f8dad5d60e11b81526001600160a01b0390911690631f1b5aba90610d26908990899089908990600401613eed565b610d94876106fd6040518060800160405280611b688b6001600160401b031690565b6001600160401b031681526020016001600160801b03198a166001600160801b0319168152602001866001600160801b0316815260200188888080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152505050915250612cf9565b335f90815260208190526040902054600114611c0a5760405163ea8e4eb560e01b815260040160405180910390fd5b5f611c1442612d33565b905061ffff7f0000000000000000000000000000000000000000000000000000000000000001811690607086901c1661ffff1603611ce557600354604051633a4ba8bf60e01b81526001600160401b0380891660048301526001600160801b0319881660248301526001600160801b03808816604484015286166064830152831660848201526001600160a01b0390911690633a4ba8bf9060a4015f604051808303815f87803b158015611cc6575f5ffd5b505af1158015611cd8573d5f5f3e3d5ffd5b505050506106a1826128d7565b61070461ffff607086901c166115436040518060a00160405280611d0f8b6001600160401b031690565b6001600160401b0390811682526001600160801b03198b1660208301526001600160801b038a81166040840152891660608301528616608090910152612d60565b335f90815260208190526040902054600114611d7f5760405163ea8e4eb560e01b815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000161ffff168461ffff1603611df15760048054604051633207adab60e01b81526001600160801b0386169281019290925260ff841660248301526001600160a01b031690633207adab90604401610b1b565b610b8e846106fd6040518060400160405280611e13886001600160801b031690565b6001600160801b031681526020018660ff16815250612d91565b335f90815260208190526040902054600114611e5c5760405163ea8e4eb560e01b815260040160405180910390fd5b6001600160a01b0381165f81815260208190526040808220829055517f184450df2e323acec0ed3b5c7531b81f9b4cdef7914dfd4c0a4317416bb5251b9190a250565b335f90815260208190526040902054600114611ece5760405163ea8e4eb560e01b815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000161ffff168961ffff1603611f75576003546001600160a01b0316636ea6e0a1898989898989611f1d8a612a67565b6040518863ffffffff1660e01b8152600401611f3f9796959493929190613f2b565b5f604051808303815f87803b158015611f56575f5ffd5b505af1158015611f68573d5f5f3e3d5ffd5b5050505061149d816128d7565b61154a896106fd6040518060e00160405280611f978d6001600160401b031690565b6001600160401b031681526001600160801b03198c166020820152604081018b9052606001611fc58a612951565b81526020018860ff16815260200187815260200186815250612dae565b335f908152602081905260409020546001146120115760405163ea8e4eb560e01b815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000161ffff168761ffff160361209f5760035460405163bccbfa8960e01b81526001600160401b03881660048201526001600160801b031987166024820152604481018690526001600160801b03851660648201526001600160a01b039091169063bccbfa89906084016112a2565b611399876121006040518060a001604052806120c18b6001600160401b031690565b6001600160401b031681526001600160801b03198a166020820152604081018990526001600160801b0388811660608301528716608090910152612df9565b7f000000000000000000000000000000000000000000000000000000000000000161ffff168b61ffff161415846129b0565b335f908152602081905260409020546001146121615760405163ea8e4eb560e01b815260040160405180910390fd5b61ffff7f000000000000000000000000000000000000000000000000000000000000000181169060308a901c1661ffff16036121ce5760048054604051632f6c33bf60e01b81526001600160a01b0390911691632f6c33bf916112a2918c918c918c918c918c9101613ddb565b61139961ffff60308a901c166113926040518060a001604052806121f88d6001600160401b031690565b6001600160401b031681526020016001600160801b03198c166001600160801b03191681526020016001600160801b038b166001600160801b03168152602001876001600160801b0316815260200189898080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152505050915250612e2a565b335f908152602081905260409020546001146122b25760405163ea8e4eb560e01b815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000161ffff168861ffff160361231f576008546001600160a01b03166312a5d10d88886122fd89612a67565b88886040518663ffffffff1660e01b81526004016112a2959493929190613f9c565b611399886106fd6040518060a001604052806123418c6001600160401b031690565b6001600160401b031681526020016001600160801b03198b166001600160801b0319168152602001898152602001866001600160801b0316815260200188888080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152505050915250612e4f565b335f908152602081905260409020546001146123e95760405163ea8e4eb560e01b815260040160405180910390fd5b8169343ab12430b7323632b960b11b0361241d57600480546001600160a01b0319166001600160a01b038316179055612574565b816473706f6b6560d81b0361244c57600380546001600160a01b0319166001600160a01b038316179055612574565b81666761746577617960c81b0361247d57600180546001600160a01b0319166001600160a01b038316179055612574565b816b18985b185b98d954da19595d60a21b036124b357600680546001600160a01b0319166001600160a01b038316179055612574565b816c7661756c74526567697374727960981b036124ea57600780546001600160a01b0319166001600160a01b038316179055612574565b816e31b7b73a3930b1ba2ab83230ba32b960891b0361252357600880546001600160a01b0319166001600160a01b038316179055612574565b816d3a37b5b2b72932b1b7bb32b932b960911b0361255b57600580546001600160a01b0319166001600160a01b038316179055612574565b604051633db0d5b960e01b815260040160405180910390fd5b817f8fef588b5fc1afbf5b2f06c1a435d513f208da2e6704c3d8f0e0ec91167066ba826040516125a491906130c5565b60405180910390a25050565b335f908152602081905260409020546001146125df5760405163ea8e4eb560e01b815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000161ffff168561ffff1603612629576006546001600160a01b031663a6fd509b856117f586612a67565b610965856106fd604051806060016040528061264b896001600160401b031690565b6001600160401b03168152602001878152602001861515815250612e8f565b335f908152602081905260409020546001146126995760405163ea8e4eb560e01b815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000161ffff168361ffff160361271c577f0000000000000000000000007ed48c31f2fdc40d37407cbabf0870b2b688368f6001600160a01b0316633b68746161270084612a67565b6040518263ffffffff1660e01b81526004016109ff91906130c5565b610a35836106fd604051806020016040528086815250612eb4565b335f908152602081905260409020546001146127665760405163ea8e4eb560e01b815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000161ffff168361ffff16036127cd577f0000000000000000000000007ed48c31f2fdc40d37407cbabf0870b2b688368f6001600160a01b03166311fd3baa61270084612a67565b610a35836106fd604051806020016040528086815250612ecc565b335f908152602081905260409020546001146128175760405163ea8e4eb560e01b815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000161ffff168661ffff160361287c57600354604051634869ac6960e01b81526001600160a01b0390911690634869ac699061066b908890889088908890600401613d75565b610704866106fd604051806080016040528061289e8a6001600160401b031690565b6001600160401b0390811682526001600160801b03198a1660208301526001600160801b03891660408301528716606090910152612ee4565b341561294e575f816001600160a01b0316346040515f6040518083038185875af1925050503d805f8114612926576040519150601f19603f3d011682016040523d82523d5f602084013e61292b565b606091505b505090508061294c576040516202d94960ed1b815260040160405180910390fd5b505b50565b5f61295b82613fdf565b92915050565b805160208201516040830151606092600a929091612981905f6080612f0f565b856060015160405160200161299a959493929190614041565b6040516020818303038152906040529050919050565b6001546040516354e6733360e11b81526001600160a01b039091169063a9cce6669034906129e890889088908890889060040161408d565b5f604051808303818588803b1580156129ff575f5ffd5b505af115801561154a573d5f5f3e3d5ffd5b8051602080830151604080850151606086810151608088015160a089015160c08a015160e08b01519651949961299a996013999198919796016140db565b805160405160609161299a9160069190602001614160565b5f6001600160601b03821615612a905760405163e8bd165960e01b815260040160405180910390fd5b5060601c90565b805160208083015160405160609361299a93601893919201614187565b60606005825f015183602001518460400151612ad4866060015151612fdf565b866060015160405160200161299a969594939291906141b3565b60606003825f0151836020015184604001518560600151866080015160405160200161299a96959493929190614240565b8051602080830151604080850151606086810151608088015160a089015160c08a015160e08b01516101008c01516101208d01519851969b61299a9b60129b919a91999801614274565b60606015825f01518360200151846040015160405160200161299a9493929190614314565b60606014825f015183602001518460400151856060015160405160200161299a959493929190614355565b60606017825f0151836020015184604001518560600151612bde876080015151612fdf565b876080015160405160200161299a97969594939291906143a6565b6060601a825f01518360200151846040015185606001518660800151612c238860a0015151612fdf565b8860a0015160405160200161299a989796959493929190614419565b8051602080830151604080850151606086810151608088015160a089015160c08a01519551939861299a98600c98919791969501614491565b60606011825f01518360200151846040015160405160200161299a9493929190614503565b6060600f825f015183602001518460400151856060015186608001518760a0015160405160200161299a979695949392919061453c565b6060600b825f01518360200151846040015160405160200161299a94939291906145a2565b6060600e825f015183602001518460400151612d19866060015151612fdf565b866060015160405160200161299a969594939291906145e0565b5f6001600160401b03821115612d5c5760405163397df9e960e21b815260040160405180910390fd5b5090565b60606009825f0151836020015184604001518560600151866080015160405160200161299a96959493929190614648565b805160208083015160405160609361299a936004939192016146a2565b8051602082015160408301516060926007929091612dce905f6080612f0f565b856060015186608001518760a001518860c0015160405160200161299a9897969594939291906146db565b6060600d825f0151836020015184604001518560600151866080015160405160200161299a96959493929190614746565b60606016825f0151836020015184604001518560600151612bde876080015151612fdf565b60606019825f0151836020015184604001518560600151612e74876080015151612fdf565b876080015160405160200161299a9796959493929190614799565b60606010825f01518360200151846040015160405160200161299a9493929190614503565b805160405160609161299a91600191906020016147fc565b805160405160609161299a91600291906020016147fc565b60606008825f015183602001518460400151856060015160405160200161299a959493929190614355565b60605f612f1c838561482a565b855110905080612f3957612f31858585613003565b915050612fd8565b5f612f518686878951612f4c919061483d565b613003565b90505f86518686612f62919061482a565b612f6c919061483d565b6001600160401b03811115612f8357612f8361311a565b6040519080825280601f01601f191660200182016040528015612fad576020820181803683370190505b5090508181604051602001612fc3929190614850565b60405160208183030381529060405293505050505b9392505050565b5f61ffff821115612d5c5760405163029ac84360e11b815260040160405180910390fd5b60608182601f011015613029576040516323d5783d60e11b815260040160405180910390fd5b613033828461482a565b8451101561305457604051633b99b53d60e01b815260040160405180910390fd5b6060821580156130725760405191505f8252602082016040526130bc565b6040519150601f8416801560200281840101858101878315602002848b0101015b818310156130ab578051835260209283019201613093565b5050858452601f01601f1916604052505b50949350505050565b6001600160a01b0391909116815260200190565b803561ffff811681146130ea575f5ffd5b919050565b6001600160401b038116811461294e575f5ffd5b80356001600160801b0319811681146130ea575f5ffd5b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f191681016001600160401b03811182821017156131565761315661311a565b604052919050565b5f82601f83011261316d575f5ffd5b81356001600160401b038111156131865761318661311a565b613199601f8201601f191660200161312e565b8181528460208386010111156131ad575f5ffd5b816020850160208301375f918101602001919091529392505050565b80356001600160a01b03811681146130ea575f5ffd5b5f5f5f5f5f5f60c087890312156131f4575f5ffd5b6131fd876130d9565b9550602087013561320d816130ef565b945061321b60408801613103565b935060608701356001600160401b03811115613235575f5ffd5b61324189828a0161315e565b93505060808701356001600160401b0381111561325c575f5ffd5b61326889828a0161315e565b92505061327760a088016131c9565b90509295509295509295565b5f60808284031215613293575f5ffd5b50919050565b6001600160801b038116811461294e575f5ffd5b5f5f5f5f5f61010086880312156132c2575f5ffd5b85356132cd816130ef565b94506132db60208701613103565b93506132ea8760408801613283565b925060c08601356132fa81613299565b915061330860e087016131c9565b90509295509295909350565b5f5f5f60608486031215613326575f5ffd5b61332f846130d9565b9250602084013561333f816130ef565b915061334d604085016131c9565b90509250925092565b5f5f5f5f60808587031215613369575f5ffd5b613372856130d9565b93506020850135613382816130ef565b925060408501359150613397606086016131c9565b905092959194509250565b803560ff811681146130ea575f5ffd5b5f5f5f5f5f5f60c087890312156133c7575f5ffd5b6133d0876130d9565b955060208701356133e0816130ef565b945060408701356001600160401b038111156133fa575f5ffd5b8701601f8101891361340a575f5ffd5b80356001600160401b038111156134235761342361311a565b8060051b6134336020820161312e565b9182526020818401810192908101908c84111561344e575f5ffd5b6020850194505b8385101561347457843580835260209586019590935090910190613455565b8098505050505050613488606088016133a2565b9250613496608088016133a2565b915061327760a088016131c9565b5f5f5f5f5f5f5f60e0888a0312156134ba575f5ffd5b6134c3886130d9565b96506020880135955060408801359450606088013593506080880135925060a088013591506134f460c089016131c9565b905092959891949750929550565b5f5f5f5f5f5f5f610140888a031215613519575f5ffd5b8735613524816130ef565b965061353260208901613103565b9550604088013561354281613299565b94506135518960608a01613283565b935060e088013561356181613299565b925061010088013561357281613299565b91506134f461012089016131c9565b5f5f5f5f5f60a08688031215613595575f5ffd5b61359e866130d9565b945060208601356135ae816130ef565b93506135bc60408701613103565b925060608601356135cc816130ef565b9150613308608087016131c9565b5f5f5f5f5f60a086880312156135ee575f5ffd5b85356135f9816130ef565b945061360760208701613103565b935060408601356135bc81613299565b5f5f83601f840112613627575f5ffd5b5081356001600160401b0381111561363d575f5ffd5b602083019150836020828501011115613654575f5ffd5b9250929050565b803580151581146130ea575f5ffd5b5f5f5f5f5f5f5f5f60e0898b031215613681575f5ffd5b883561368c816130ef565b975061369a60208a01613103565b965060408901356136aa81613299565b955060608901356001600160401b038111156136c4575f5ffd5b6136d08b828c01613617565b90965094505060808901356136e481613299565b92506136f260a08a0161365b565b915061370060c08a016131c9565b90509295985092959890939650565b5f5f5f5f5f5f5f5f60e0898b031215613726575f5ffd5b8835613731816130ef565b975061373f60208a01613103565b96506040890135955060608901356001600160401b03811115613760575f5ffd5b61376c8b828c01613617565b9096509450506080890135925060a08901356136f281613299565b5f60208284031215613797575f5ffd5b612fd8826131c9565b5f5f5f5f5f5f5f5f610100898b0312156137b8575f5ffd5b6137c1896130d9565b975060208901356137d1816130ef565b96506137df60408a01613103565b95506060890135945060808901356137f681613299565b935060a089013561380681613299565b925060c089013561381681613299565b915061370060e08a016131c9565b5f5f5f5f5f60a08688031215613838575f5ffd5b613841866130d9565b94506020860135613851816130ef565b9350604086013592506135cc6060870161365b565b5f5f5f5f5f5f5f60e0888a03121561387c575f5ffd5b8735613887816130ef565b965061389560208901613103565b955060408801356138a581613299565b9450606088013593506080880135600381106138bf575f5ffd5b925060a08801356138cf81613299565b91506134f460c089016131c9565b5f5f5f5f5f60a086880312156138f1575f5ffd5b6138fa866130d9565b9450602086013561390a816130ef565b935061391860408701613103565b925060608601359150613308608087016131c9565b5f5f5f5f5f5f5f60c0888a031215613943575f5ffd5b61394c886130d9565b9650602088013561395c816130ef565b955061396a60408901613103565b945060608801356001600160401b03811115613984575f5ffd5b6139908a828b01613617565b90955093505060808801356139a481613299565b91506134f460a089016131c9565b5f5f5f5f5f60a086880312156139c6575f5ffd5b85356139d1816130ef565b94506139df60208701613103565b935060408601356139ef81613299565b925060608601356135cc81613299565b5f5f5f5f60808587031215613a12575f5ffd5b613a1b856130d9565b93506020850135613a2b81613299565b9250613a39604086016133a2565b9150613397606086016131c9565b5f5f5f5f5f5f5f5f5f6101208a8c031215613a60575f5ffd5b613a698a6130d9565b985060208a0135613a79816130ef565b9750613a8760408b01613103565b965060608a01356001600160401b03811115613aa1575f5ffd5b613aad8c828d0161315e565b96505060808a01356001600160401b03811115613ac8575f5ffd5b613ad48c828d0161315e565b955050613ae360a08b016133a2565b935060c08a0135925060e08a01359150613b006101008b016131c9565b90509295985092959850929598565b5f5f5f5f5f5f5f5f610100898b031215613b27575f5ffd5b613b30896130d9565b9750613b3e60208a016130d9565b96506040890135613b4e816130ef565b9550613b5c60608a01613103565b94506080890135935060a089013561380681613299565b5f5f5f5f5f5f5f5f60e0898b031215613b8a575f5ffd5b613b93896130d9565b97506020890135613ba3816130ef565b9650613bb160408a01613103565b95506060890135945060808901356001600160401b03811115613bd2575f5ffd5b613bde8b828c01613617565b90955093505060a08901356136f281613299565b5f5f60408385031215613c03575f5ffd5b82359150613c13602084016131c9565b90509250929050565b5f5f5f60608486031215613c2e575f5ffd5b613c37846130d9565b92506020840135915061334d604085016131c9565b5f5f5f5f5f5f60c08789031215613c61575f5ffd5b613c6a876130d9565b95506020870135613c7a816130ef565b9450613c8860408801613103565b93506060870135613c9881613299565b92506080870135613496816130ef565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b6001600160401b03851681526001600160801b0319841660208201526080604082018190525f90613d0990830185613ca8565b8281036060840152613d1b8185613ca8565b979650505050505050565b5f60208284031215613d36575f5ffd5b8135612fd881613299565b5f60208284031215613d51575f5ffd5b612fd88261365b565b5f60208284031215613d6a575f5ffd5b8135612fd8816130ef565b6001600160401b0394851681526001600160801b03199390931660208401526001600160801b03919091166040830152909116606082015260800190565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b6001600160401b03861681526001600160801b0319851660208201526001600160801b03841660408201526080606082018190525f90613d1b9083018486613db3565b6001600160401b03881681526001600160801b0319871660208201526001600160a01b038616604082015260c0606082018190525f90613e619083018688613db3565b61ffff9490941660808301525060a0015295945050505050565b634e487b7160e01b5f52602160045260245ffd5b6001600160401b03861681526001600160801b0319851660208201526001600160801b03841660408201526001600160a01b038316606082015260a0810160038310613edd57613edd613e7b565b8260808301529695505050505050565b6001600160401b03851681526001600160801b0319841660208201526060604082018190525f90613f219083018486613db3565b9695505050505050565b6001600160401b03881681526001600160801b03198716602082015260e0604082018190525f90613f5e90830188613ca8565b8281036060840152613f708188613ca8565b60ff969096166080840152505060a08101929092526001600160a01b031660c090910152949350505050565b6001600160401b03861681526001600160801b0319851660208201526001600160a01b03841660408201526080606082018190525f90613d1b9083018486613db3565b80516020808301519190811015613293575f1960209190910360031b1b16919050565b601b811061401257614012613e7b565b60f81b9052565b60c01b6001600160c01b0319169052565b5f81518060208401855e5f93019283525090919050565b61404b8187614002565b60c085901b6001600160c01b03191660018201526001600160801b0319841660098201525f61407d601983018561402a565b9283525050602001949350505050565b61ffff85168152608060208201525f6140a96080830186613ca8565b9315156040830152506001600160a01b039190911660609091015292915050565b60801b6001600160801b0319169052565b6140e5818b614002565b6001600160c01b031960c08a811b821660018401526001600160801b03198a8116600985015260808a901b16601984015287901b16602982015284151560f890811b6031830152841515901b60328201526141436033820184614019565b614150603b8201836140ca565b604b019998505050505050505050565b61416a8184614002565b60c09190911b6001600160c01b0319166001820152600901919050565b6141918185614002565b60c09290921b6001600160c01b03191660018301526009820152602901919050565b6141bd8188614002565b6001600160c01b031960c087901b1660018201526001600160f81b031960f886811b8216600984015285901b16600a8201526001600160f01b031960f084901b16600b82015281515f90600d83019060208501835b82811015614230578151845260209384019390910190600101614212565b50919a9950505050505050505050565b61424a8188614002565b6001810195909552602185019390935260418401919091526061830152608182015260a101919050565b61427e818d614002565b60c08b901b6001600160c01b03191660018201526001600160801b03198a8116600983015260808a811b8216601984015289901b1660298201526142c560398201886140ca565b6142d26049820187614019565b84151560f81b605182015283151560f81b60528201526142f56053820184614019565b614302605b8201836140ca565b606b019b9a5050505050505050505050565b61431e8186614002565b6001600160c01b031960c094851b811660018301526001600160801b0319939093166009820152921b166019820152602101919050565b61435f8187614002565b6001600160c01b031960c095861b811660018301526001600160801b0319948516600983015260809390931b909316601984015290921b9091166029820152603101919050565b6143b08189614002565b60c087901b6001600160c01b03191660018201526001600160801b03198681166009830152608086811b8216601984015285901b16602982015260f083901b6001600160f01b03191660398201525f61440c603b83018461402a565b9998505050505050505050565b614423818a614002565b60c088901b6001600160c01b03191660018201526001600160801b031987811660098301526019820187905260398201869052608085901b16605982015260f083901b6001600160f01b03191660698201525f614483606b83018461402a565b9a9950505050505050505050565b61449b818a614002565b60c09790971b6001600160c01b03191660018801526001600160801b0319958616600988015260f09490941b6001600160f01b0319166019870152601b860192909252608090811b8416603b86015290811b8316604b8501521b16605b820152606b01919050565b61450d8186614002565b60c09390931b6001600160c01b03191660018401526009830191909152151560f81b6029820152602a01919050565b6145468189614002565b60c09690961b6001600160c01b03191660018701526001600160801b03199485166009870152608093841b85166019870152602986019290925260f81b6001600160f81b0319166049850152901b16604a820152605a01919050565b6145ac8186614002565b60c09390931b6001600160c01b03191660018401526001600160801b03199190911660098301526019820152603901919050565b6145ea8188614002565b60c086901b6001600160c01b03191660018201526001600160801b03198581166009830152608085901b16601982015260f083901b6001600160f01b03191660298201525f61463c602b83018461402a565b98975050505050505050565b6146528188614002565b6001600160c01b031960c096871b811660018301526001600160801b03199586166009830152608094851b861660198301529290931b90931660298301529190921b166039820152604101919050565b6146ac8185614002565b60809290921b6001600160801b031916600183015260f81b6001600160f81b0319166011820152601201919050565b6146e5818a614002565b60c088901b6001600160c01b03191660018201526001600160801b0319871660098201525f614717601983018861402a565b958652505060f89290921b6001600160f81b031916602084015260218301526041820152606101949350505050565b6147508188614002565b60c09590951b6001600160c01b03191660018601526001600160801b031993841660098601526019850192909252608090811b831660398501521b166049820152605901919050565b6147a38189614002565b60c087901b6001600160c01b03191660018201526001600160801b0319868116600983015260198201869052608085901b16603982015260f083901b6001600160f01b03191660498201525f61440c604b83018461402a565b6148068184614002565b6001810191909152602101919050565b634e487b7160e01b5f52601160045260245ffd5b8082018082111561295b5761295b614816565b8181038181111561295b5761295b614816565b5f61486461485e838661402a565b8461402a565b94935050505056","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":["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/","forge-std/=lib/forge-std/src/","@recon/=lib/setup-helpers/src/","@chimera/=lib/chimera/src/","chimera/=lib/chimera/src/","ds-test/=lib/chimera/lib/forge-std/lib/ds-test/src/","setup-helpers/=lib/setup-helpers/src/","src/=src/","test/=test/","createx-forge/=lib/createx-forge/"],"viaIR":false},"optimization_runs":1,"sourcify_repo_url":null,"decoded_constructor_args":[["1",{"internalType":"uint16","name":"localCentrifugeId_","type":"uint16"}],["0x7Ed48C31f2fdC40d37407cBaBf0870B2b688368f",{"internalType":"contract IScheduleAuth","name":"scheduleAuth_","type":"address"}],["0x19a524D03aA94ECEe41a80341537BCFCb47D3172",{"internalType":"contract IGateway","name":"gateway_","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-05-21T07:54:54.518732Z","implementations":[],"proxy_type":null,"external_libraries":[],"creation_bytecode":"0x60c060405234801561000f575f5ffd5b50604051614a92380380614a9283398101604081905261002e916100bc565b6001600160a01b0381165f8181526020819052604080822060019055518392917fdd0e34038ac38b2a1ce960229778ac48a8719bc900b6c4f8d0475c6e8b385a6091a2505061ffff929092166080526001600160a01b0390811660a052600180546001600160a01b0319169190921617905561011e565b6001600160a01b03811681146100b9575f5ffd5b50565b5f5f5f5f608085870312156100cf575f5ffd5b845161ffff811681146100e0575f5ffd5b60208601519094506100f1816100a5565b6040860151909350610102816100a5565b6060860151909250610113816100a5565b939692955090935050565b60805160a05161486c6102265f395f8181610256015281816126ca015261279701525f81816101df0152818161060801528181610740015281816107840152818161099d01528181610a9d01528181610bc501528181610c8501528181610dd101528181610e150152818161103d0152818161113b01528181611239015281816113df01528181611425015281816115fc01528181611643015281816117ad015281816118ac015281816119d601528181611ae301528181611c1b01528181611d8101528181611ed0015281816120130152818161210201528181612166015281816122b4015281816125e10152818161269b015281816127680152612819015261486c5ff3fe6080604052600436106101ca575f3560e01c80630a14789a146101ce578063116191b6146102195780631906c4a4146102455780631e840e451461027857806322285cf61461028d578063229d6f96146102ac578063268808c6146102bf57806332b05d53146102de578063351a4dd2146102f15780633daa8497146103045780634285d94c1461032357806347bfbcc6146103365780634c4d5a741461035557806353b6642414610368578063573178b41461037b5780635ffb48621461038e578063606436a3146103a157806363900d62146103b457806365fae35e146103c75780636c5e906c146103e65780637161b3f0146103f95780637a626bb71461040c578063862a05ef1461041f5780638c06200e146104325780638c5a29b4146104455780638c8b1f8e146104585780639c52a7f11461046b578063a2f965d51461048a578063a578b9ec1461049d578063ab1632f4146104b0578063bb308cdc146104cf578063bf353dbb146104e2578063cdd7b38a1461051b578063cfc32cc71461053a578063d4e8be831461054d578063dbb6d9d01461056c578063eae1ecdf1461057f578063ed15d96014610592578063f34b1f04146105b1578063ff69f205146105c4575b5f5ffd5b3480156101d9575f5ffd5b506102017f000000000000000000000000000000000000000000000000000000000000000081565b60405161ffff90911681526020015b60405180910390f35b348015610224575f5ffd5b50600154610238906001600160a01b031681565b60405161021091906130c5565b348015610250575f5ffd5b506102387f000000000000000000000000000000000000000000000000000000000000000081565b61028b6102863660046131df565b6105d7565b005b348015610298575f5ffd5b50600654610238906001600160a01b031681565b61028b6102ba3660046132ad565b61070c565b3480156102ca575f5ffd5b50600554610238906001600160a01b031681565b61028b6102ec366004613314565b61096c565b61028b6102ff366004613356565b610a6c565b34801561030f575f5ffd5b50600454610238906001600160a01b031681565b61028b6103313660046133b2565b610b94565b348015610341575f5ffd5b50600354610238906001600160a01b031681565b61028b6103633660046134a4565b610c54565b61028b610376366004613502565b610d9d565b61028b610389366004613581565b61100c565b61028b61039c3660046135da565b611107565b61028b6103af36600461366a565b611205565b61028b6103c236600461370f565b6113a3565b3480156103d2575f5ffd5b5061028b6103e1366004613787565b611555565b61028b6103f43660046137a0565b6115c8565b61028b610407366004613824565b61177c565b61028b61041a366004613866565b611878565b61028b61042d3660046138dd565b6119a5565b61028b61044036600461392d565b611ab2565b61028b6104533660046139b2565b611bdb565b61028b6104663660046139ff565b611d50565b348015610476575f5ffd5b5061028b610485366004613787565b611e2d565b61028b610498366004613a47565b611e9f565b61028b6104ab366004613b0f565b611fe2565b3480156104bb575f5ffd5b50600254610238906001600160a01b031681565b61028b6104dd36600461366a565b612132565b3480156104ed575f5ffd5b5061050d6104fc366004613787565b5f6020819052908152604090205481565b604051908152602001610210565b348015610526575f5ffd5b50600754610238906001600160a01b031681565b61028b610548366004613b73565b612283565b348015610558575f5ffd5b5061028b610567366004613bf2565b6123ba565b61028b61057a366004613824565b6125b0565b61028b61058d366004613c1c565b61266a565b34801561059d575f5ffd5b50600854610238906001600160a01b031681565b61028b6105bf366004613c1c565b612737565b61028b6105d2366004613c4c565b6127e8565b335f908152602081905260409020546001146106065760405163ea8e4eb560e01b815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000061ffff168661ffff16036106a6576003546040516324c7bed560e21b81526001600160a01b039091169063931efb549061066b908890889088908890600401613cd6565b5f604051808303815f87803b158015610682575f5ffd5b505af1158015610694573d5f5f3e3d5ffd5b505050506106a1816128d7565b610704565b610704866106fd60405180608001604052806106c88a6001600160401b031690565b6001600160401b031681526001600160801b031989166020820152604081018890526060016106f687612951565b9052612961565b5f846129b0565b505050505050565b335f9081526020819052604090205460011461073b5760405163ea8e4eb560e01b815260040160405180910390fd5b61ffff7f0000000000000000000000000000000000000000000000000000000000000000811690603087901c1661ffff1603610885576004546001600160a01b031663778158cc7f000000000000000000000000000000000000000000000000000000000000000087876107b26020890189613d26565b6107c260408a0160208b01613d41565b6107d260608b0160408c01613d41565b6107e260808c0160608d01613d5a565b6040516001600160e01b031960e08a901b16815261ffff90971660048801526001600160401b0395861660248801526001600160801b031990941660448701526001600160801b03909216606486015215156084850152151560a48401521660c482015260e4015b5f604051808303815f87803b158015610861575f5ffd5b505af1158015610873573d5f5f3e3d5ffd5b50505050610880816128d7565b610965565b61096561ffff603087901c166106fd6040518061010001604052806108b08a6001600160401b031690565b6001600160401b031681526020016001600160801b031989166001600160801b03191681526020908101906108e790890189613d26565b6001600160801b03168152602001426001600160401b031681526020018760200160208101906109179190613d41565b1515815260200161092e6060890160408a01613d41565b151581526020016109456080890160608a01613d5a565b6001600160401b03168152602001866001600160801b0316815250612a11565b5050505050565b335f9081526020819052604090205460011461099b5760405163ea8e4eb560e01b815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000061ffff168361ffff1603610a3a57600354604051632b89610160e01b81526001600160401b03841660048201526001600160a01b0390911690632b896101906024015b5f604051808303815f87803b158015610a16575f5ffd5b505af1158015610a28573d5f5f3e3d5ffd5b50505050610a35816128d7565b505050565b610a35836106fd6040518060200160405280610a5c876001600160401b031690565b6001600160401b03169052612a4f565b335f90815260208190526040902054600114610a9b5760405163ea8e4eb560e01b815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000061ffff168461ffff1603610b56576003546001600160a01b0316634421169384610ae585612a67565b6040516001600160e01b031960e085901b1681526001600160401b0390921660048301526001600160a01b031660248201526044015b5f604051808303815f87803b158015610b32575f5ffd5b505af1158015610b44573d5f5f3e3d5ffd5b50505050610b51816128d7565b610b8e565b610b8e846106fd6040518060400160405280610b78886001600160401b031690565b6001600160401b03168152602001869052612a97565b50505050565b335f90815260208190526040902054600114610bc35760405163ea8e4eb560e01b815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000061ffff168661ffff1603610c0b576040516322bc1cf360e01b815260040160405180910390fd5b610704866106fd6040518060800160405280610c2d8a6001600160401b031690565b6001600160401b0316815260ff808916602083015287166040820152606001889052612ab4565b335f90815260208190526040902054600114610c835760405163ea8e4eb560e01b815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000061ffff168761ffff1603610d61576005546001600160a01b031663109037c0610ccc88612a67565b610cd588612a67565b87610cdf88612a67565b60405160e086901b6001600160e01b03191681526001600160a01b0394851660048201529284166024840152604483019190915290911660648201526084810185905260a4015b5f604051808303815f87803b158015610d3d575f5ffd5b505af1158015610d4f573d5f5f3e3d5ffd5b50505050610d5c816128d7565b610d94565b610d94876106fd6040518060a001604052808a815260200189815260200188815260200187815260200186815250612aee565b50505050505050565b335f90815260208190526040902054600114610dcc5760405163ea8e4eb560e01b815260040160405180910390fd5b61ffff7f0000000000000000000000000000000000000000000000000000000000000000811690603089901c1661ffff1603610ef6576004546001600160a01b0316630646affc7f0000000000000000000000000000000000000000000000000000000000000000898989610e4460208b018b613d26565b89610e5560408d0160208e01613d41565b610e6560608e0160408f01613d41565b8d6060016020810190610e789190613d5a565b6040516001600160e01b031960e08c901b16815261ffff90991660048a01526001600160401b0397881660248a01526001600160801b031990961660448901526001600160801b0394851660648901529284166084880152921660a486015290151560c4850152151560e48401521661010482015261012401610d26565b610d9461ffff603089901c166106fd604051806101400160405280610f218c6001600160401b031690565b6001600160401b031681526020016001600160801b03198b166001600160801b03191681526020016001600160801b038a166001600160801b03168152602090810190610f70908a018a613d26565b6001600160801b03168152602001610f8e886001600160801b031690565b6001600160801b03168152602001426001600160401b03168152602001886020016020810190610fbe9190613d41565b15158152602001610fd560608a0160408b01613d41565b15158152602001610fec60808a0160608b01613d5a565b6001600160401b03168152602001866001600160801b0316815250612b1f565b335f9081526020819052604090205460011461103b5760405163ea8e4eb560e01b815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000061ffff168561ffff16036110bb5760035460405163eece6c4360e01b81526001600160401b0380871660048301526001600160801b031986166024830152841660448201526001600160a01b039091169063eece6c439060640161084a565b610965856106fd60405180606001604052806110dd896001600160401b031690565b6001600160401b0390811682526001600160801b0319891660208301528716604090910152612b69565b335f908152602081905260409020546001146111365760405163ea8e4eb560e01b815260040160405180910390fd5b61ffff7f0000000000000000000000000000000000000000000000000000000000000000811690607085901c1661ffff16036111a257600354604051636a4873e160e11b81526001600160a01b039091169063d490e7c29061084a908890889088908890600401613d75565b61096561ffff607085901c166106fd60405180608001604052806111cc8a6001600160401b031690565b6001600160401b0390811682526001600160801b03198a1660208301526001600160801b03891660408301528716606090910152612b8e565b335f908152602081905260409020546001146112345760405163ea8e4eb560e01b815260040160405180910390fd5b61ffff7f0000000000000000000000000000000000000000000000000000000000000000811690607088901c1661ffff16036112dd576003546040516336c6cf3760e21b81526001600160a01b039091169063db1b3cdc906112a2908b908b908b908b908b90600401613ddb565b5f604051808303815f87803b1580156112b9575f5ffd5b505af11580156112cb573d5f5f3e3d5ffd5b505050506112d8816128d7565b611399565b61139961ffff607088901c166113926040518060a001604052806113078d6001600160401b031690565b6001600160401b031681526020016001600160801b03198c166001600160801b03191681526020016001600160801b038b166001600160801b03168152602001876001600160801b0316815260200189898080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152505050915250612bb9565b84846129b0565b5050505050505050565b335f908152602081905260409020546001146113d25760405163ea8e4eb560e01b815260040160405180910390fd5b61ffff603089901c8116907f00000000000000000000000000000000000000000000000000000000000000001681036114a2576008546001600160a01b03166324f500a08a8a6114218b612a67565b8a8a7f00000000000000000000000000000000000000000000000000000000000000008b6040518863ffffffff1660e01b81526004016114679796959493929190613e1e565b5f604051808303815f87803b15801561147e575f5ffd5b505af1158015611490573d5f5f3e3d5ffd5b5050505061149d826128d7565b61154a565b61154a816115436040518060c001604052806114c48e6001600160401b031690565b6001600160401b031681526020016001600160801b03198d166001600160801b03191681526020018b8152602001888152602001876001600160801b031681526020018a8a8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152505050915250612bf9565b5f856129b0565b505050505050505050565b335f908152602081905260409020546001146115845760405163ea8e4eb560e01b815260040160405180910390fd5b6001600160a01b0381165f8181526020819052604080822060019055517fdd0e34038ac38b2a1ce960229778ac48a8719bc900b6c4f8d0475c6e8b385a609190a250565b335f908152602081905260409020546001146115f75760405163ea8e4eb560e01b815260040160405180910390fd5b61ffff7f0000000000000000000000000000000000000000000000000000000000000000811690603089901c1661ffff16036117015760048054604051630fb3791160e01b815261ffff7f0000000000000000000000000000000000000000000000000000000000000000811693820193909352918a1660248301526001600160401b03891660448301526001600160801b031988166064830152608482018790526001600160801b0380871660a4840152841660c48301526001600160a01b0383811660e48401521690630fb37911903490610104015f604051808303818588803b1580156116e5575f5ffd5b505af11580156116f7573d5f5f3e3d5ffd5b5050505050611399565b61139961ffff603089901c166106fd6040518060e0016040528061172b8c6001600160401b031690565b6001600160401b031681526001600160801b03198b16602082015261ffff8d166040820152606081018a90526001600160801b03898116608083015287811660a0830152881660c090910152612c3f565b335f908152602081905260409020546001146117ab5760405163ea8e4eb560e01b815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000061ffff168561ffff1603611837576001546001600160a01b031663a6fd509b856117f586612a67565b6040516001600160e01b031960e085901b1681526001600160401b0390921660048301526001600160a01b03166024820152841515604482015260640161084a565b610965856106fd6040518060600160405280611859896001600160401b031690565b6001600160401b03168152602001878152602001861515815250612c78565b335f908152602081905260409020546001146118a75760405163ea8e4eb560e01b815260040160405180910390fd5b61ffff7f0000000000000000000000000000000000000000000000000000000000000000811690607087901c1661ffff160361191b576007546001600160a01b031663b3cfb8178888886118fa89612a67565b886040518663ffffffff1660e01b8152600401610d26959493929190613e8f565b610d9461ffff607087901c166106fd6040518060c001604052806119458c6001600160401b031690565b6001600160401b031681526001600160801b03198b1660208201526001600160801b038a1660408201526060810189905260800187600281111561198b5761198b613e7b565b60ff168152602001866001600160801b0316815250612c9d565b335f908152602081905260409020546001146119d45760405163ea8e4eb560e01b815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000061ffff168561ffff1603611a6a576003546001600160a01b031663fb59077a8585611a1f86612a67565b6040516001600160e01b031960e086901b1681526001600160401b0390931660048401526001600160801b031990911660248301526001600160a01b0316604482015260640161084a565b610965856106fd6040518060600160405280611a8c896001600160401b031690565b6001600160401b031681526001600160801b031988166020820152604001869052612cd4565b335f90815260208190526040902054600114611ae15760405163ea8e4eb560e01b815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000061ffff168761ffff1603611b4657600354604051630f8dad5d60e11b81526001600160a01b0390911690631f1b5aba90610d26908990899089908990600401613eed565b610d94876106fd6040518060800160405280611b688b6001600160401b031690565b6001600160401b031681526020016001600160801b03198a166001600160801b0319168152602001866001600160801b0316815260200188888080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152505050915250612cf9565b335f90815260208190526040902054600114611c0a5760405163ea8e4eb560e01b815260040160405180910390fd5b5f611c1442612d33565b905061ffff7f0000000000000000000000000000000000000000000000000000000000000000811690607086901c1661ffff1603611ce557600354604051633a4ba8bf60e01b81526001600160401b0380891660048301526001600160801b0319881660248301526001600160801b03808816604484015286166064830152831660848201526001600160a01b0390911690633a4ba8bf9060a4015f604051808303815f87803b158015611cc6575f5ffd5b505af1158015611cd8573d5f5f3e3d5ffd5b505050506106a1826128d7565b61070461ffff607086901c166115436040518060a00160405280611d0f8b6001600160401b031690565b6001600160401b0390811682526001600160801b03198b1660208301526001600160801b038a81166040840152891660608301528616608090910152612d60565b335f90815260208190526040902054600114611d7f5760405163ea8e4eb560e01b815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000061ffff168461ffff1603611df15760048054604051633207adab60e01b81526001600160801b0386169281019290925260ff841660248301526001600160a01b031690633207adab90604401610b1b565b610b8e846106fd6040518060400160405280611e13886001600160801b031690565b6001600160801b031681526020018660ff16815250612d91565b335f90815260208190526040902054600114611e5c5760405163ea8e4eb560e01b815260040160405180910390fd5b6001600160a01b0381165f81815260208190526040808220829055517f184450df2e323acec0ed3b5c7531b81f9b4cdef7914dfd4c0a4317416bb5251b9190a250565b335f90815260208190526040902054600114611ece5760405163ea8e4eb560e01b815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000061ffff168961ffff1603611f75576003546001600160a01b0316636ea6e0a1898989898989611f1d8a612a67565b6040518863ffffffff1660e01b8152600401611f3f9796959493929190613f2b565b5f604051808303815f87803b158015611f56575f5ffd5b505af1158015611f68573d5f5f3e3d5ffd5b5050505061149d816128d7565b61154a896106fd6040518060e00160405280611f978d6001600160401b031690565b6001600160401b031681526001600160801b03198c166020820152604081018b9052606001611fc58a612951565b81526020018860ff16815260200187815260200186815250612dae565b335f908152602081905260409020546001146120115760405163ea8e4eb560e01b815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000061ffff168761ffff160361209f5760035460405163bccbfa8960e01b81526001600160401b03881660048201526001600160801b031987166024820152604481018690526001600160801b03851660648201526001600160a01b039091169063bccbfa89906084016112a2565b611399876121006040518060a001604052806120c18b6001600160401b031690565b6001600160401b031681526001600160801b03198a166020820152604081018990526001600160801b0388811660608301528716608090910152612df9565b7f000000000000000000000000000000000000000000000000000000000000000061ffff168b61ffff161415846129b0565b335f908152602081905260409020546001146121615760405163ea8e4eb560e01b815260040160405180910390fd5b61ffff7f000000000000000000000000000000000000000000000000000000000000000081169060308a901c1661ffff16036121ce5760048054604051632f6c33bf60e01b81526001600160a01b0390911691632f6c33bf916112a2918c918c918c918c918c9101613ddb565b61139961ffff60308a901c166113926040518060a001604052806121f88d6001600160401b031690565b6001600160401b031681526020016001600160801b03198c166001600160801b03191681526020016001600160801b038b166001600160801b03168152602001876001600160801b0316815260200189898080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152505050915250612e2a565b335f908152602081905260409020546001146122b25760405163ea8e4eb560e01b815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000061ffff168861ffff160361231f576008546001600160a01b03166312a5d10d88886122fd89612a67565b88886040518663ffffffff1660e01b81526004016112a2959493929190613f9c565b611399886106fd6040518060a001604052806123418c6001600160401b031690565b6001600160401b031681526020016001600160801b03198b166001600160801b0319168152602001898152602001866001600160801b0316815260200188888080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152505050915250612e4f565b335f908152602081905260409020546001146123e95760405163ea8e4eb560e01b815260040160405180910390fd5b8169343ab12430b7323632b960b11b0361241d57600480546001600160a01b0319166001600160a01b038316179055612574565b816473706f6b6560d81b0361244c57600380546001600160a01b0319166001600160a01b038316179055612574565b81666761746577617960c81b0361247d57600180546001600160a01b0319166001600160a01b038316179055612574565b816b18985b185b98d954da19595d60a21b036124b357600680546001600160a01b0319166001600160a01b038316179055612574565b816c7661756c74526567697374727960981b036124ea57600780546001600160a01b0319166001600160a01b038316179055612574565b816e31b7b73a3930b1ba2ab83230ba32b960891b0361252357600880546001600160a01b0319166001600160a01b038316179055612574565b816d3a37b5b2b72932b1b7bb32b932b960911b0361255b57600580546001600160a01b0319166001600160a01b038316179055612574565b604051633db0d5b960e01b815260040160405180910390fd5b817f8fef588b5fc1afbf5b2f06c1a435d513f208da2e6704c3d8f0e0ec91167066ba826040516125a491906130c5565b60405180910390a25050565b335f908152602081905260409020546001146125df5760405163ea8e4eb560e01b815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000061ffff168561ffff1603612629576006546001600160a01b031663a6fd509b856117f586612a67565b610965856106fd604051806060016040528061264b896001600160401b031690565b6001600160401b03168152602001878152602001861515815250612e8f565b335f908152602081905260409020546001146126995760405163ea8e4eb560e01b815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000061ffff168361ffff160361271c577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316633b68746161270084612a67565b6040518263ffffffff1660e01b81526004016109ff91906130c5565b610a35836106fd604051806020016040528086815250612eb4565b335f908152602081905260409020546001146127665760405163ea8e4eb560e01b815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000061ffff168361ffff16036127cd577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03166311fd3baa61270084612a67565b610a35836106fd604051806020016040528086815250612ecc565b335f908152602081905260409020546001146128175760405163ea8e4eb560e01b815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000061ffff168661ffff160361287c57600354604051634869ac6960e01b81526001600160a01b0390911690634869ac699061066b908890889088908890600401613d75565b610704866106fd604051806080016040528061289e8a6001600160401b031690565b6001600160401b0390811682526001600160801b03198a1660208301526001600160801b03891660408301528716606090910152612ee4565b341561294e575f816001600160a01b0316346040515f6040518083038185875af1925050503d805f8114612926576040519150601f19603f3d011682016040523d82523d5f602084013e61292b565b606091505b505090508061294c576040516202d94960ed1b815260040160405180910390fd5b505b50565b5f61295b82613fdf565b92915050565b805160208201516040830151606092600a929091612981905f6080612f0f565b856060015160405160200161299a959493929190614041565b6040516020818303038152906040529050919050565b6001546040516354e6733360e11b81526001600160a01b039091169063a9cce6669034906129e890889088908890889060040161408d565b5f604051808303818588803b1580156129ff575f5ffd5b505af115801561154a573d5f5f3e3d5ffd5b8051602080830151604080850151606086810151608088015160a089015160c08a015160e08b01519651949961299a996013999198919796016140db565b805160405160609161299a9160069190602001614160565b5f6001600160601b03821615612a905760405163e8bd165960e01b815260040160405180910390fd5b5060601c90565b805160208083015160405160609361299a93601893919201614187565b60606005825f015183602001518460400151612ad4866060015151612fdf565b866060015160405160200161299a969594939291906141b3565b60606003825f0151836020015184604001518560600151866080015160405160200161299a96959493929190614240565b8051602080830151604080850151606086810151608088015160a089015160c08a015160e08b01516101008c01516101208d01519851969b61299a9b60129b919a91999801614274565b60606015825f01518360200151846040015160405160200161299a9493929190614314565b60606014825f015183602001518460400151856060015160405160200161299a959493929190614355565b60606017825f0151836020015184604001518560600151612bde876080015151612fdf565b876080015160405160200161299a97969594939291906143a6565b6060601a825f01518360200151846040015185606001518660800151612c238860a0015151612fdf565b8860a0015160405160200161299a989796959493929190614419565b8051602080830151604080850151606086810151608088015160a089015160c08a01519551939861299a98600c98919791969501614491565b60606011825f01518360200151846040015160405160200161299a9493929190614503565b6060600f825f015183602001518460400151856060015186608001518760a0015160405160200161299a979695949392919061453c565b6060600b825f01518360200151846040015160405160200161299a94939291906145a2565b6060600e825f015183602001518460400151612d19866060015151612fdf565b866060015160405160200161299a969594939291906145e0565b5f6001600160401b03821115612d5c5760405163397df9e960e21b815260040160405180910390fd5b5090565b60606009825f0151836020015184604001518560600151866080015160405160200161299a96959493929190614648565b805160208083015160405160609361299a936004939192016146a2565b8051602082015160408301516060926007929091612dce905f6080612f0f565b856060015186608001518760a001518860c0015160405160200161299a9897969594939291906146db565b6060600d825f0151836020015184604001518560600151866080015160405160200161299a96959493929190614746565b60606016825f0151836020015184604001518560600151612bde876080015151612fdf565b60606019825f0151836020015184604001518560600151612e74876080015151612fdf565b876080015160405160200161299a9796959493929190614799565b60606010825f01518360200151846040015160405160200161299a9493929190614503565b805160405160609161299a91600191906020016147fc565b805160405160609161299a91600291906020016147fc565b60606008825f015183602001518460400151856060015160405160200161299a959493929190614355565b60605f612f1c838561482a565b855110905080612f3957612f31858585613003565b915050612fd8565b5f612f518686878951612f4c919061483d565b613003565b90505f86518686612f62919061482a565b612f6c919061483d565b6001600160401b03811115612f8357612f8361311a565b6040519080825280601f01601f191660200182016040528015612fad576020820181803683370190505b5090508181604051602001612fc3929190614850565b60405160208183030381529060405293505050505b9392505050565b5f61ffff821115612d5c5760405163029ac84360e11b815260040160405180910390fd5b60608182601f011015613029576040516323d5783d60e11b815260040160405180910390fd5b613033828461482a565b8451101561305457604051633b99b53d60e01b815260040160405180910390fd5b6060821580156130725760405191505f8252602082016040526130bc565b6040519150601f8416801560200281840101858101878315602002848b0101015b818310156130ab578051835260209283019201613093565b5050858452601f01601f1916604052505b50949350505050565b6001600160a01b0391909116815260200190565b803561ffff811681146130ea575f5ffd5b919050565b6001600160401b038116811461294e575f5ffd5b80356001600160801b0319811681146130ea575f5ffd5b634e487b7160e01b5f52604160045260245ffd5b604051601f8201601f191681016001600160401b03811182821017156131565761315661311a565b604052919050565b5f82601f83011261316d575f5ffd5b81356001600160401b038111156131865761318661311a565b613199601f8201601f191660200161312e565b8181528460208386010111156131ad575f5ffd5b816020850160208301375f918101602001919091529392505050565b80356001600160a01b03811681146130ea575f5ffd5b5f5f5f5f5f5f60c087890312156131f4575f5ffd5b6131fd876130d9565b9550602087013561320d816130ef565b945061321b60408801613103565b935060608701356001600160401b03811115613235575f5ffd5b61324189828a0161315e565b93505060808701356001600160401b0381111561325c575f5ffd5b61326889828a0161315e565b92505061327760a088016131c9565b90509295509295509295565b5f60808284031215613293575f5ffd5b50919050565b6001600160801b038116811461294e575f5ffd5b5f5f5f5f5f61010086880312156132c2575f5ffd5b85356132cd816130ef565b94506132db60208701613103565b93506132ea8760408801613283565b925060c08601356132fa81613299565b915061330860e087016131c9565b90509295509295909350565b5f5f5f60608486031215613326575f5ffd5b61332f846130d9565b9250602084013561333f816130ef565b915061334d604085016131c9565b90509250925092565b5f5f5f5f60808587031215613369575f5ffd5b613372856130d9565b93506020850135613382816130ef565b925060408501359150613397606086016131c9565b905092959194509250565b803560ff811681146130ea575f5ffd5b5f5f5f5f5f5f60c087890312156133c7575f5ffd5b6133d0876130d9565b955060208701356133e0816130ef565b945060408701356001600160401b038111156133fa575f5ffd5b8701601f8101891361340a575f5ffd5b80356001600160401b038111156134235761342361311a565b8060051b6134336020820161312e565b9182526020818401810192908101908c84111561344e575f5ffd5b6020850194505b8385101561347457843580835260209586019590935090910190613455565b8098505050505050613488606088016133a2565b9250613496608088016133a2565b915061327760a088016131c9565b5f5f5f5f5f5f5f60e0888a0312156134ba575f5ffd5b6134c3886130d9565b96506020880135955060408801359450606088013593506080880135925060a088013591506134f460c089016131c9565b905092959891949750929550565b5f5f5f5f5f5f5f610140888a031215613519575f5ffd5b8735613524816130ef565b965061353260208901613103565b9550604088013561354281613299565b94506135518960608a01613283565b935060e088013561356181613299565b925061010088013561357281613299565b91506134f461012089016131c9565b5f5f5f5f5f60a08688031215613595575f5ffd5b61359e866130d9565b945060208601356135ae816130ef565b93506135bc60408701613103565b925060608601356135cc816130ef565b9150613308608087016131c9565b5f5f5f5f5f60a086880312156135ee575f5ffd5b85356135f9816130ef565b945061360760208701613103565b935060408601356135bc81613299565b5f5f83601f840112613627575f5ffd5b5081356001600160401b0381111561363d575f5ffd5b602083019150836020828501011115613654575f5ffd5b9250929050565b803580151581146130ea575f5ffd5b5f5f5f5f5f5f5f5f60e0898b031215613681575f5ffd5b883561368c816130ef565b975061369a60208a01613103565b965060408901356136aa81613299565b955060608901356001600160401b038111156136c4575f5ffd5b6136d08b828c01613617565b90965094505060808901356136e481613299565b92506136f260a08a0161365b565b915061370060c08a016131c9565b90509295985092959890939650565b5f5f5f5f5f5f5f5f60e0898b031215613726575f5ffd5b8835613731816130ef565b975061373f60208a01613103565b96506040890135955060608901356001600160401b03811115613760575f5ffd5b61376c8b828c01613617565b9096509450506080890135925060a08901356136f281613299565b5f60208284031215613797575f5ffd5b612fd8826131c9565b5f5f5f5f5f5f5f5f610100898b0312156137b8575f5ffd5b6137c1896130d9565b975060208901356137d1816130ef565b96506137df60408a01613103565b95506060890135945060808901356137f681613299565b935060a089013561380681613299565b925060c089013561381681613299565b915061370060e08a016131c9565b5f5f5f5f5f60a08688031215613838575f5ffd5b613841866130d9565b94506020860135613851816130ef565b9350604086013592506135cc6060870161365b565b5f5f5f5f5f5f5f60e0888a03121561387c575f5ffd5b8735613887816130ef565b965061389560208901613103565b955060408801356138a581613299565b9450606088013593506080880135600381106138bf575f5ffd5b925060a08801356138cf81613299565b91506134f460c089016131c9565b5f5f5f5f5f60a086880312156138f1575f5ffd5b6138fa866130d9565b9450602086013561390a816130ef565b935061391860408701613103565b925060608601359150613308608087016131c9565b5f5f5f5f5f5f5f60c0888a031215613943575f5ffd5b61394c886130d9565b9650602088013561395c816130ef565b955061396a60408901613103565b945060608801356001600160401b03811115613984575f5ffd5b6139908a828b01613617565b90955093505060808801356139a481613299565b91506134f460a089016131c9565b5f5f5f5f5f60a086880312156139c6575f5ffd5b85356139d1816130ef565b94506139df60208701613103565b935060408601356139ef81613299565b925060608601356135cc81613299565b5f5f5f5f60808587031215613a12575f5ffd5b613a1b856130d9565b93506020850135613a2b81613299565b9250613a39604086016133a2565b9150613397606086016131c9565b5f5f5f5f5f5f5f5f5f6101208a8c031215613a60575f5ffd5b613a698a6130d9565b985060208a0135613a79816130ef565b9750613a8760408b01613103565b965060608a01356001600160401b03811115613aa1575f5ffd5b613aad8c828d0161315e565b96505060808a01356001600160401b03811115613ac8575f5ffd5b613ad48c828d0161315e565b955050613ae360a08b016133a2565b935060c08a0135925060e08a01359150613b006101008b016131c9565b90509295985092959850929598565b5f5f5f5f5f5f5f5f610100898b031215613b27575f5ffd5b613b30896130d9565b9750613b3e60208a016130d9565b96506040890135613b4e816130ef565b9550613b5c60608a01613103565b94506080890135935060a089013561380681613299565b5f5f5f5f5f5f5f5f60e0898b031215613b8a575f5ffd5b613b93896130d9565b97506020890135613ba3816130ef565b9650613bb160408a01613103565b95506060890135945060808901356001600160401b03811115613bd2575f5ffd5b613bde8b828c01613617565b90955093505060a08901356136f281613299565b5f5f60408385031215613c03575f5ffd5b82359150613c13602084016131c9565b90509250929050565b5f5f5f60608486031215613c2e575f5ffd5b613c37846130d9565b92506020840135915061334d604085016131c9565b5f5f5f5f5f5f60c08789031215613c61575f5ffd5b613c6a876130d9565b95506020870135613c7a816130ef565b9450613c8860408801613103565b93506060870135613c9881613299565b92506080870135613496816130ef565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b6001600160401b03851681526001600160801b0319841660208201526080604082018190525f90613d0990830185613ca8565b8281036060840152613d1b8185613ca8565b979650505050505050565b5f60208284031215613d36575f5ffd5b8135612fd881613299565b5f60208284031215613d51575f5ffd5b612fd88261365b565b5f60208284031215613d6a575f5ffd5b8135612fd8816130ef565b6001600160401b0394851681526001600160801b03199390931660208401526001600160801b03919091166040830152909116606082015260800190565b81835281816020850137505f828201602090810191909152601f909101601f19169091010190565b6001600160401b03861681526001600160801b0319851660208201526001600160801b03841660408201526080606082018190525f90613d1b9083018486613db3565b6001600160401b03881681526001600160801b0319871660208201526001600160a01b038616604082015260c0606082018190525f90613e619083018688613db3565b61ffff9490941660808301525060a0015295945050505050565b634e487b7160e01b5f52602160045260245ffd5b6001600160401b03861681526001600160801b0319851660208201526001600160801b03841660408201526001600160a01b038316606082015260a0810160038310613edd57613edd613e7b565b8260808301529695505050505050565b6001600160401b03851681526001600160801b0319841660208201526060604082018190525f90613f219083018486613db3565b9695505050505050565b6001600160401b03881681526001600160801b03198716602082015260e0604082018190525f90613f5e90830188613ca8565b8281036060840152613f708188613ca8565b60ff969096166080840152505060a08101929092526001600160a01b031660c090910152949350505050565b6001600160401b03861681526001600160801b0319851660208201526001600160a01b03841660408201526080606082018190525f90613d1b9083018486613db3565b80516020808301519190811015613293575f1960209190910360031b1b16919050565b601b811061401257614012613e7b565b60f81b9052565b60c01b6001600160c01b0319169052565b5f81518060208401855e5f93019283525090919050565b61404b8187614002565b60c085901b6001600160c01b03191660018201526001600160801b0319841660098201525f61407d601983018561402a565b9283525050602001949350505050565b61ffff85168152608060208201525f6140a96080830186613ca8565b9315156040830152506001600160a01b039190911660609091015292915050565b60801b6001600160801b0319169052565b6140e5818b614002565b6001600160c01b031960c08a811b821660018401526001600160801b03198a8116600985015260808a901b16601984015287901b16602982015284151560f890811b6031830152841515901b60328201526141436033820184614019565b614150603b8201836140ca565b604b019998505050505050505050565b61416a8184614002565b60c09190911b6001600160c01b0319166001820152600901919050565b6141918185614002565b60c09290921b6001600160c01b03191660018301526009820152602901919050565b6141bd8188614002565b6001600160c01b031960c087901b1660018201526001600160f81b031960f886811b8216600984015285901b16600a8201526001600160f01b031960f084901b16600b82015281515f90600d83019060208501835b82811015614230578151845260209384019390910190600101614212565b50919a9950505050505050505050565b61424a8188614002565b6001810195909552602185019390935260418401919091526061830152608182015260a101919050565b61427e818d614002565b60c08b901b6001600160c01b03191660018201526001600160801b03198a8116600983015260808a811b8216601984015289901b1660298201526142c560398201886140ca565b6142d26049820187614019565b84151560f81b605182015283151560f81b60528201526142f56053820184614019565b614302605b8201836140ca565b606b019b9a5050505050505050505050565b61431e8186614002565b6001600160c01b031960c094851b811660018301526001600160801b0319939093166009820152921b166019820152602101919050565b61435f8187614002565b6001600160c01b031960c095861b811660018301526001600160801b0319948516600983015260809390931b909316601984015290921b9091166029820152603101919050565b6143b08189614002565b60c087901b6001600160c01b03191660018201526001600160801b03198681166009830152608086811b8216601984015285901b16602982015260f083901b6001600160f01b03191660398201525f61440c603b83018461402a565b9998505050505050505050565b614423818a614002565b60c088901b6001600160c01b03191660018201526001600160801b031987811660098301526019820187905260398201869052608085901b16605982015260f083901b6001600160f01b03191660698201525f614483606b83018461402a565b9a9950505050505050505050565b61449b818a614002565b60c09790971b6001600160c01b03191660018801526001600160801b0319958616600988015260f09490941b6001600160f01b0319166019870152601b860192909252608090811b8416603b86015290811b8316604b8501521b16605b820152606b01919050565b61450d8186614002565b60c09390931b6001600160c01b03191660018401526009830191909152151560f81b6029820152602a01919050565b6145468189614002565b60c09690961b6001600160c01b03191660018701526001600160801b03199485166009870152608093841b85166019870152602986019290925260f81b6001600160f81b0319166049850152901b16604a820152605a01919050565b6145ac8186614002565b60c09390931b6001600160c01b03191660018401526001600160801b03199190911660098301526019820152603901919050565b6145ea8188614002565b60c086901b6001600160c01b03191660018201526001600160801b03198581166009830152608085901b16601982015260f083901b6001600160f01b03191660298201525f61463c602b83018461402a565b98975050505050505050565b6146528188614002565b6001600160c01b031960c096871b811660018301526001600160801b03199586166009830152608094851b861660198301529290931b90931660298301529190921b166039820152604101919050565b6146ac8185614002565b60809290921b6001600160801b031916600183015260f81b6001600160f81b0319166011820152601201919050565b6146e5818a614002565b60c088901b6001600160c01b03191660018201526001600160801b0319871660098201525f614717601983018861402a565b958652505060f89290921b6001600160f81b031916602084015260218301526041820152606101949350505050565b6147508188614002565b60c09590951b6001600160c01b03191660018601526001600160801b031993841660098601526019850192909252608090811b831660398501521b166049820152605901919050565b6147a38189614002565b60c087901b6001600160c01b03191660018201526001600160801b0319868116600983015260198201869052608085901b16603982015260f083901b6001600160f01b03191660498201525f61440c604b83018461402a565b6148068184614002565b6001810191909152602101919050565b634e487b7160e01b5f52601160045260245ffd5b8082018082111561295b5761295b614816565b8181038181111561295b5761295b614816565b5f61486461485e838661402a565b8461402a565b9493505050505600000000000000000000000000000000000000000000000000000000000000010000000000000000000000007ed48c31f2fdc40d37407cbabf0870b2b688368f00000000000000000000000019a524d03aa94ecee41a80341537bcfcb47d3172000000000000000000000000b3c086db30c1be6e40d8775607c3662ab160bda5","name":"MessageDispatcher","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/admin/interfaces/IRoot.sol","source_code":"// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\nimport {IEndorsements} from \"../../core/spoke/interfaces/IEndorsements.sol\";\nimport {IScheduleAuth} from \"../../core/messaging/interfaces/IScheduleAuth.sol\";\nimport {IProtocolPauser} from \"../../core/messaging/interfaces/IProtocolPauser.sol\";\n\ninterface IRoot is IEndorsements, IProtocolPauser, IScheduleAuth {\n    //----------------------------------------------------------------------------------------------\n    // Events\n    //----------------------------------------------------------------------------------------------\n\n    event File(bytes32 indexed what, uint256 data);\n    event RelyContract(address indexed target, address indexed user);\n    event DenyContract(address indexed target, address indexed user);\n\n    //----------------------------------------------------------------------------------------------\n    // Errors\n    //----------------------------------------------------------------------------------------------\n\n    error DelayTooLong();\n    error FileUnrecognizedParam();\n    error TargetNotScheduled();\n    error TargetNotReady();\n\n    //----------------------------------------------------------------------------------------------\n    // View methods\n    //----------------------------------------------------------------------------------------------\n\n    /// @notice Returns the current timelock for adding new wards\n    function delay() external view returns (uint256);\n\n    /// @notice Trusted contracts within the system\n    function endorsements(address target) external view returns (uint256);\n\n    /// @notice Returns when `relyTarget` has passed the timelock\n    function schedule(address relyTarget) external view returns (uint256 timestamp);\n\n    //----------------------------------------------------------------------------------------------\n    // Administration\n    //----------------------------------------------------------------------------------------------\n\n    /// @notice Updates a contract parameter\n    /// @param what Accepts a bytes32 representation of 'delay'\n    function file(bytes32 what, uint256 data) external;\n\n    //----------------------------------------------------------------------------------------------\n    // Endorsements\n    //----------------------------------------------------------------------------------------------\n\n    /// @notice Endorses the `user`\n    /// @dev    Endorsed users are trusted contracts in the system. They are allowed to bypass\n    ///         token restrictions (e.g. the Escrow can automatically receive share class tokens by being endorsed), and\n    ///         can automatically set operators in ERC-7540 vaults (e.g. the VaultRouter) is always an operator.\n    function endorse(address user) external;\n\n    /// @notice Removes the endorsed user\n    function veto(address user) external;\n\n    //----------------------------------------------------------------------------------------------\n    // Pause management\n    //----------------------------------------------------------------------------------------------\n\n    /// @notice Pause any contracts that depend on `Root.paused()`\n    function pause() external;\n\n    /// @notice Unpause any contracts that depend on `Root.paused()`\n    function unpause() external;\n\n    //----------------------------------------------------------------------------------------------\n    // Timelocked ward management\n    //----------------------------------------------------------------------------------------------\n\n    /// @notice Execute a scheduled rely\n    /// @dev    Can be triggered by anyone since the scheduling is protected\n    function executeScheduledRely(address target) external;\n\n    //----------------------------------------------------------------------------------------------\n    // External contract ward management\n    //----------------------------------------------------------------------------------------------\n\n    /// @notice Make an address a ward on any contract that Root is a ward on\n    function relyContract(address target, address user) external;\n\n    /// @notice Removes an address as a ward on any contract that Root is a ward on\n    function denyContract(address target, address user) external;\n}\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/IAdapter.sol","source_code":"// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\ninterface IAdapter {\n    //----------------------------------------------------------------------------------------------\n    // Errors\n    //----------------------------------------------------------------------------------------------\n\n    error NotEntrypoint();\n    error UnknownChainId();\n\n    //----------------------------------------------------------------------------------------------\n    // Outgoing\n    //----------------------------------------------------------------------------------------------\n\n    /// @notice Send a payload to the destination chain\n    /// @param centrifugeId The destination chain ID\n    /// @param payload The message payload to send\n    /// @param gasLimit The gas limit for execution on the destination chain\n    /// @param refund The address to receive any excess payment refund\n    /// @return adapterData Adapter-specific data returned from the send operation\n    function send(uint16 centrifugeId, bytes calldata payload, uint256 gasLimit, address refund)\n        external\n        payable\n        returns (bytes32 adapterData);\n\n    /// @notice Estimate the total cost in native gas tokens\n    /// @param centrifugeId The destination chain ID\n    /// @param payload The message payload to send\n    /// @param gasLimit The gas limit for execution on the destination chain\n    /// @return The estimated cost in native gas tokens\n    function estimate(uint16 centrifugeId, bytes calldata payload, uint256 gasLimit) external view returns (uint256);\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 {IAdapter} from \"./IAdapter.sol\";\nimport {IMessageHandler} from \"./IMessageHandler.sol\";\nimport {IProtocolPauser} from \"./IProtocolPauser.sol\";\nimport {IMessageProperties} from \"./IMessageProperties.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 Block or unblock outgoing messages for a pool on a specific chain.\n    /// @dev    Used during adapter migrations to ensure no messages are in-flight while the adapter\n    ///         configuration is being updated. See `IHub.setAdapters` for the full procedure.\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 Protocol's internal chain identifier for this network, distinct from the EVM chain ID\n    function localCentrifugeId() external view returns (uint16);\n\n    /// @notice MultiAdapter used for outbound message dispatch and inbound quorum verification\n    function adapter() external view returns (IAdapter);\n\n    /// @notice Handler that routes confirmed inbound cross-chain messages to their target contracts\n    function processor() external view returns (IMessageHandler);\n\n    /// @notice Provides gas cost estimates and message type metadata for cross-chain messages\n    function messageProperties() external view returns (IMessageProperties);\n\n    /// @notice ProtocolGuardian that can pause/unpause all cross-chain messaging\n    function pauser() external view returns (IProtocolPauser);\n\n    /// @notice Returns whether an address is a manager for a given pool\n    /// @param poolId The pool identifier\n    /// @param who The address to check\n    /// @return Whether the address is a manager\n    function manager(PoolId poolId, address who) external view returns (bool);\n\n    /// @notice Returns whether outgoing messages are blocked for a pool on a specific chain\n    /// @param centrifugeId The destination chain identifier\n    /// @param poolId The pool identifier\n    /// @return Whether outgoing is blocked\n    function isOutgoingBlocked(uint16 centrifugeId, PoolId poolId) external view returns (bool);\n\n    /// @notice Returns the underpaid batch info for a given chain and batch hash\n    /// @param centrifugeId The destination chain identifier\n    /// @param batchHash The hash of the underpaid batch\n    /// @return gasLimit The gas limit for the batch\n    /// @return counter The number of underpaid instances\n    function underpaid(uint16 centrifugeId, bytes32 batchHash) external view returns (uint128 gasLimit, uint64 counter);\n\n    /// @notice Returns the number of failed message instances for a given chain and message hash\n    /// @param centrifugeId The source chain identifier\n    /// @param messageHash The hash of the failed message\n    /// @return The count of failed instances\n    function failedMessages(uint16 centrifugeId, bytes32 messageHash) external view returns (uint256);\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/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/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/core/messaging/interfaces/IMessageDispatcher.sol","source_code":"// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\nimport {IGateway} from \"./IGateway.sol\";\nimport {IMultiAdapter} from \"./IMultiAdapter.sol\";\nimport {IScheduleAuth} from \"./IScheduleAuth.sol\";\nimport {ITokenRecoverer} from \"./ITokenRecoverer.sol\";\nimport {ISpokeMessageSender, IHubMessageSender, IScheduleAuthMessageSender} from \"./IGatewaySenders.sol\";\nimport {\n    ISpokeGatewayHandler,\n    IBalanceSheetGatewayHandler,\n    IHubGatewayHandler,\n    IContractUpdateGatewayHandler,\n    IVaultRegistryGatewayHandler\n} from \"./IGatewayHandlers.sol\";\n\ninterface IMessageDispatcher is IScheduleAuthMessageSender, ISpokeMessageSender, IHubMessageSender {\n    /// @notice Emitted when a call to `file()` was performed.\n    event File(bytes32 indexed what, address addr);\n\n    /// @notice Dispatched when the `what` parameter of `file()` is not supported by the implementation.\n    error FileUnrecognizedParam();\n\n    /// @notice Dispatched when an account is not valid to withdraw funds\n    error CannotRefund();\n\n    //----------------------------------------------------------------------------------------------\n    // View methods\n    //----------------------------------------------------------------------------------------------\n\n    /// @notice Routes and batches cross-chain messages between hub and spoke\n    function gateway() external view returns (IGateway);\n\n    /// @notice Handles multi-protocol message verification and routing for cross-chain communication\n    function multiAdapter() external view returns (IMultiAdapter);\n\n    /// @notice Spoke-side handler for pool, share class, and vault operations\n    function spoke() external view returns (ISpokeGatewayHandler);\n\n    /// @notice Processes timelocked rely/deny operations received from remote chains\n    function scheduleAuth() external view returns (IScheduleAuth);\n\n    /// @notice Hub-side handler for investment request processing and share issuance\n    function hubHandler() external view returns (IHubGatewayHandler);\n\n    /// @notice Recovers tokens mistakenly sent to protocol contracts\n    function tokenRecoverer() external view returns (ITokenRecoverer);\n\n    /// @notice Spoke-side handler for share and asset balance mutations\n    function balanceSheet() external view returns (IBalanceSheetGatewayHandler);\n\n    /// @notice Spoke-side handler for vault deployment and linking\n    function vaultRegistry() external view returns (IVaultRegistryGatewayHandler);\n\n    /// @notice Spoke-side handler for trusted contract reference updates\n    function contractUpdater() external view returns (IContractUpdateGatewayHandler);\n\n    //----------------------------------------------------------------------------------------------\n    // Administration\n    //----------------------------------------------------------------------------------------------\n\n    /// @notice Updates a contract parameter.\n    /// @param what Name of the parameter to update.\n    ///         Accepts a `bytes32` representation of 'hubRegistry' string value.\n    /// @param data New value given to the `what` parameter\n    function file(bytes32 what, address data) external;\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/core/messaging/interfaces/IMessageProperties.sol","source_code":"// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\nimport {PoolId} from \"../../types/PoolId.sol\";\n\n/// @notice Defines methods to get properties from raw messages\ninterface IMessageProperties {\n    /// @notice Gas limit for the execution cost of an individual message in a remote chain from the adapter.\n    /// @dev    NOTE: In the future we could want to dispatch:\n    ///         - by destination chain (for non-EVM chains)\n    ///         - by message type\n    ///         - by inspecting the payload checking different subsmessages that alter the endpoint processing\n    /// @param centrifugeId Where to the cost is defined\n    /// @param message Individual message\n    /// @return Estimated cost in WEI units\n    function messageOverallGasLimit(uint16 centrifugeId, bytes calldata message) external view returns (uint128);\n\n    /// @notice Similar to messageOverallGasLimit but taking only into account the exact gas to process it from the Gateway\n    ///         for processing the message without any extra addition\n    function messageProcessingGasLimit(uint16 centrifugeId, bytes calldata message) external view returns (uint128);\n\n    /// @notice Maximum Gas limit for a batch, determined how much the destination chain can process\n    /// @param centrifugeId Destination where to the maximum cost is defined\n    function maxBatchGasLimit(uint16 centrifugeId) external view returns (uint128);\n\n    /// @notice Inspect the message to return the length\n    function messageLength(bytes calldata message) external view returns (uint16);\n\n    /// @notice Inspect the message to return the associated PoolId if any\n    function messagePoolId(bytes calldata message) external pure returns (PoolId);\n}\n"},{"file_path":"src/core/messaging/interfaces/IMultiAdapter.sol","source_code":"// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\nimport {IAdapter} from \"./IAdapter.sol\";\nimport {IMessageHandler} from \"./IMessageHandler.sol\";\nimport {IMessageProperties} from \"./IMessageProperties.sol\";\n\nimport {PoolId} from \"../../types/PoolId.sol\";\n\nuint8 constant MAX_ADAPTER_COUNT = 8;\n\n/// @notice Interface for handling several adapters transparently\ninterface IMultiAdapter is IAdapter, IMessageHandler {\n    //----------------------------------------------------------------------------------------------\n    // Structs\n    //----------------------------------------------------------------------------------------------\n\n    /// @dev Each adapter struct is packed with the quorum, threshold and recoveryIndex to reduce SLOADs on handle\n    struct Adapter {\n        /// @notice Starts at 1 and maps to id - 1 as the index on the adapters array\n        uint8 id;\n        /// @notice Number of configured adapters\n        uint8 quorum;\n        /// @notice Number of votes required for a message to be executed. Less-equal to quorum\n        uint8 threshold;\n        /// @notice Index in the adapter array to start consider the adapter as recovery adapter\n        uint8 recoveryIndex;\n        /// @notice Each time the quorum is decreased, a new session starts which invalidates old votes\n        uint128 activeSessionId;\n    }\n\n    struct Inbound {\n        /// @dev Counts are stored as integers (instead of boolean values) to accommodate duplicate\n        ///      messages (e.g. two investments from the same user with the same amount) being\n        ///      processed in parallel. The entire struct is packed in a single bytes32 slot.\n        ///      Max int16 = 32,767 so at most 32,767 duplicate messages can be processed in parallel\n        int16[MAX_ADAPTER_COUNT] votes;\n        /// @notice Each time adapters are updated, a new session starts which invalidates old votes\n        uint128 sessionId;\n    }\n\n    //----------------------------------------------------------------------------------------------\n    // Events\n    //----------------------------------------------------------------------------------------------\n\n    event File(bytes32 indexed what, address addr);\n    event SetAdapters(uint16 centrifugeId, PoolId poolId, IAdapter[] adapters, uint8 threshold, uint8 recoveryIndex);\n    event HandlePayload(uint16 indexed centrifugeId, bytes32 indexed payloadId, bytes payload, IAdapter adapter);\n    event SendPayload(\n        uint16 indexed centrifugeId,\n        bytes32 indexed payloadId,\n        bytes payload,\n        IAdapter adapter,\n        bytes32 adapterData,\n        uint256 gasLimit,\n        uint256 gasPaid,\n        address refund\n    );\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 contract is configured with an empty adapter set.\n    error EmptyAdapterSet();\n\n    /// @notice Dispatched when the threshold number is higher than the number of configured adapters (aka quorum).\n    error ThresholdHigherThanQuorum();\n\n    /// @notice Dispatched when the recovery index is higher than the number of configured adapters (aka quorum).\n    error RecoveryIndexHigherThanQuorum();\n\n    /// @notice Dispatched when the contract is configured with a number of adapter exceeding the maximum.\n    error ExceedsMax();\n\n    /// @notice Dispatched when the contract is configured with duplicate adapters.\n    error NoDuplicatesAllowed();\n\n    /// @notice Dispatched when the contract tries to handle a message from an adapter not contained in the adapter set.\n    error InvalidAdapter();\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 Configure new adapters for a determined pool.\n    ///         Messages sent but not yet received when this is executed will be lost.\n    /// @param  centrifugeId Chain where the adapters are associated to.\n    /// @param  poolId PoolId associated to the adapters\n    /// @param  adapters New adapter addresses already deployed.\n    ///         If the array is empty, it disables the usage for messages of that pool.\n    /// @param  threshold Minimum number of adapters required to process the messages\n    ///         If not wanted a threshold set `adapters.length` value\n    /// @param  recoveryIndex Index in adapters array from where consider the adapter as recovery adapter.\n    ///         If not wanted a recoveryIndex set `adapters.length` value\n    ///\n    ///         A recovery adapter is an adapter that does not decrease their votes below 0.\n    ///         it is, it can never have a debt on messages not received.\n    ///         It can be used to easily emulate receiving a missing message by some of the others adapters.\n    ///\n    ///         i.e: Suppose a configuration of `[Adapter1, Adapter2, RecoveryAdapter]` with threshold 2.\n    ///         Both `Adapter1` and `Adapter2` will need always need to handle the message, each one, to process it.\n    ///         In case some of those fail, the losing vote can be recover through the `RecoveryAdapter`` to reach\n    ///         threshold 2.\n    function setAdapters(\n        uint16 centrifugeId,\n        PoolId poolId,\n        IAdapter[] calldata adapters,\n        uint8 threshold,\n        uint8 recoveryIndex\n    ) external;\n\n    //----------------------------------------------------------------------------------------------\n    // View methods\n    //----------------------------------------------------------------------------------------------\n\n    /// @notice Protocol's internal chain identifier for this network, distinct from the EVM chain ID\n    function localCentrifugeId() external view returns (uint16);\n\n    /// @notice Gateway that receives confirmed messages once adapter quorum is reached\n    function gateway() external view returns (IMessageHandler);\n\n    /// @notice Provides gas cost estimates and message type metadata for cross-chain messages\n    function messageProperties() external view returns (IMessageProperties);\n\n    /// @notice Returns the inbound message session id for a given chain and payload hash\n    /// @param centrifugeId The source chain identifier\n    /// @param payloadHash The hash of the inbound payload\n    /// @return sessionId The session id when the votes were cast\n    function inbound(uint16 centrifugeId, bytes32 payloadHash) external view returns (uint128 sessionId);\n\n    /// @notice Number of total configured adapters for a pool\n    /// @param centrifugeId Chain where the adapter is configured for\n    /// @param poolId PoolId associated to the adapters\n    /// @return Needed amount\n    function quorum(uint16 centrifugeId, PoolId poolId) external view returns (uint8);\n\n    /// @notice Number of required votes to consider a message valid for processing\n    /// @dev It's lower-equal than quorum\n    /// @param centrifugeId Chain where the adapter is configured for\n    /// @param poolId PoolId associated to the adapters\n    /// @return Needed amount\n    function threshold(uint16 centrifugeId, PoolId poolId) external view returns (uint8);\n\n    /// @notice Index in the adapter array to start consider the adapter as recovery adapter\n    /// @param centrifugeId Chain where the adapter is configured for\n    /// @param poolId PoolId associated to the adapters\n    /// @return Recovery index\n    function recoveryIndex(uint16 centrifugeId, PoolId poolId) external view returns (uint8);\n\n    /// @notice Gets the current active routers session id\n    /// @dev When the adapters are updated with new ones, each new set of adapters has their own sessionId\n    /// @param centrifugeId Chain where the adapters are configured for\n    /// @param poolId PoolId associated to the adapters\n    /// @return The active session id\n    function activeSessionId(uint16 centrifugeId, PoolId poolId) external view returns (uint128);\n\n    /// @notice Counts how many times each incoming messages has been received per adapter.\n    /// @dev    It supports parallel messages ( duplicates ). That means that the incoming messages could be\n    ///         the result of two or more independent request from the user of the same type.\n    ///         i.e. Same user would like to deposit same underlying asset with the same amount more then once.\n    /// @param  centrifugeId Chain where the adapter is configured for\n    /// @param  payloadHash The hash value of the incoming message.\n    /// @return The votes array\n    function votes(uint16 centrifugeId, bytes32 payloadHash) external view returns (int16[MAX_ADAPTER_COUNT] memory);\n\n    /// @notice Returns the address of the adapter at the given id\n    /// @param centrifugeId Chain where the adapters are configured for\n    /// @param poolId PoolId associated to the adapters\n    /// @param id The adapter id\n    /// @return The adapter at the specified id\n    function adapters(uint16 centrifugeId, PoolId poolId, uint256 id) external view returns (IAdapter);\n}\n"},{"file_path":"src/core/messaging/interfaces/IProtocolPauser.sol","source_code":"// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\ninterface IProtocolPauser {\n    event Pause();\n    event Unpause();\n\n    /// @notice Returns whether the root is paused\n    /// @return True if the protocol is paused, false otherwise\n    function paused() external view returns (bool);\n}\n"},{"file_path":"src/core/messaging/interfaces/IScheduleAuth.sol","source_code":"// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\ninterface IScheduleAuth {\n    event ScheduleRely(address indexed target, uint256 indexed scheduledTime);\n    event CancelRely(address indexed target);\n\n    /// @notice Schedule relying a new ward after the delay has passed\n    /// @param target The address to schedule as a ward\n    function scheduleRely(address target) external;\n\n    /// @notice Cancel a pending scheduled rely\n    /// @param target The address to cancel the scheduled rely for\n    function cancelRely(address target) external;\n}\n"},{"file_path":"src/core/messaging/interfaces/ITokenRecoverer.sol","source_code":"// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\nimport {IRecoverable} from \"../../../misc/interfaces/IRecoverable.sol\";\n\nimport {IRoot} from \"../../../admin/interfaces/IRoot.sol\";\n\ninterface ITokenRecoverer {\n    event RecoverTokens(\n        IRecoverable indexed target, address indexed token, uint256 tokenId, address indexed to, uint256 amount\n    );\n\n    /// @notice Recovers tokens from a target contract\n    /// @param target The contract to recover tokens from\n    /// @param token The token address to recover\n    /// @param tokenId The token ID (0 for ERC20, non-zero for ERC6909)\n    /// @param to The address to send recovered tokens to\n    /// @param amount The amount of tokens to recover\n    function recoverTokens(IRecoverable target, address token, uint256 tokenId, address to, uint256 amount) external;\n\n    /// @notice Root authority that grants this contract permission to recover tokens from protocol contracts\n    function root() external view returns (IRoot);\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/core/spoke/interfaces/IEndorsements.sol","source_code":"// SPDX-License-Identifier: GPL-2.0-or-later\npragma solidity >=0.5.0;\n\ninterface IEndorsements {\n    event Endorse(address indexed user);\n    event Veto(address indexed user);\n\n    /// @notice Returns whether the user is endorsed\n    /// @param user The address to check for endorsement status\n    /// @return True if the user is endorsed, false otherwise\n    function endorsed(address user) external view returns (bool);\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/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/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/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/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/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/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/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/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":"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"}],"certified":false,"conflicting_implementations":null,"abi":[{"inputs":[{"internalType":"uint16","name":"localCentrifugeId_","type":"uint16"},{"internalType":"contract IScheduleAuth","name":"scheduleAuth_","type":"address"},{"internalType":"contract IGateway","name":"gateway_","type":"address"},{"internalType":"address","name":"deployer","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"CannotBeSentLocally","type":"error"},{"inputs":[],"name":"CannotRefund","type":"error"},{"inputs":[],"name":"FileUnrecognizedParam","type":"error"},{"inputs":[],"name":"NotAuthorized","type":"error"},{"inputs":[],"name":"PrefixNotZero","type":"error"},{"inputs":[],"name":"SliceOutOfBounds","type":"error"},{"inputs":[],"name":"SliceOverflow","type":"error"},{"inputs":[],"name":"Uint16_Overflow","type":"error"},{"inputs":[],"name":"Uint64_Overflow","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"}],"name":"Deny","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"what","type":"bytes32"},{"indexed":false,"internalType":"address","name":"addr","type":"address"}],"name":"File","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"}],"name":"Rely","type":"event"},{"inputs":[],"name":"balanceSheet","outputs":[{"internalType":"contract IBalanceSheetGatewayHandler","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"contractUpdater","outputs":[{"internalType":"contract IContractUpdateGatewayHandler","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"deny","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":[],"name":"hubHandler","outputs":[{"internalType":"contract IHubGatewayHandler","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"localCentrifugeId","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"multiAdapter","outputs":[{"internalType":"contract IMultiAdapter","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"rely","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"scheduleAuth","outputs":[{"internalType":"contract IScheduleAuth","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"centrifugeId","type":"uint16"},{"internalType":"bytes32","name":"target","type":"bytes32"},{"internalType":"address","name":"refund","type":"address"}],"name":"sendCancelUpgrade","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint16","name":"originCentrifugeId","type":"uint16"},{"internalType":"uint16","name":"targetCentrifugeId","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":"address","name":"refund","type":"address"}],"name":"sendExecuteTransferShares","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint16","name":"targetCentrifugeId","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":"sendInitiateTransferShares","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint16","name":"centrifugeId","type":"uint16"},{"internalType":"PoolId","name":"poolId","type":"uint64"},{"internalType":"address","name":"refund","type":"address"}],"name":"sendNotifyPool","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":"pricePoolPerAsset","type":"uint128"},{"internalType":"address","name":"refund","type":"address"}],"name":"sendNotifyPricePoolPerAsset","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint16","name":"chainId","type":"uint16"},{"internalType":"PoolId","name":"poolId","type":"uint64"},{"internalType":"ShareClassId","name":"scId","type":"bytes16"},{"internalType":"D18","name":"pricePoolPerShare","type":"uint128"},{"internalType":"uint64","name":"computedAt","type":"uint64"},{"internalType":"address","name":"refund","type":"address"}],"name":"sendNotifyPricePoolPerShare","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":"string","name":"name","type":"string"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"bytes32","name":"hook","type":"bytes32"},{"internalType":"address","name":"refund","type":"address"}],"name":"sendNotifyShareClass","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":"string","name":"name","type":"string"},{"internalType":"string","name":"symbol","type":"string"},{"internalType":"address","name":"refund","type":"address"}],"name":"sendNotifyShareMetadata","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint16","name":"centrifugeId","type":"uint16"},{"internalType":"bytes32","name":"target","type":"bytes32"},{"internalType":"bytes32","name":"token","type":"bytes32"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes32","name":"to","type":"bytes32"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"refund","type":"address"}],"name":"sendRecoverTokens","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint16","name":"centrifugeId","type":"uint16"},{"internalType":"AssetId","name":"assetId","type":"uint128"},{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"address","name":"refund","type":"address"}],"name":"sendRegisterAsset","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"},{"internalType":"uint128","name":"extraGasLimit","type":"uint128"},{"internalType":"bool","name":"unpaidMode","type":"bool"},{"internalType":"address","name":"refund","type":"address"}],"name":"sendRequest","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"},{"internalType":"uint128","name":"extraGasLimit","type":"uint128"},{"internalType":"bool","name":"unpaidMode","type":"bool"},{"internalType":"address","name":"refund","type":"address"}],"name":"sendRequestCallback","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint16","name":"centrifugeId","type":"uint16"},{"internalType":"bytes32","name":"target","type":"bytes32"},{"internalType":"address","name":"refund","type":"address"}],"name":"sendScheduleUpgrade","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":"uint64","name":"maxPriceAge","type":"uint64"},{"internalType":"address","name":"refund","type":"address"}],"name":"sendSetMaxAssetPriceAge","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":"uint64","name":"maxPriceAge","type":"uint64"},{"internalType":"address","name":"refund","type":"address"}],"name":"sendSetMaxSharePriceAge","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint16","name":"centrifugeId","type":"uint16"},{"internalType":"PoolId","name":"poolId","type":"uint64"},{"internalType":"bytes32[]","name":"adapters","type":"bytes32[]"},{"internalType":"uint8","name":"threshold","type":"uint8"},{"internalType":"uint8","name":"recoveryIndex","type":"uint8"},{"internalType":"address","name":"refund","type":"address"}],"name":"sendSetPoolAdapters","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint16","name":"centrifugeId","type":"uint16"},{"internalType":"PoolId","name":"poolId","type":"uint64"},{"internalType":"bytes32","name":"manager","type":"bytes32"},{"internalType":"address","name":"refund","type":"address"}],"name":"sendSetRequestManager","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":"target","type":"bytes32"},{"internalType":"bytes","name":"payload","type":"bytes"},{"internalType":"uint128","name":"extraGasLimit","type":"uint128"},{"internalType":"address","name":"refund","type":"address"}],"name":"sendTrustedContractUpdate","outputs":[],"stateMutability":"payable","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":"bytes32","name":"sender","type":"bytes32"},{"internalType":"uint128","name":"extraGasLimit","type":"uint128"},{"internalType":"address","name":"refund","type":"address"}],"name":"sendUntrustedContractUpdate","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint16","name":"centrifugeId","type":"uint16"},{"internalType":"PoolId","name":"poolId","type":"uint64"},{"internalType":"bytes32","name":"who","type":"bytes32"},{"internalType":"bool","name":"canManage","type":"bool"},{"internalType":"address","name":"refund","type":"address"}],"name":"sendUpdateBalanceSheetManager","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint16","name":"centrifugeId","type":"uint16"},{"internalType":"PoolId","name":"poolId","type":"uint64"},{"internalType":"bytes32","name":"who","type":"bytes32"},{"internalType":"bool","name":"canManage","type":"bool"},{"internalType":"address","name":"refund","type":"address"}],"name":"sendUpdateGatewayManager","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"PoolId","name":"poolId","type":"uint64"},{"internalType":"ShareClassId","name":"scId","type":"bytes16"},{"internalType":"AssetId","name":"assetId","type":"uint128"},{"components":[{"internalType":"uint128","name":"netAmount","type":"uint128"},{"internalType":"bool","name":"isIncrease","type":"bool"},{"internalType":"bool","name":"isSnapshot","type":"bool"},{"internalType":"uint64","name":"nonce","type":"uint64"}],"internalType":"struct ISpokeMessageSender.UpdateData","name":"data","type":"tuple"},{"internalType":"D18","name":"pricePoolPerAsset","type":"uint128"},{"internalType":"uint128","name":"extraGasLimit","type":"uint128"},{"internalType":"address","name":"refund","type":"address"}],"name":"sendUpdateHoldingAmount","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":"bytes","name":"payload","type":"bytes"},{"internalType":"uint128","name":"extraGasLimit","type":"uint128"},{"internalType":"address","name":"refund","type":"address"}],"name":"sendUpdateRestriction","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":"hook","type":"bytes32"},{"internalType":"address","name":"refund","type":"address"}],"name":"sendUpdateShareHook","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"PoolId","name":"poolId","type":"uint64"},{"internalType":"ShareClassId","name":"scId","type":"bytes16"},{"components":[{"internalType":"uint128","name":"netAmount","type":"uint128"},{"internalType":"bool","name":"isIncrease","type":"bool"},{"internalType":"bool","name":"isSnapshot","type":"bool"},{"internalType":"uint64","name":"nonce","type":"uint64"}],"internalType":"struct ISpokeMessageSender.UpdateData","name":"data","type":"tuple"},{"internalType":"uint128","name":"extraGasLimit","type":"uint128"},{"internalType":"address","name":"refund","type":"address"}],"name":"sendUpdateShares","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":"bytes32","name":"vaultOrFactory","type":"bytes32"},{"internalType":"enum VaultUpdateKind","name":"kind","type":"uint8"},{"internalType":"uint128","name":"extraGasLimit","type":"uint128"},{"internalType":"address","name":"refund","type":"address"}],"name":"sendUpdateVault","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"spoke","outputs":[{"internalType":"contract ISpokeGatewayHandler","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokenRecoverer","outputs":[{"internalType":"contract ITokenRecoverer","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"vaultRegistry","outputs":[{"internalType":"contract IVaultRegistryGatewayHandler","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"wards","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}],"is_changed_bytecode":false,"is_partially_verified":true,"constructor_args":"00000000000000000000000000000000000000000000000000000000000000010000000000000000000000007ed48c31f2fdc40d37407cbabf0870b2b688368f00000000000000000000000019a524d03aa94ecee41a80341537bcfcb47d3172000000000000000000000000b3c086db30c1be6e40d8775607c3662ab160bda5"}