From 27bb97b3890ac88a7f031f617c253cc33b740e24 Mon Sep 17 00:00:00 2001 From: Kristijan Date: Tue, 25 Aug 2026 13:24:51 +0200 Subject: [PATCH 01/23] Restructure TP flow with onlyRouter access --- .../ccip/ccipsend_executor/contract.tolk | 34 + .../ccip/ccipsend_executor/errors.tolk | 1 + .../ccip/ccipsend_executor/messages.tolk | 5 +- contracts/contracts/ccip/pools/TokenPool.tolk | 15 +- .../ccip/pools/burn_mint/contract.tolk | 16 +- .../ccip/pools/burn_mint/storage.tolk | 6 +- .../ccip/pools/lib/token_pool/entrypoint.tolk | 167 +- .../ccip/pools/lib/token_pool/events.tolk | 8 - .../ccip/pools/lib/token_pool/messages.tolk | 17 +- .../ccip/pools/lib/token_pool/types.tolk | 13 +- .../ccip/pools/lock_release/contract.tolk | 16 +- .../ccip/pools/lock_release/storage.tolk | 4 +- .../pools/lock_release_lockbox/contract.tolk | 16 +- .../pools/lock_release_lockbox/storage.tolk | 4 +- contracts/contracts/ccip/router/contract.tolk | 122 +- contracts/contracts/ccip/router/errors.tolk | 1 + contracts/contracts/ccip/router/messages.tolk | 33 + .../ccip/test/tokenPool/contract.tolk | 60 + .../e2e/CCIPSendWithTokenTransfer.spec.ts | 27 +- contracts/tests/ccip/offramp/OffRamp.Setup.ts | 29 +- .../ccip/pools/BurnMintTokenPool.spec.ts | 28 +- .../pools/LockReleaseLockboxTokenPool.spec.ts | 49 +- .../ccip/pools/LockReleaseTokenPool.spec.ts | 46 +- .../pools/TokenPool.asyncHook.behavior.ts | 16 +- .../tests/ccip/pools/TokenPool.behavior.ts | 231 +- .../ccip/router/Router.ccipReceive.spec.ts | 24 + .../tests/ccip/router/Router.cursing.spec.ts | 93 +- .../wrappers/gen/ccip/CCIPSendExecutor.ts | 137 +- contracts/wrappers/gen/ccip/MockTokenPool.ts | 5178 +++++++++++++++++ contracts/wrappers/gen/ccip/Router.ts | 2837 +++++---- .../gen/ccip/pools/BurnMintTokenPool.ts | 299 +- .../ccip/pools/LockReleaseLockboxTokenPool.ts | 299 +- .../gen/ccip/pools/LockReleaseTokenPool.ts | 299 +- .../wrappers/gen/ccip/pools/TokenPool.ts | 319 +- 34 files changed, 7594 insertions(+), 2855 deletions(-) create mode 100644 contracts/contracts/ccip/test/tokenPool/contract.tolk create mode 100644 contracts/wrappers/gen/ccip/MockTokenPool.ts diff --git a/contracts/contracts/ccip/ccipsend_executor/contract.tolk b/contracts/contracts/ccip/ccipsend_executor/contract.tolk index 443fee641..8cb5fc139 100644 --- a/contracts/contracts/ccip/ccipsend_executor/contract.tolk +++ b/contracts/contracts/ccip/ccipsend_executor/contract.tolk @@ -81,6 +81,40 @@ fun onInternalMessage(in: InMessage) { assert(this.state.load().tokenPool == in.senderAddress, CCIPSendExecutor_Error.Unauthorized); this.onConfirmWithdraw(msg); } + // Structured pool failures can arrive either before custody withdrawal + // or while the withdrawal/finalization phase is in progress. + TokenPool_LockOrBurnFailure => { + val st = lazy CCIPSendExecutor_Data.fromCell(contract.getData()); + if (st.state is Cell) { + var this = CCIPSendExecutor.load(); + assert(this.state.load().tokenPool == in.senderAddress, CCIPSendExecutor_Error.Unauthorized); + this.exitWithError(msg.errorCode as uint256); + } else { + var this = CCIPSendExecutor.load(); + assert(this.state.load().tokenPool == in.senderAddress, CCIPSendExecutor_Error.Unauthorized); + this.exitWithError(msg.errorCode as uint256); + } + } + // Router policy rejection, a pre-admission pool bounce, or a bounced + // Router-wallet withdrawal is reported by the configured Router. + Router_TokenPoolLockOrBurnFailed => { + val st = lazy CCIPSendExecutor_Data.fromCell(contract.getData()); + if (st.state is Cell) { + var this = CCIPSendExecutor.load(); + val state = lazy this.state.load(); + val addresses = lazy this.addresses.load(); + assert(addresses.router == in.senderAddress, CCIPSendExecutor_Error.Unauthorized); + assert(state.tokenPool == msg.tokenPool, CCIPSendExecutor_Error.Unauthorized); + this.exitWithError(CCIPSendExecutor_Error.TokenPoolBounce as uint256); + } else { + var this = CCIPSendExecutor.load(); + val state = lazy this.state.load(); + val addresses = lazy this.addresses.load(); + assert(addresses.router == in.senderAddress, CCIPSendExecutor_Error.Unauthorized); + assert(state.tokenPool == msg.tokenPool, CCIPSendExecutor_Error.Unauthorized); + this.exitWithError(CCIPSendExecutor_Error.TokenPoolBounce as uint256); + } + } else => { assert (in.body.isEmpty()) throw 0xFFFF; }, diff --git a/contracts/contracts/ccip/ccipsend_executor/errors.tolk b/contracts/contracts/ccip/ccipsend_executor/errors.tolk index bf0e3dd02..1c7e76d21 100644 --- a/contracts/contracts/ccip/ccipsend_executor/errors.tolk +++ b/contracts/contracts/ccip/ccipsend_executor/errors.tolk @@ -8,4 +8,5 @@ enum CCIPSendExecutor_Error { InsufficientFee FeeQuoterBounce TokenNotEnabled + TokenPoolBounce } diff --git a/contracts/contracts/ccip/ccipsend_executor/messages.tolk b/contracts/contracts/ccip/ccipsend_executor/messages.tolk index 543cc6170..11988b275 100644 --- a/contracts/contracts/ccip/ccipsend_executor/messages.tolk +++ b/contracts/contracts/ccip/ccipsend_executor/messages.tolk @@ -1,5 +1,6 @@ import "../../lib/jetton/messages" +import "../router/messages" import "../onramp/messages" import "../fee_quoter/messages" import "../token_admin_registry_entry/messages" @@ -14,7 +15,9 @@ type CCIPSendExecutor_InMessage = | TokenAdminRegistryEntry_ReturnTokenInfo | ResponseWalletAddress | TokenPool_LockOrBurnWithdraw - | TokenPool_LockOrBurnFinished; + | TokenPool_LockOrBurnFinished + | TokenPool_LockOrBurnFailure + | Router_TokenPoolLockOrBurnFailed; type FeeQuoter_MessageValidated_Any = FeeQuoter_MessageValidated type FeeQuoter_MessageValidationFailed_Any = FeeQuoter_MessageValidationFailed diff --git a/contracts/contracts/ccip/pools/TokenPool.tolk b/contracts/contracts/ccip/pools/TokenPool.tolk index 0ec3d63da..3605e0ff3 100644 --- a/contracts/contracts/ccip/pools/TokenPool.tolk +++ b/contracts/contracts/ccip/pools/TokenPool.tolk @@ -52,16 +52,8 @@ get fun isSupportedChain(remoteChainSelector: uint64): bool { throw 0xFFFF; } -get fun onRamp(remoteChainSelector: uint64): address? { - throw 0xFFFF; -} - -get fun offRamp(remoteChainSelector: uint64): address? { - throw 0xFFFF; -} - /// Matches Go binding GetRMNProxy (Name: "getRMNProxy"). -get fun getRMNProxy(): address { +get fun getRMNProxy(): address? { throw 0xFFFF; } @@ -133,11 +125,6 @@ get fun getAdminConfig(): TokenPool_AdminConfig { throw 0xFFFF; } -/// Matches Go binding GetMirroredPolicy (Name: "getMirroredPolicy"). -get fun getMirroredPolicy(): TokenPool_MirroredPolicy { - throw 0xFFFF; -} - /// Matches Go binding GetRemoteChainConfig (Name: "getRemoteChainConfig"). get fun getRemoteChainConfig(remoteChainSelector: uint64): TokenPool_RemoteChainConfig? { throw 0xFFFF; diff --git a/contracts/contracts/ccip/pools/burn_mint/contract.tolk b/contracts/contracts/ccip/pools/burn_mint/contract.tolk index b67064fc4..ab26e5632 100644 --- a/contracts/contracts/ccip/pools/burn_mint/contract.tolk +++ b/contracts/contracts/ccip/pools/burn_mint/contract.tolk @@ -430,8 +430,6 @@ fun loadPool(st: Storage): TokenPool { data: st.poolData.load(), context: st, hooks: TokenPool_Hooks { - ensureOutboundAccess: null, - ensureInboundAccess: null, ensureNotCursed: null, onLockOrBurn: null, validateLockOrBurn: null, @@ -471,22 +469,12 @@ get fun isSupportedChain(remoteChainSelector: uint64): bool { return Storage.load().poolData.load().remoteChainConfigs.get(remoteChainSelector).isFound; } -get fun onRamp(remoteChainSelector: uint64): address? { - val entry = Storage.load().poolData.load().mirroredPolicy.load().onRamps.get(remoteChainSelector); - return entry.isFound ? entry.loadValue() : null; -} - -get fun offRamp(remoteChainSelector: uint64): address? { - val entry = Storage.load().poolData.load().mirroredPolicy.load().offRamps.get(remoteChainSelector); - return entry.isFound ? entry.loadValue() : null; -} - -get fun getRMNProxy(): address { +get fun getRMNProxy(): address? { return Storage.load().poolData.load().adminConfig.load().rmnProxy; } get fun verifyNotCursed(subject: uint128): bool { - return !Storage.load().poolData.load().mirroredPolicy.load().cursedSubjects.isCursed(subject); + return !Storage.load().poolData.load().localPolicy.load().cursedSubjects.isCursed(subject); } get fun owner(): address { diff --git a/contracts/contracts/ccip/pools/burn_mint/storage.tolk b/contracts/contracts/ccip/pools/burn_mint/storage.tolk index 17d4b4aa5..f3e0ca061 100644 --- a/contracts/contracts/ccip/pools/burn_mint/storage.tolk +++ b/contracts/contracts/ccip/pools/burn_mint/storage.tolk @@ -41,9 +41,7 @@ fun Storage.init(config: BurnMintTokenPool_InitConfig): Storage { advancedPoolHooks: createAddressNone() as address, deployableCode: config.deployableCode, }.toCell(), - mirroredPolicy: TokenPool_MirroredPolicy { - onRamps: createEmptyMap(), - offRamps: createEmptyMap(), + localPolicy: TokenPool_LocalPolicy { cursedSubjects: CursedSubjects { data: createEmptyMap(), }, @@ -54,4 +52,4 @@ fun Storage.init(config: BurnMintTokenPool_InitConfig): Storage { }.toCell(), offRampAccountCode: config.offRampAccountCode, }; -} \ No newline at end of file +} diff --git a/contracts/contracts/ccip/pools/lib/token_pool/entrypoint.tolk b/contracts/contracts/ccip/pools/lib/token_pool/entrypoint.tolk index ae53c9b09..281bbefe9 100644 --- a/contracts/contracts/ccip/pools/lib/token_pool/entrypoint.tolk +++ b/contracts/contracts/ccip/pools/lib/token_pool/entrypoint.tolk @@ -49,7 +49,7 @@ struct TokenPool { struct TokenPool_AdminConfig { ownable: Cell; - rmnProxy: address; + rmnProxy: address?; dynamicConfig: Cell; /// The pool's Jetton identity (master + wallet code). Single source of truth used to /// derive and authenticate the pool's own wallet. @@ -70,7 +70,7 @@ struct TokenPool_AdminConfig { struct TokenPool_Data { adminConfig: Cell; - mirroredPolicy: Cell; + localPolicy: Cell; tokenDecimals: uint8; remoteChainConfigs: map = []; tokenTransferFeeConfigs: map = []; @@ -90,20 +90,19 @@ fun TokenPool_Data.storeAsContractData(self) { /// Optional extension points wired by concrete pools (e.g. lock/release) to customize the base /// TokenPool behavior. Each field is the implementation of the corresponding hook, or `null` to -/// use the base behavior. Pools share a generic `T` as the first arg, their per-call `context` (nullable). +/// use the base behavior. Pools share a generic `T` = their per-call `context`, which flows +/// through every hook (`T?` when a hook may be invoked with no context, e.g. getters). +/// +/// There are three hook families, mirroring the three flows: +/// - **Guards**: curse checks — override to add custom policy. +/// - **Operation hooks**: entry + validation + (pre/post)flight for the LockOrBurn and +/// ReleaseOrMint flows. Hooks returning a `TokenPool_*Prepared` may also signal `wait` to defer +/// execution to the on-chain (async) `advancedPoolHooks` contract. +/// - **Continuation hooks**: run after Jetton custody is settled, letting the pool track binding +/// side effects (e.g. lock/release accrues fees only on confirmed deposit). +/// +/// The fee-withdrawal hook `onWithdrawFeeTokens` is a fourth, standalone extension point. struct TokenPool_Hooks { - /// Outbound (LockOrBurn) access guard. - /// @param sender The msg.sender requesting the outbound transfer. - /// @param remoteChainSelector The destination lane; must be supported. - /// @dev Base behavior: requires `sender` to be the configured OnRamp for the lane. - ensureOutboundAccess: ((T?, address, uint64) -> void)?; - - /// Inbound (ReleaseOrMint) access guard. - /// @param sender The msg.sender requesting the inbound transfer. - /// @param remoteChainSelector The source lane; must be supported. - /// @dev Base behavior: requires `sender` to be the configured OffRamp for the lane. - ensureInboundAccess: ((T?, address, uint64) -> void)?; - /// RMN curse guard for a remote lane. /// @param remoteChainSelector The remote lane to check for a curse. /// @dev Base behavior: reverts if the lane's cursed subjects mark it cursed by RMN. @@ -251,7 +250,7 @@ fun TokenPool.getTokenDecimals(self): uint8 { } @inline -fun TokenPool.getRmnProxy(self): address { +fun TokenPool.getRmnProxy(self): address? { val ac = lazy self.data.adminConfig.load(); return ac.rmnProxy; } @@ -278,21 +277,9 @@ fun TokenPool.getAdvancedPoolHooks(self): address? { return self.data.adminConfig.load().advancedPoolHooks; } -@inline -fun TokenPool.getOnRamp(self, remoteChainSelector: uint64): address? { - val entry = self.data.mirroredPolicy.load().onRamps.get(remoteChainSelector); - return entry.isFound ? entry.loadValue() : null; -} - -@inline -fun TokenPool.getOffRamp(self, remoteChainSelector: uint64): address? { - val entry = self.data.mirroredPolicy.load().offRamps.get(remoteChainSelector); - return entry.isFound ? entry.loadValue() : null; -} - @inline fun TokenPool.verifyNotCursed(self, subject: uint128): bool { - return !self.data.mirroredPolicy.load().cursedSubjects.isCursed(subject); + return !self.data.localPolicy.load().cursedSubjects.isCursed(subject); } /// Checks whether a remote chain is supported in the token pool. @@ -361,6 +348,7 @@ fun TokenPool.setDynamicConfig( assert(!isZeroAddress(router), TokenPool_Error.ZeroAddressInvalid); // feeAdmin: `null` means owner-only; the zero address is never a valid fee admin. assert(feeAdmin == null || !isZeroAddress(feeAdmin!), TokenPool_Error.ZeroAddressInvalid); + adminConfig.dynamicConfig = TokenPool_DynamicConfig { router, rateLimitAdmin, @@ -631,62 +619,20 @@ fun TokenPool.applyChainUpdates( reply.send(SEND_MODE_CARRY_ALL_REMAINING_MESSAGE_VALUE); } -fun TokenPool.applyRampAccessUpdates( - mutate self, - sender: address, - queryId: uint64, - updates: SnakedCell, -) { - val adminConfig = self.data.adminConfig.load(); - adminConfig.ownable.load().requireOwner(sender); - - var mirroredPolicy = self.data.mirroredPolicy.load(); - var iter = updates.iter(); - while (!iter.empty()) { - val update = iter.next(); - - if (update.onRamp != null) { - mirroredPolicy.onRamps.set(update.remoteChainSelector, update.onRamp!); - } else { - mirroredPolicy.onRamps.delete(update.remoteChainSelector); - } - - if (update.offRamp != null) { - mirroredPolicy.offRamps.set(update.remoteChainSelector, update.offRamp!); - } else { - mirroredPolicy.offRamps.delete(update.remoteChainSelector); - } - - emit(TOPIC_TOKEN_POOL_RAMP_ACCESS_UPDATED, TokenPool_RampAccessUpdated { - remoteChainSelector: update.remoteChainSelector, - onRamp: update.onRamp, - offRamp: update.offRamp, - }); - } - - self.data.mirroredPolicy = mirroredPolicy.toCell(); - - val reply = createMessage({ - bounce: BounceMode.NoBounce, - value: 0, - dest: sender, - body: TokenPool_RampAccessUpdatesApplied { queryId }, - }); - reply.send(SEND_MODE_CARRY_ALL_REMAINING_MESSAGE_VALUE); -} - +// TODO: make rmnProxy immutable (same as EVM) fun TokenPool.setRMNProxy( mutate self, sender: address, queryId: uint64, - rmnProxy: address + rmnProxy: address? ) { var adminConfig = self.data.adminConfig.load(); adminConfig.ownable.load().requireOwner(sender); // EVM makes `rmnProxy` immutable (constructor-checked); TON makes it mutable here, so the // zero-address guard must live on the setter. See AUDIT_REPORT.md L-11. - assert(!isZeroAddress(rmnProxy), TokenPool_Error.ZeroAddressInvalid); + // `null` is a legal value: it unsets the proxy; the zero address is never valid. + assert(rmnProxy == null || !isZeroAddress(rmnProxy!), TokenPool_Error.ZeroAddressInvalid); adminConfig.rmnProxy = rmnProxy; self.data.adminConfig = adminConfig.toCell(); @@ -708,9 +654,9 @@ fun TokenPool.setCursedSubjects( ) { self.onlyOwnerOrRMNProxy(sender); - var mirroredPolicy = self.data.mirroredPolicy.load(); - mirroredPolicy.cursedSubjects = cursedSubjects; - self.data.mirroredPolicy = mirroredPolicy.toCell(); + var localPolicy = self.data.localPolicy.load(); + localPolicy.cursedSubjects = cursedSubjects; + self.data.localPolicy = localPolicy.toCell(); val reply = createMessage({ bounce: BounceMode.NoBounce, @@ -789,9 +735,6 @@ fun TokenPool.onInternalMessage(mutate self, msgSender: address, msgValue: co TokenPool_ApplyTokenTransferFeeConfigUpdates => { self.applyTokenTransferFeeConfigUpdates(msgSender, msg.queryId, msg.updates, msg.disableChainSelectors); } - TokenPool_UpdateRampAccess => { - self.applyRampAccessUpdates(msgSender, msg.queryId, msg.updates); - } TokenPool_SetRMNProxy => { self.setRMNProxy(msgSender, msg.queryId, msg.rmnProxy); } @@ -832,6 +775,7 @@ fun TokenPool.onPreflightCheckFinished( sender: address, msg: TokenPool_PreflightCheckFinished, ): void { + self.onlyAdvancedPoolHooks(sender); val fwdp = msg.forwardPayload.load(); val originalSender = fwdp.originalSender; val requestMsg = lazy fwdp.requestMsg.load(); @@ -848,6 +792,7 @@ fun TokenPool.onPreflightCheckFailed( sender: address, msg: TokenPool_PreflightCheckFailed, ): void { + self.onlyAdvancedPoolHooks(sender); val fwdp = msg.forwardPayload.load(); // Refund outbound rate limit that was consumed before the hook check. @@ -864,6 +809,7 @@ fun TokenPool.onPostflightCheckFinished( sender: address, msg: TokenPool_PostflightCheckFinished, ): void { + self.onlyAdvancedPoolHooks(sender); val fwdp = msg.forwardPayload.load(); val originalSender = fwdp.originalSender; val requestMsg = lazy fwdp.requestMsg.load(); @@ -880,6 +826,7 @@ fun TokenPool.onPostflightCheckFailed( sender: address, msg: TokenPool_PostflightCheckFailed, ): void { + self.onlyAdvancedPoolHooks(sender); val fwdp = msg.forwardPayload.load(); // Refund inbound rate limit that was consumed before the hook check. @@ -1436,7 +1383,6 @@ fun TokenPool.validateLockOrBurn( assert(self.isSupportedToken(details.localToken), TokenPool_Error.InvalidToken); self.requireSupportedChain(details.remoteChainSelector); self.ensureNotCursed(details.remoteChainSelector); - self.ensureOutboundAccess(sender, details.remoteChainSelector); val feeAmount = self.getFeeAmount(request.transfer, msg.requestedFinalityConfig); val destTokenAmount = details.amount - feeAmount; @@ -1475,6 +1421,10 @@ fun TokenPool.onLockOrBurn( sender: address, msg: TokenPool_LockOrBurn, ): void { + // Authenticate before invoking an overridable operation hook so a custom + // pool cannot accidentally bypass the Router boundary. + self.onlyRouter(sender); + if (self.hooks != null && self.hooks.onLockOrBurn != null) { self.context = self.hooks.onLockOrBurn(self.context!, sender, msg); @@ -1822,7 +1772,6 @@ fun TokenPool.validateReleaseOrMint( assert(self.isSupportedToken(details.localToken), TokenPool_Error.InvalidToken); self.requireSupportedChain(details.remoteChainSelector); self.ensureNotCursed(details.remoteChainSelector); - self.ensureInboundAccess(sender, details.remoteChainSelector); assert(self.isRemotePool(details.remoteChainSelector, request.sourcePoolAddress), TokenPool_Error.InvalidRemotePoolForChain); val remoteDecimals = self.parseRemoteDecimals(request.sourcePoolData); @@ -1862,6 +1811,10 @@ fun TokenPool.onReleaseOrMint( sender: address, msg: TokenPool_ReleaseOrMint, ): void { + // Authenticate before invoking an overridable operation hook so a custom + // pool cannot accidentally bypass the Router boundary. + self.onlyRouter(sender); + if (self.hooks != null && self.hooks.onReleaseOrMint != null) { self.context = self.hooks.onReleaseOrMint(self.context!, msg); @@ -2003,38 +1956,38 @@ fun TokenPool.onlyOwnerOrRMNProxy(self, sender: address) { val adminConfig = self.data.adminConfig.load(); val ownable = adminConfig.ownable.load(); assert( - sender == ownable.owner || sender == adminConfig.rmnProxy, + sender == ownable.owner || (adminConfig.rmnProxy != null && sender == adminConfig.rmnProxy!), TokenPool_Error.Unauthorized ); } -fun TokenPool.ensureNotCursed(self, remoteChainSelector: uint64) { - if (self.hooks != null && self.hooks.ensureNotCursed != null) { - return self.hooks.ensureNotCursed(self.context, remoteChainSelector); - } - assert(self.verifyNotCursed(remoteChainSelector as uint128), TokenPool_Error.CursedByRMN); -} - -fun TokenPool.ensureOutboundAccess(self, sender: address, remoteChainSelector: uint64) { - if (self.hooks != null && self.hooks.ensureOutboundAccess != null) { - self.hooks.ensureOutboundAccess(self.context, sender, remoteChainSelector); - - return; - } - - val onRamp = self.getOnRamp(remoteChainSelector); - assert(onRamp != null && onRamp! == sender, TokenPool_Error.Unauthorized); +/// Restricts CCIP token operations to the configured Router. +/// +/// This check intentionally runs in the message dispatcher, before any pool +/// hook can handle LockOrBurn or ReleaseOrMint. The Router owns ramp +/// authentication and applies its own RMN policy; the pool independently +/// applies its local cursed-subject policy during request validation. +fun TokenPool.onlyRouter(self, sender: address) { + val router = self.data.adminConfig.load().dynamicConfig.load().router; + assert(sender == router, TokenPool_Error.Unauthorized); +} + +/// Authenticates asynchronous pool-hook continuations. Without this boundary, +/// an arbitrary sender could forge a success/failure continuation after the +/// Router-authenticated operation returned to the async flow. +fun TokenPool.onlyAdvancedPoolHooks(self, sender: address) { + val hooks = self.data.adminConfig.load().advancedPoolHooks; + assert(hooks != null && sender == hooks!, TokenPool_Error.Unauthorized); } -fun TokenPool.ensureInboundAccess(self, sender: address, remoteChainSelector: uint64) { - if (self.hooks != null && self.hooks.ensureInboundAccess != null) { - self.hooks.ensureInboundAccess(self.context, sender, remoteChainSelector); +fun TokenPool.ensureNotCursed(self, remoteChainSelector: uint64) { + // The owner-selected local RMN policy is mandatory. Hooks may impose an + // additional restriction, but cannot bypass this policy domain. + assert(self.verifyNotCursed(remoteChainSelector as uint128), TokenPool_Error.CursedByRMN); - return; + if (self.hooks != null && self.hooks.ensureNotCursed != null) { + return self.hooks.ensureNotCursed(self.context, remoteChainSelector); } - - val offRamp = self.getOffRamp(remoteChainSelector); - assert(offRamp != null && offRamp! == sender, TokenPool_Error.Unauthorized); } fun TokenPool.preflightCheck( diff --git a/contracts/contracts/ccip/pools/lib/token_pool/events.tolk b/contracts/contracts/ccip/pools/lib/token_pool/events.tolk index fa18e78f3..d71d63f32 100644 --- a/contracts/contracts/ccip/pools/lib/token_pool/events.tolk +++ b/contracts/contracts/ccip/pools/lib/token_pool/events.tolk @@ -10,7 +10,6 @@ const TOPIC_TOKEN_POOL_CHAIN_REMOVED = "TokenPool_ChainRemoved".crc32(); const TOPIC_TOKEN_POOL_REMOTE_POOL_ADDED = "TokenPool_RemotePoolAdded".crc32(); const TOPIC_TOKEN_POOL_REMOTE_POOL_REMOVED = "TokenPool_RemotePoolRemoved".crc32(); const TOPIC_TOKEN_POOL_DYNAMIC_CONFIG_SET = "TokenPool_DynamicConfigSet".crc32(); -const TOPIC_TOKEN_POOL_RAMP_ACCESS_UPDATED = "TokenPool_RampAccessUpdated".crc32(); const TOPIC_TOKEN_POOL_FINALITY_CONFIG_SET = "TokenPool_FinalityConfigSet".crc32(); const TOPIC_TOKEN_POOL_RATE_LIMIT_CONFIGURED = "TokenPool_RateLimitConfigured".crc32(); const TOPIC_TOKEN_POOL_FEE_CONFIG_UPDATED = "TokenPool_TokenTransferFeeConfigUpdated".crc32(); @@ -155,17 +154,10 @@ struct TokenPool_RateLimitConfigured { // ); // event AdvancedPoolHooksUpdated(IAdvancedPoolHooks oldHook, IAdvancedPoolHooks newHook); -struct TokenPool_RampAccessUpdated { - remoteChainSelector: uint64; - onRamp: address? = null; - offRamp: address? = null; -} - type TokenPool_Events = | TokenPool_ChainAdded | TokenPool_ChainRemoved | TokenPool_RateLimitConfigured - | TokenPool_RampAccessUpdated | TokenPool_TokenTransferFeeConfigUpdated | TokenPool_TokenTransferFeeConfigDeleted | TokenPool_OutboundRateLimitConsumed diff --git a/contracts/contracts/ccip/pools/lib/token_pool/messages.tolk b/contracts/contracts/ccip/pools/lib/token_pool/messages.tolk index cc7481d18..1d3708456 100644 --- a/contracts/contracts/ccip/pools/lib/token_pool/messages.tolk +++ b/contracts/contracts/ccip/pools/lib/token_pool/messages.tolk @@ -2,6 +2,7 @@ import "../../../../lib/jetton/messages" import "../../../../lib/funding/jetton_withdrawable" import "../../../../lib/utils" + import "../../../common/types" import "../../../rmn_remote/lib" @@ -79,15 +80,10 @@ struct (0x30a1d1f7) TokenPool_ApplyTokenTransferFeeConfigUpdates { disableChainSelectors: SnakedCell; } -struct (0xe30764be) TokenPool_UpdateRampAccess { - queryId: uint64; - updates: SnakedCell; -} - /// Sets the RMN proxy address, a role which is responsible for updating the cursed subjects list. struct (0x9929b642) TokenPool_SetRMNProxy { queryId: uint64; - rmnProxy: address; + rmnProxy: address?; } struct (0x9da4da09) TokenPool_SetCursedSubjects { @@ -277,7 +273,6 @@ type TokenPool_InMessage = | TokenPool_SetAllowedDepositNamespaces | TokenPool_SetRateLimitConfig | TokenPool_ApplyTokenTransferFeeConfigUpdates - | TokenPool_UpdateRampAccess | TokenPool_SetRMNProxy | TokenPool_SetCursedSubjects | JettonWithdrawable_Withdraw; @@ -346,7 +341,7 @@ struct (0xdd7b0c71) TokenPool_RateLimitConfiguredNotification { /// Replied on `TokenPool_SetRMNProxy` to confirm tx and return excess to sender. struct (0xe5d08b2e) TokenPool_RMNProxySet { queryId: uint64; - rmnProxy: address; + rmnProxy: address?; } /// Replied on `TokenPool_SetCursedSubjects` to confirm tx and return excess to sender. @@ -360,11 +355,6 @@ struct (0xad7833d7) TokenPool_ChainUpdatesApplied { queryId: uint64; } -/// Replied on `TokenPool_UpdateRampAccess` to confirm tx and return excess to sender. -struct (0xd7f5c563) TokenPool_RampAccessUpdatesApplied { - queryId: uint64; -} - /// Replied on `TokenPool_ApplyTokenTransferFeeConfigUpdates` to confirm tx and return excess to sender. struct (0x28cbcc64) TokenPool_FeeConfigApplied { queryId: uint64; @@ -396,5 +386,4 @@ type TokenPool_OutMessage = | TokenPool_CursedSubjectsSet | TokenPool_AdvancedPoolHooksSet | TokenPool_ChainUpdatesApplied - | TokenPool_RampAccessUpdatesApplied | TokenPool_FeeConfigApplied; diff --git a/contracts/contracts/ccip/pools/lib/token_pool/types.tolk b/contracts/contracts/ccip/pools/lib/token_pool/types.tolk index dbfcfdacd..a7e46749f 100644 --- a/contracts/contracts/ccip/pools/lib/token_pool/types.tolk +++ b/contracts/contracts/ccip/pools/lib/token_pool/types.tolk @@ -33,18 +33,13 @@ struct TokenPool_DynamicConfig { allowedDepositNamespaces: map = []; } -struct TokenPool_MirroredPolicy { - onRamps: map = []; - offRamps: map = []; +struct TokenPool_LocalPolicy { + // Independently managed pool-local RMN policy. This is intentionally not a + // mirror of the Router's cursed subjects: the pool owner may configure a + // distinct RMN proxy, or disable proxy updates by setting it to addr_none. cursedSubjects: CursedSubjects; } -struct TokenPool_RampUpdate { - remoteChainSelector: uint64; - onRamp: address? = null; - offRamp: address? = null; -} - struct TokenPool_RateLimiterPair { outbound: Cell; inbound: Cell; diff --git a/contracts/contracts/ccip/pools/lock_release/contract.tolk b/contracts/contracts/ccip/pools/lock_release/contract.tolk index 8524ef00f..342627186 100644 --- a/contracts/contracts/ccip/pools/lock_release/contract.tolk +++ b/contracts/contracts/ccip/pools/lock_release/contract.tolk @@ -338,8 +338,6 @@ fun loadPool(st: Storage): TokenPool { data: st.poolData.load(), context: st, hooks: TokenPool_Hooks { - ensureOutboundAccess: null, - ensureInboundAccess: null, ensureNotCursed: null, onLockOrBurn: null, validateLockOrBurn: null, @@ -437,22 +435,12 @@ get fun isSupportedChain(remoteChainSelector: uint64): bool { return Storage.load().poolData.load().remoteChainConfigs.get(remoteChainSelector).isFound; } -get fun onRamp(remoteChainSelector: uint64): address? { - val entry = Storage.load().poolData.load().mirroredPolicy.load().onRamps.get(remoteChainSelector); - return entry.isFound ? entry.loadValue() : null; -} - -get fun offRamp(remoteChainSelector: uint64): address? { - val entry = Storage.load().poolData.load().mirroredPolicy.load().offRamps.get(remoteChainSelector); - return entry.isFound ? entry.loadValue() : null; -} - -get fun getRMNProxy(): address { +get fun getRMNProxy(): address? { return Storage.load().poolData.load().adminConfig.load().rmnProxy; } get fun verifyNotCursed(subject: uint128): bool { - return !Storage.load().poolData.load().mirroredPolicy.load().cursedSubjects.isCursed(subject); + return !Storage.load().poolData.load().localPolicy.load().cursedSubjects.isCursed(subject); } get fun owner(): address { diff --git a/contracts/contracts/ccip/pools/lock_release/storage.tolk b/contracts/contracts/ccip/pools/lock_release/storage.tolk index 8516ca837..acc2ad36a 100644 --- a/contracts/contracts/ccip/pools/lock_release/storage.tolk +++ b/contracts/contracts/ccip/pools/lock_release/storage.tolk @@ -44,9 +44,7 @@ fun Storage.init(config: LockReleaseTokenPool_InitConfig): Storage { advancedPoolHooks: createAddressNone() as address, deployableCode: config.deployableCode, }.toCell(), - mirroredPolicy: TokenPool_MirroredPolicy { - onRamps: createEmptyMap(), - offRamps: createEmptyMap(), + localPolicy: TokenPool_LocalPolicy { cursedSubjects: CursedSubjects { data: createEmptyMap(), }, diff --git a/contracts/contracts/ccip/pools/lock_release_lockbox/contract.tolk b/contracts/contracts/ccip/pools/lock_release_lockbox/contract.tolk index c713eb1d9..e0208302b 100644 --- a/contracts/contracts/ccip/pools/lock_release_lockbox/contract.tolk +++ b/contracts/contracts/ccip/pools/lock_release_lockbox/contract.tolk @@ -451,8 +451,6 @@ fun loadPool(st: Storage): TokenPool { data: st.poolData.load(), context: st, hooks: TokenPool_Hooks { - ensureOutboundAccess: null, - ensureInboundAccess: null, ensureNotCursed: null, onLockOrBurn: null, validateLockOrBurn: null, @@ -498,22 +496,12 @@ get fun isSupportedChain(remoteChainSelector: uint64): bool { return Storage.load().poolData.load().remoteChainConfigs.get(remoteChainSelector).isFound; } -get fun onRamp(remoteChainSelector: uint64): address? { - val entry = Storage.load().poolData.load().mirroredPolicy.load().onRamps.get(remoteChainSelector); - return entry.isFound ? entry.loadValue() : null; -} - -get fun offRamp(remoteChainSelector: uint64): address? { - val entry = Storage.load().poolData.load().mirroredPolicy.load().offRamps.get(remoteChainSelector); - return entry.isFound ? entry.loadValue() : null; -} - -get fun getRMNProxy(): address { +get fun getRMNProxy(): address? { return Storage.load().poolData.load().adminConfig.load().rmnProxy; } get fun verifyNotCursed(subject: uint128): bool { - return !Storage.load().poolData.load().mirroredPolicy.load().cursedSubjects.isCursed(subject); + return !Storage.load().poolData.load().localPolicy.load().cursedSubjects.isCursed(subject); } get fun owner(): address { diff --git a/contracts/contracts/ccip/pools/lock_release_lockbox/storage.tolk b/contracts/contracts/ccip/pools/lock_release_lockbox/storage.tolk index ad9cc2d3f..c699a6dca 100644 --- a/contracts/contracts/ccip/pools/lock_release_lockbox/storage.tolk +++ b/contracts/contracts/ccip/pools/lock_release_lockbox/storage.tolk @@ -44,9 +44,7 @@ fun Storage.init(config: LockReleaseLockboxTokenPool_InitConfig): Storage { advancedPoolHooks: createAddressNone() as address, deployableCode: config.deployableCode, }.toCell(), - mirroredPolicy: TokenPool_MirroredPolicy { - onRamps: createEmptyMap(), - offRamps: createEmptyMap(), + localPolicy: TokenPool_LocalPolicy { cursedSubjects: CursedSubjects { data: createEmptyMap(), }, diff --git a/contracts/contracts/ccip/router/contract.tolk b/contracts/contracts/ccip/router/contract.tolk index eb432493b..2a08045b4 100644 --- a/contracts/contracts/ccip/router/contract.tolk +++ b/contracts/contracts/ccip/router/contract.tolk @@ -11,21 +11,20 @@ import "../../lib/receiver/messages" import "../../lib/jetton/jetton_client" import "../rmn_remote/lib.tolk" +import "../common/types" import "../onramp/messages" import "../onramp/types" import "../offramp/messages" import "../offramp/types" import "../rmn_remote/lib" import "../pools/lib/token_pool/messages" +import "../pools/lib/token_pool/types" import "types" import "messages" import "storage" import "errors" import "events" -import "../pools/lib/token_pool/types" -import "../common/types" -import "../../lib/jetton/jetton_client" tolk 1.4.1 @@ -90,6 +89,7 @@ fun onInternalMessage(in: InMessage) { val message = lazy msg.message.load(); val expectedOffRamp = st.offRamps.mustGet(message.sourceChainSelector, Router_Error.SourceChainNotEnabled); assert(in.senderAddress == expectedOffRamp, Router_Error.SenderIsNotOffRamp); + assertNotCursed(st, message.sourceChainSelector); onRouteMessage(msg, msg.message); } // Sender must be OnRamp @@ -175,8 +175,35 @@ fun onInternalMessage(in: InMessage) { val request = lazy msg.request.load(); val details = lazy request.transfer.details.load(); assertSenderIsOnRamp(st, details.remoteChainSelector, in.senderAddress); + if (isCursed(st, details.remoteChainSelector)) { + return sendLockOrBurnRelayFailure( + msg.executorAddress, + msg.queryID, + msg.tokenPool, + Router_Error.SubjectCursed as int32, + ); + } onLockOrBurn(msg); } + // Sender must be the OffRamp registered for the request's source chain. + Router_RelayReleaseOrMint => { + val st = lazy Storage.load(); + val expectedOffRamp = st.offRamps.mustGet(msg.sourceChainSelector, Router_Error.SourceChainNotEnabled); + assert(in.senderAddress == expectedOffRamp, Router_Error.SenderIsNotOffRamp); + + val request = lazy msg.request.load(); + val details = lazy request.transfer.details.load(); + assert(details.remoteChainSelector == msg.sourceChainSelector, Router_Error.SourceChainSelectorMismatch); + if (isCursed(st, msg.sourceChainSelector)) { + return sendReleaseOrMintRelayFailure( + msg.replyTo, + msg.queryID, + msg.tokenPool, + Router_Error.SubjectCursed as int32, + ); + } + onRelayReleaseOrMint(msg); + } // Sender must be a Jetton Wallet owned by the Router TransferNotificationForRecipient => { // TODO we can't just throw errors in the Router on JettonTransferNotification - this will burn the tokens. @@ -224,6 +251,34 @@ fun onInternalMessage(in: InMessage) { } fun onBouncedMessage(in: InMessageBounced) { + if (in.bouncedBody.preloadUint(32) == 0xfffffffe) { + val rich = lazy RichBounceBody.fromSlice(in.bouncedBody); + val richMsg = lazy Router_RichBouncedMessage.fromCell(rich.originalBody); + match (richMsg) { + TokenPool_LockOrBurn => { + if (richMsg.replyTo != null) { + sendLockOrBurnRelayFailure( + richMsg.replyTo!, + richMsg.queryId, + in.senderAddress, + rich.exitCode, + ); + } + } + TokenPool_ReleaseOrMint => { + if (richMsg.replyTo != null) { + sendReleaseOrMintRelayFailure( + richMsg.replyTo!, + richMsg.queryId, + in.senderAddress, + rich.exitCode, + ); + } + } + } + return; + } + val msg = lazy Router_BouncedMessage.fromSlice(in.bouncedBody.skipBouncedPrefix()); match (msg) { // We are lazy matching and only accessing the first element of the struct. @@ -702,7 +757,7 @@ withdraw path should go through the executor - so the TP needs to withdraw -> ex */ fun onLockOrBurn(msg: Router_LockOrBurn) { val tokenPoolLockOrBurn = createMessage({ - bounce: true, + bounce: BounceMode.RichBounce, value: 0, dest: msg.tokenPool, body: TokenPool_LockOrBurn { @@ -714,7 +769,22 @@ fun onLockOrBurn(msg: Router_LockOrBurn) { } }); tokenPoolLockOrBurn.send(SEND_MODE_CARRY_ALL_REMAINING_MESSAGE_VALUE); -} +} + +fun onRelayReleaseOrMint(msg: Router_RelayReleaseOrMint) { + val tokenPoolReleaseOrMint = createMessage({ + bounce: BounceMode.RichBounce, + value: 0, + dest: msg.tokenPool, + body: TokenPool_ReleaseOrMint { + queryId: msg.queryID, + request: msg.request, + requestedFinalityConfig: msg.requestedFinalityConfig, + replyTo: msg.replyTo, + }, + }); + tokenPoolReleaseOrMint.send(SEND_MODE_CARRY_ALL_REMAINING_MESSAGE_VALUE); +} /* Handles contract upgrade requests using the Upgradeable pattern. Invokes the @@ -732,6 +802,48 @@ fun assertSenderIsOnRamp(st: Storage, destChainSelector: uint64, sender: address assert (sender == onRampAddress) throw Router_Error.NotOnRamp; } +/// Enforces the Router's authoritative RMN policy for a remote chain. +/// +/// Token pools can additionally enforce an independently managed local curse +/// policy. A transfer is admitted only when both policy domains allow it. +fun assertNotCursed(st: Storage, remoteChainSelector: uint64) { + assert(!isCursed(st, remoteChainSelector), Router_Error.SubjectCursed); +} + +fun isCursed(st: Storage, remoteChainSelector: uint64): bool { + return st.rmnRemote.load().cursedSubjects.isCursed(remoteChainSelector as uint128); +} + +fun sendLockOrBurnRelayFailure( + executor: address, + queryID: uint64, + tokenPool: address, + exitCode: int32, +) { + val failed = createMessage({ + bounce: BounceMode.NoBounce, + value: 0, + dest: executor, + body: Router_TokenPoolLockOrBurnFailed { queryID, tokenPool, exitCode }, + }); + failed.send(SEND_MODE_CARRY_ALL_REMAINING_MESSAGE_VALUE); +} + +fun sendReleaseOrMintRelayFailure( + executor: address, + queryID: uint64, + tokenPool: address, + exitCode: int32, +) { + val failed = createMessage({ + bounce: BounceMode.NoBounce, + value: 0, + dest: executor, + body: Router_TokenPoolReleaseOrMintFailed { queryID, tokenPool, exitCode }, + }); + failed.send(SEND_MODE_CARRY_ALL_REMAINING_MESSAGE_VALUE); +} + @method_id(1000) fun migrate(storage: cell, version: slice): cell { requireSupportedVersion(version); diff --git a/contracts/contracts/ccip/router/errors.tolk b/contracts/contracts/ccip/router/errors.tolk index 1cfdee07f..bad6b3d2c 100644 --- a/contracts/contracts/ccip/router/errors.tolk +++ b/contracts/contracts/ccip/router/errors.tolk @@ -16,4 +16,5 @@ enum Router_Error { JettonTransferNotificationWithoutForwardPayload TokenAmountMismatch ForwardPayloadIsNotCCIPSend + SourceChainSelectorMismatch } diff --git a/contracts/contracts/ccip/router/messages.tolk b/contracts/contracts/ccip/router/messages.tolk index 091d3291b..053e4cdb5 100644 --- a/contracts/contracts/ccip/router/messages.tolk +++ b/contracts/contracts/ccip/router/messages.tolk @@ -30,6 +30,7 @@ type Router_InMsg = | Router_MessageSent | Router_MessageRejected | Router_LockOrBurn + | Router_RelayReleaseOrMint | Router_RMNOwnableMessage | TransferNotificationForRecipient; @@ -42,6 +43,10 @@ type Router_BouncedMessage = | OffRamp_CCIPReceiveConfirm | OffRamp_CCIPReceiveBounced; +type Router_RichBouncedMessage = + | TokenPool_LockOrBurn + | TokenPool_ReleaseOrMint; + // update multiple chain selectors in batch to the same onramp/offramp address struct (0x7db6745d) Router_ApplyRampUpdates { queryId: uint64; @@ -148,6 +153,18 @@ struct (0x6f2d00df) Router_LockOrBurn { executorAddress: address, } +/// Relays an inbound token operation from the registered OffRamp to the pool. +/// The Router binds the authenticated OffRamp selector to the selector encoded +/// in the pool request and applies its own RMN policy before dispatch. +struct (0xb19862a3) Router_RelayReleaseOrMint { + queryID: uint64; + sourceChainSelector: uint64; + tokenPool: address; + request: Cell; + requestedFinalityConfig: uint32; + replyTo: address; +} + struct Router_GetValidatedFeeContext { routerContext: address; // sender userContext: RemainingBitsOrRef, @@ -175,6 +192,22 @@ struct (0xec23c562) Router_MessageValidationFailed { context: RemainingBitsOrRef } +/// Canonical Router failure returned when a LockOrBurn request bounced before +/// the token pool admitted it. +struct (0xb76e3a84) Router_TokenPoolLockOrBurnFailed { + queryID: uint64; + tokenPool: address; + exitCode: int32; +} + +/// Canonical Router failure returned when a ReleaseOrMint request bounced +/// before the token pool admitted it. +struct (0xb980cb4e) Router_TokenPoolReleaseOrMintFailed { + queryID: uint64; + tokenPool: address; + exitCode: int32; +} + // Costs associated with Router operations struct Router_Costs {} diff --git a/contracts/contracts/ccip/test/tokenPool/contract.tolk b/contracts/contracts/ccip/test/tokenPool/contract.tolk new file mode 100644 index 000000000..e8023baca --- /dev/null +++ b/contracts/contracts/ccip/test/tokenPool/contract.tolk @@ -0,0 +1,60 @@ +import "../../pools/lib/token_pool/entrypoint" +import "../../pools/lib/token_pool/messages" + + +contract MockTokenPool { + author: "SmartContract Chainlink Limited SEZC" + version: "1.6.1" + description: "link.chain.ton.ccip.test.TokenPool" + storage: Storage + incomingMessages: TokenPool_InMessage +} + +const CONTRACT_VERSION = "0.0.1".literalSlice(); + +struct Storage { + poolData: Cell +} + +fun Storage.load(): Storage { + return Storage.fromCell(contract.getData()); +} + +fun Storage.store(self) { + contract.setData(self.toCell()); +} + +fun loadPool(st: Storage): TokenPool { + return TokenPool { + data: st.poolData.load(), + context: st, + hooks: TokenPool_Hooks { + ensureNotCursed: null, + onLockOrBurn: null, + validateLockOrBurn: null, + preflightCheck: null, + onLockOrBurnTransfer: null, + onLockOrBurnTransferContinue: null, + onReleaseOrMint: null, + validateReleaseOrMint: null, + postflightCheck: null, + onReleaseOrMintContinue: null, + onWithdrawFeeTokens: null, + }, + }; +} + +fun onInternalMessage(in: InMessage) { + var st = Storage.load(); + var pool = loadPool(st); + val handled = pool.onInternalMessage(in.senderAddress, in.valueCoins, in.body); + if (handled) { + st = pool.context != null ? pool.context! : st; + st.poolData = pool.data.toCell(); + st.store(); + return; + } + + assert(in.body.isEmpty()) throw 0xFFFF; +} + diff --git a/contracts/tests/ccip/e2e/CCIPSendWithTokenTransfer.spec.ts b/contracts/tests/ccip/e2e/CCIPSendWithTokenTransfer.spec.ts index 1a3927d74..0c98226ab 100644 --- a/contracts/tests/ccip/e2e/CCIPSendWithTokenTransfer.spec.ts +++ b/contracts/tests/ccip/e2e/CCIPSendWithTokenTransfer.spec.ts @@ -170,9 +170,7 @@ describe('CCIPSend with token transfer (e2e)', () => { }), advancedPoolHooks: null, }), - mirroredPolicy: tp.TokenPool_MirroredPolicy.create({ - onRamps: new Map(), - offRamps: new Map(), + localPolicy: tp.TokenPool_LocalPolicy.create({ cursedSubjects: tp.CursedSubjects.create({ data: new Set(), }), @@ -229,29 +227,6 @@ describe('CCIPSend with token transfer (e2e)', () => { success: true, }) - // Register the Router as the authorized caller for lock/burn on this chain. - // The Router forwards Router_LockOrBurn on behalf of the OnRamp, so it's the - // sender the pool sees for TokenPool_LockOrBurn. - const rampAccessResult = await tokenPool.sendTokenPoolUpdateRampAccess( - deployer.getSender(), - toNano('0.05'), - { - updates: [ - tp.TokenPool_RampUpdate.create({ - remoteChainSelector: DestChainSelector, - onRamp: router.address, - offRamp: null, - }), - ], - }, - ) - - expect(rampAccessResult.transactions).toHaveTransaction({ - from: deployer.address, - to: tokenPool.address, - success: true, - }) - const registrationResult = await tokenAdminRegistry.sendTokenAdminRegistryRegisterToken( deployer.getSender(), toNano('0.2'), diff --git a/contracts/tests/ccip/offramp/OffRamp.Setup.ts b/contracts/tests/ccip/offramp/OffRamp.Setup.ts index 892eed52f..52c5d4341 100644 --- a/contracts/tests/ccip/offramp/OffRamp.Setup.ts +++ b/contracts/tests/ccip/offramp/OffRamp.Setup.ts @@ -901,12 +901,8 @@ export class OffRampWithTokenPoolTestSetup extends OffRampTestSetup { }), allowedFinalityConfig: 0n, }), - mirroredPolicy: tp.TokenPool_MirroredPolicy.create({ - onRamps: new Map(), - offRamps: new Map(), - cursedSubjects: tp.CursedSubjects.create({ - data: new Set(), - }), + localPolicy: tp.TokenPool_LocalPolicy.create({ + cursedSubjects: tp.CursedSubjects.create({ data: new Set() }), }), tokenDecimals, remoteChainConfigs: new Map(), @@ -960,27 +956,6 @@ export class OffRampWithTokenPoolTestSetup extends OffRampTestSetup { success: true, }) - // Register the OffRamp as the authorized inbound caller (offRamp) for the chain. - const rampAccessResult = await tokenPool.sendTokenPoolUpdateRampAccess( - this.deployer.getSender(), - toNano('0.05'), - { - updates: [ - tp.TokenPool_RampUpdate.create({ - remoteChainSelector, - onRamp: null, - offRamp: this.offRamp.address, - }), - ], - }, - ) - - expect(rampAccessResult.transactions).toHaveTransaction({ - from: this.deployer.address, - to: tokenPool.address, - success: true, - }) - return tokenPool } diff --git a/contracts/tests/ccip/pools/BurnMintTokenPool.spec.ts b/contracts/tests/ccip/pools/BurnMintTokenPool.spec.ts index 1694da739..48a6d3b77 100644 --- a/contracts/tests/ccip/pools/BurnMintTokenPool.spec.ts +++ b/contracts/tests/ccip/pools/BurnMintTokenPool.spec.ts @@ -11,7 +11,6 @@ import { TokenPool, TokenPool_Data, TokenPool_AdminConfig, - TokenPool_RampUpdate, TokenPool_RateLimitConfigPair, TokenPool_ChainUpdate, TokenPool_LockOrBurn, @@ -23,7 +22,7 @@ import { TokenPool_LockOrBurnOutV1, TokenPool_ReleaseOrMintInV1, TokenPool_ReleaseOrMintFinished, - TokenPool_MirroredPolicy, + TokenPool_LocalPolicy, TokenPool_DynamicConfig, TokenPool_Transfer, TokenPool_TransferDetails, @@ -127,9 +126,7 @@ describe('BurnMintTokenPool', () => { allowedFinalityConfig: 0n, advancedPoolHooks: null, }), - mirroredPolicy: TokenPool_MirroredPolicy.create({ - onRamps: new Map(), - offRamps: new Map(), + localPolicy: TokenPool_LocalPolicy.create({ cursedSubjects: CursedSubjects.create({ data: new Set(), }), @@ -184,17 +181,6 @@ describe('BurnMintTokenPool', () => { }) } - await burnMintPool.sendTokenPoolUpdateRampAccess(deployer.getSender(), toNano('0.2'), { - queryId: 2n, - updates: [ - TokenPool_RampUpdate.create({ - remoteChainSelector, - onRamp: deployer.address, - offRamp: offRamp.address, - }), - ], - }) - // Mint user-side test balance before handing minter admin to the pool. const mintToOnRamp = await cctMinterRuntime.sendMint(deployer.getSender(), { value: toNano('1'), @@ -267,6 +253,7 @@ describe('BurnMintTokenPool', () => { runTokenPoolBehaviorTests('BurnMintTokenPool', async () => ({ pool, + blockchain, deployer, offRamp, altOffRamp: deployer, @@ -310,6 +297,7 @@ describe('BurnMintTokenPool', () => { return { pool, + blockchain, deployer, offRamp, unauthorized, @@ -757,7 +745,7 @@ describe('BurnMintTokenPool', () => { it('mints tokens on releaseOrMint path and finalizes through the executor notification', async () => { const result = await burnMintPool.sendTokenPoolReleaseOrMint( - offRamp.getSender(), + deployer.getSender(), toNano('0.6'), { queryId: 22n, @@ -782,7 +770,7 @@ describe('BurnMintTokenPool', () => { ) expect(result.transactions).toHaveTransaction({ - from: offRamp.address, + from: deployer.address, to: burnMintPool.address, success: true, }) @@ -808,7 +796,7 @@ describe('BurnMintTokenPool', () => { it('mints on releaseOrMint with null replyTo without emitting response message', async () => { const result = await burnMintPool.sendTokenPoolReleaseOrMint( - offRamp.getSender(), + deployer.getSender(), toNano('0.6'), { queryId: 305n, @@ -833,7 +821,7 @@ describe('BurnMintTokenPool', () => { ) expect(result.transactions).toHaveTransaction({ - from: offRamp.address, + from: deployer.address, to: burnMintPool.address, success: true, }) diff --git a/contracts/tests/ccip/pools/LockReleaseLockboxTokenPool.spec.ts b/contracts/tests/ccip/pools/LockReleaseLockboxTokenPool.spec.ts index 59727a099..bdcf75429 100644 --- a/contracts/tests/ccip/pools/LockReleaseLockboxTokenPool.spec.ts +++ b/contracts/tests/ccip/pools/LockReleaseLockboxTokenPool.spec.ts @@ -10,7 +10,7 @@ import { TokenPool_Data, TokenPool_AdminConfig, TokenPool_DynamicConfig, - TokenPool_MirroredPolicy, + TokenPool_LocalPolicy, TokenPool_ReleaseOrMintFinished, TokenPool_LockOrBurn, TokenPool_LockOrBurnForwardPayload, @@ -19,7 +19,6 @@ import { TokenPool_LockOrBurnInV1, TokenPool_ReleaseOrMintInV1, TokenPool_RateLimitConfigPair, - TokenPool_RampUpdate, TokenPool_ChainUpdate, Ownable2Step, TokenPool_TransferDetails, @@ -163,9 +162,7 @@ describe('LockReleaseLockboxTokenPool', () => { allowedFinalityConfig: 0n, advancedPoolHooks: null, }), - mirroredPolicy: TokenPool_MirroredPolicy.create({ - onRamps: new Map(), - offRamps: new Map(), + localPolicy: TokenPool_LocalPolicy.create({ cursedSubjects: CursedSubjects.create({ data: new Set(), }), @@ -242,28 +239,6 @@ describe('LockReleaseLockboxTokenPool', () => { success: true, }) - // Update ramp access (deployer is the on-ramp) - const updateRampAccess = await lockReleaseLockboxPool.sendTokenPoolUpdateRampAccess( - deployer.getSender(), - toNano('0.2'), - { - queryId: 2n, - updates: [ - TokenPool_RampUpdate.create({ - remoteChainSelector, - onRamp: deployer.address, - offRamp: offRamp.address, - }), - ], - }, - ) - - expect(updateRampAccess.transactions).toHaveTransaction({ - from: deployer.address, - to: lockReleaseLockboxPool.address, - success: true, - }) - // Mint tokens to deployer's wallet (acts as on-ramp) const mintToDeployer = await jettonMinter.sendMint(deployer.getSender(), { value: toNano('1'), @@ -368,6 +343,7 @@ describe('LockReleaseLockboxTokenPool', () => { 'LockReleaseLockboxTokenPool', async () => ({ pool, + blockchain, deployer, offRamp, unauthorized: recipient, @@ -413,6 +389,7 @@ describe('LockReleaseLockboxTokenPool', () => { return { pool, + blockchain, deployer, offRamp, unauthorized: recipient, @@ -709,7 +686,7 @@ describe('LockReleaseLockboxTokenPool', () => { }) const result = await lockReleaseLockboxPool.sendTokenPoolReleaseOrMint( - offRamp.getSender(), + deployer.getSender(), toNano('0.5'), { queryId: 200n, @@ -735,7 +712,7 @@ describe('LockReleaseLockboxTokenPool', () => { // Pool processes the release request expect(result.transactions).toHaveTransaction({ - from: offRamp.address, + from: deployer.address, to: lockReleaseLockboxPool.address, success: true, }) @@ -751,7 +728,7 @@ describe('LockReleaseLockboxTokenPool', () => { it('should reject release when requested amount exceeds lockbox liquidity', async () => { const result = await lockReleaseLockboxPool.sendTokenPoolReleaseOrMint( - offRamp.getSender(), + deployer.getSender(), toNano('0.4'), { queryId: 201n, @@ -776,7 +753,7 @@ describe('LockReleaseLockboxTokenPool', () => { ) expect(result.transactions).toHaveTransaction({ - from: offRamp.address, + from: deployer.address, to: lockReleaseLockboxPool.address, success: false, }) @@ -884,7 +861,7 @@ describe('LockReleaseLockboxTokenPool', () => { // Trigger release from off-ramp const result = await lockReleaseLockboxPool.sendTokenPoolReleaseOrMint( - offRamp.getSender(), + deployer.getSender(), toNano('1'), { queryId: 400n, @@ -910,7 +887,7 @@ describe('LockReleaseLockboxTokenPool', () => { // Pool processes the release request expect(result.transactions).toHaveTransaction({ - from: offRamp.address, + from: deployer.address, to: lockReleaseLockboxPool.address, success: true, }) @@ -950,7 +927,7 @@ describe('LockReleaseLockboxTokenPool', () => { // Trigger release request for more than the lockbox holds const result = await lockReleaseLockboxPool.sendTokenPoolReleaseOrMint( - offRamp.getSender(), + deployer.getSender(), toNano('0.5'), { queryId: 401n, @@ -976,7 +953,7 @@ describe('LockReleaseLockboxTokenPool', () => { // The release request should fail or bounce expect(result.transactions).toHaveTransaction({ - from: offRamp.address, + from: deployer.address, to: lockReleaseLockboxPool.address, success: false, }) @@ -986,7 +963,7 @@ describe('LockReleaseLockboxTokenPool', () => { }) describe('cursed state', () => { - it('should mirror cursed state locally and block release while cursed', async () => { + it('should apply local cursed state and block release while cursed', async () => { const curseUpdate = await lockReleaseLockboxPool.sendTokenPoolSetCursedSubjects( deployer.getSender(), toNano('0.2'), diff --git a/contracts/tests/ccip/pools/LockReleaseTokenPool.spec.ts b/contracts/tests/ccip/pools/LockReleaseTokenPool.spec.ts index a71d96ba3..aa51bbc73 100644 --- a/contracts/tests/ccip/pools/LockReleaseTokenPool.spec.ts +++ b/contracts/tests/ccip/pools/LockReleaseTokenPool.spec.ts @@ -11,7 +11,7 @@ import { TokenPool_Data, TokenPool_AdminConfig, TokenPool_DynamicConfig, - TokenPool_MirroredPolicy, + TokenPool_LocalPolicy, TokenPool_ReleaseOrMintFailure, TokenPool_ReleaseOrMintFinished, TokenPool_LockOrBurn, @@ -22,7 +22,6 @@ import { TokenPool_LockOrBurnPrepared, TokenPool_ReleaseOrMintInV1, TokenPool_RateLimitConfigPair, - TokenPool_RampUpdate, TokenPool_ChainUpdate, Ownable2Step, TokenPool_TransferDetails, @@ -131,9 +130,7 @@ describe('LockReleaseTokenPool', () => { allowedFinalityConfig: 0n, advancedPoolHooks: null, }), - mirroredPolicy: TokenPool_MirroredPolicy.create({ - onRamps: new Map(), - offRamps: new Map(), + localPolicy: TokenPool_LocalPolicy.create({ cursedSubjects: CursedSubjects.create({ data: new Set(), }), @@ -187,27 +184,6 @@ describe('LockReleaseTokenPool', () => { success: true, }) - const updateRampAccess = await lockReleasePool.sendTokenPoolUpdateRampAccess( - deployer.getSender(), - toNano('0.2'), - { - queryId: 2n, - updates: [ - TokenPool_RampUpdate.create({ - remoteChainSelector, - onRamp: deployer.address, - offRamp: offRamp.address, - }), - ], - }, - ) - - expect(updateRampAccess.transactions).toHaveTransaction({ - from: deployer.address, - to: lockReleasePool.address, - success: true, - }) - const mintToOnRamp = await jettonMinter.sendMint(deployer.getSender(), { value: toNano('1'), message: { @@ -252,6 +228,7 @@ describe('LockReleaseTokenPool', () => { 'LockReleaseTokenPool', async () => ({ pool, + blockchain, deployer, offRamp, unauthorized: recipient, @@ -297,6 +274,7 @@ describe('LockReleaseTokenPool', () => { return { pool, + blockchain, deployer, offRamp, unauthorized: recipient, @@ -686,7 +664,7 @@ describe('LockReleaseTokenPool', () => { it('reverts releaseOrMint when requested amount exceeds pool liquidity', async () => { const result = await lockReleasePool.sendTokenPoolReleaseOrMint( - offRamp.getSender(), + deployer.getSender(), toNano('0.4'), { queryId: 46n, @@ -711,7 +689,7 @@ describe('LockReleaseTokenPool', () => { ) expect(result.transactions).toHaveTransaction({ - from: offRamp.address, + from: deployer.address, to: lockReleasePool.address, success: false, }) @@ -726,7 +704,7 @@ describe('LockReleaseTokenPool', () => { expect(before.inbound.tokens).toEqual(toNano('100')) const result = await lockReleasePool.sendTokenPoolReleaseOrMint( - offRamp.getSender(), + deployer.getSender(), toNano('0.4'), { queryId: 77n, @@ -865,7 +843,7 @@ describe('LockReleaseTokenPool', () => { }) const result = await lockReleasePool.sendTokenPoolReleaseOrMint( - offRamp.getSender(), + deployer.getSender(), toNano('0.4'), { queryId: 22n, @@ -890,7 +868,7 @@ describe('LockReleaseTokenPool', () => { ) expect(result.transactions).toHaveTransaction({ - from: offRamp.address, + from: deployer.address, to: lockReleasePool.address, success: true, }) @@ -942,7 +920,7 @@ describe('LockReleaseTokenPool', () => { }) const result = await lockReleasePool.sendTokenPoolReleaseOrMint( - offRamp.getSender(), + deployer.getSender(), toNano('0.4'), { queryId: 223n, @@ -1007,7 +985,7 @@ describe('LockReleaseTokenPool', () => { expect(await lockReleasePool.getVerifyNotCursed(remoteChainSelector)).toBe(false) const result = await lockReleasePool.sendTokenPoolReleaseOrMint( - offRamp.getSender(), + deployer.getSender(), toNano('0.3'), { queryId: 33n, @@ -1032,7 +1010,7 @@ describe('LockReleaseTokenPool', () => { ) expect(result.transactions).toHaveTransaction({ - from: offRamp.address, + from: deployer.address, to: lockReleasePool.address, success: false, }) diff --git a/contracts/tests/ccip/pools/TokenPool.asyncHook.behavior.ts b/contracts/tests/ccip/pools/TokenPool.asyncHook.behavior.ts index 673effb80..8c942df81 100644 --- a/contracts/tests/ccip/pools/TokenPool.asyncHook.behavior.ts +++ b/contracts/tests/ccip/pools/TokenPool.asyncHook.behavior.ts @@ -100,7 +100,7 @@ export function runTokenPoolAsyncHookBehaviorTests( }), }) const fwdp = TokenPool_ReleaseOrMintForwardPayload.create({ - originalSender: ctx.offRamp.address, + originalSender: ctx.deployer.address, requestMsg: TokenPool_ReleaseOrMint.create({ queryId: 0n, request, @@ -208,7 +208,7 @@ export function runTokenPoolAsyncHookBehaviorTests( const request = releaseRequest(ctx) const result = await ctx.pool.sendTokenPoolReleaseOrMint( - ctx.offRamp.getSender(), + ctx.deployer.getSender(), toNano('1'), { queryId: 2n, @@ -241,7 +241,7 @@ export function runTokenPoolAsyncHookBehaviorTests( const request = releaseRequest(ctx) const result = await ctx.pool.sendTokenPoolReleaseOrMint( - ctx.offRamp.getSender(), + ctx.deployer.getSender(), toNano('1'), { queryId: 1n, @@ -285,7 +285,7 @@ export function runTokenPoolAsyncHookBehaviorTests( const request = releaseRequest(ctx) const result = await ctx.pool.sendTokenPoolReleaseOrMint( - ctx.offRamp.getSender(), + ctx.deployer.getSender(), toNano('1'), { queryId: 3n, @@ -345,7 +345,7 @@ export function runTokenPoolAsyncHookBehaviorTests( const request = releaseRequest(ctx) const result = await ctx.pool.sendTokenPoolReleaseOrMint( - ctx.offRamp.getSender(), + ctx.deployer.getSender(), toNano('1'), { queryId: 100n, @@ -356,7 +356,7 @@ export function runTokenPoolAsyncHookBehaviorTests( ) expect(result.transactions).toHaveTransaction({ - from: ctx.offRamp.address, + from: ctx.deployer.address, to: ctx.pool.address, success: true, }) @@ -421,7 +421,7 @@ export function runTokenPoolAsyncHookBehaviorTests( // Even → success const requestEven = releaseRequest(ctx) const evenResult = await ctx.pool.sendTokenPoolReleaseOrMint( - ctx.offRamp.getSender(), + ctx.deployer.getSender(), toNano('1'), { queryId: 6n, @@ -440,7 +440,7 @@ export function runTokenPoolAsyncHookBehaviorTests( // Odd → failure const requestOdd = releaseRequest(ctx) const oddResult = await ctx.pool.sendTokenPoolReleaseOrMint( - ctx.offRamp.getSender(), + ctx.deployer.getSender(), toNano('1'), { queryId: 7n, diff --git a/contracts/tests/ccip/pools/TokenPool.behavior.ts b/contracts/tests/ccip/pools/TokenPool.behavior.ts index 68923d923..da4649710 100644 --- a/contracts/tests/ccip/pools/TokenPool.behavior.ts +++ b/contracts/tests/ccip/pools/TokenPool.behavior.ts @@ -1,12 +1,11 @@ import '@ton/test-utils' -import { SandboxContract, TreasuryContract } from '@ton/sandbox' +import { Blockchain, SandboxContract, TreasuryContract } from '@ton/sandbox' import { Address, beginCell, Cell, toNano } from '@ton/core' import { CrossChainAddress, CursedSubjects, TokenPool, TokenPool_ChainUpdate, - TokenPool_RampUpdate, TokenPool_RateLimitConfigPair, TokenPool_RateLimitConfigArgs, TokenPool_ReleaseOrMint, @@ -21,6 +20,7 @@ import { export type TokenPoolBehaviorContext = { pool: SandboxContract + blockchain: Blockchain deployer: SandboxContract offRamp: SandboxContract unauthorized: SandboxContract @@ -71,15 +71,13 @@ export function runTokenPoolBehaviorTests( } describe(`${name} TokenPool behavior`, () => { - it('mirrors ramp access and supported chain state after setup', async () => { + it('reports the configured chain as supported after setup', async () => { const ctx = await setup() expect(await ctx.pool.getIsSupportedChain(ctx.remoteChainSelector)).toBe(true) - expect(await ctx.pool.getOnRamp(ctx.remoteChainSelector)).not.toBeNull() - expect(await ctx.pool.getOffRamp(ctx.remoteChainSelector)).toEqualAddress(ctx.offRamp.address) }) - it('reverts releaseOrMint when caller is not configured off-ramp', async () => { + it('reverts releaseOrMint when caller is not the configured Router', async () => { const ctx = await setup() const result = await ctx.pool.sendTokenPoolReleaseOrMint( @@ -97,6 +95,29 @@ export function runTokenPoolBehaviorTests( from: ctx.unauthorized.address, to: ctx.pool.address, success: false, + exitCode: 14910, // TokenPool_Error.Unauthorized + }) + }) + + it('does not authorize an OffRamp to call the pool directly', async () => { + const ctx = await setup() + + const result = await ctx.pool.sendTokenPoolReleaseOrMint( + ctx.offRamp.getSender(), + toNano('0.3'), + { + queryId: 900n, + request: releaseRequest(ctx), + requestedFinalityConfig: 0n, + replyTo: ctx.deployer.address, + }, + ) + + expect(result.transactions).toHaveTransaction({ + from: ctx.offRamp.address, + to: ctx.pool.address, + success: false, + exitCode: 14910, // TokenPool_Error.Unauthorized }) }) @@ -135,7 +156,7 @@ export function runTokenPoolBehaviorTests( expect(await ctx.pool.getVerifyNotCursed(ctx.remoteChainSelector)).toBe(false) const result = await ctx.pool.sendTokenPoolReleaseOrMint( - ctx.offRamp.getSender(), + ctx.deployer.getSender(), toNano('0.3'), { queryId: 902n, @@ -146,7 +167,7 @@ export function runTokenPoolBehaviorTests( ) expect(result.transactions).toHaveTransaction({ - from: ctx.offRamp.address, + from: ctx.deployer.address, to: ctx.pool.address, success: false, }) @@ -184,7 +205,7 @@ export function runTokenPoolBehaviorTests( // First release consumes the single inbound token and admits. const first = await ctx.pool.sendTokenPoolReleaseOrMint( - ctx.offRamp.getSender(), + ctx.deployer.getSender(), toNano('0.3'), { queryId: 931n, @@ -194,14 +215,14 @@ export function runTokenPoolBehaviorTests( }, ) expect(first.transactions).toHaveTransaction({ - from: ctx.offRamp.address, + from: ctx.deployer.address, to: ctx.pool.address, success: true, }) // Second release of the same amount must be rejected (bucket has no refill, rate=0). const second = await ctx.pool.sendTokenPoolReleaseOrMint( - ctx.offRamp.getSender(), + ctx.deployer.getSender(), toNano('0.3'), { queryId: 932n, @@ -211,19 +232,12 @@ export function runTokenPoolBehaviorTests( }, ) expect(second.transactions).toHaveTransaction({ - from: ctx.offRamp.address, + from: ctx.deployer.address, to: ctx.pool.address, success: false, }) }) - it('returns null ramps for unknown chain', async () => { - const ctx = await setup() - const unknownChainSelector = ctx.remoteChainSelector + 1n - expect(await ctx.pool.getOnRamp(unknownChainSelector)).toBeNull() - expect(await ctx.pool.getOffRamp(unknownChainSelector)).toBeNull() - }) - it('returns unsupported for unknown chain', async () => { const ctx = await setup() const unknownChainSelector = ctx.remoteChainSelector + 1n @@ -249,30 +263,6 @@ export function runTokenPoolBehaviorTests( }) }) - it('rejects updateRampAccess from non-owner', async () => { - const ctx = await setup() - const result = await ctx.pool.sendTokenPoolUpdateRampAccess( - ctx.unauthorized.getSender(), - toNano('0.2'), - { - queryId: 904n, - updates: [ - TokenPool_RampUpdate.create({ - remoteChainSelector: ctx.remoteChainSelector, - onRamp: ctx.onRampAddress, - offRamp: ctx.unauthorized.address, - }), - ], - }, - ) - - expect(result.transactions).toHaveTransaction({ - from: ctx.unauthorized.address, - to: ctx.pool.address, - success: false, - }) - }) - it('rejects cursed-subject updates from non-rmn sender', async () => { const ctx = await setup() const result = await ctx.pool.sendTokenPoolSetCursedSubjects( @@ -306,6 +296,40 @@ export function runTokenPoolBehaviorTests( expect(await ctx.pool.getVerifyNotCursed(ctx.remoteChainSelector)).toBe(true) }) + it('allows the owner to disable RMN proxy updates with addr_none', async () => { + const ctx = await setup() + + await ctx.pool.sendTokenPoolSetRMNProxy(ctx.deployer.getSender(), toNano('0.2'), { + queryId: 903n, + rmnProxy: ctx.unauthorized.address, + }) + + const disable = await ctx.pool.sendTokenPoolSetRMNProxy( + ctx.deployer.getSender(), + toNano('0.2'), + { queryId: 904n, rmnProxy: null }, + ) + expect(disable.transactions).toHaveTransaction({ + from: ctx.deployer.address, + to: ctx.pool.address, + success: true, + }) + + const update = await ctx.pool.sendTokenPoolSetCursedSubjects( + ctx.unauthorized.getSender(), + toNano('0.2'), + { + queryId: 905n, + cursedSubjects: CursedSubjects.create({ data: new Set([ctx.remoteChainSelector]) }), + }, + ) + expect(update.transactions).toHaveTransaction({ + from: ctx.unauthorized.address, + to: ctx.pool.address, + success: false, + }) + }) + it('removes configured chain via applyChainUpdates', async () => { const ctx = await setup() const result = await ctx.pool.sendTokenPoolApplyChainUpdates( @@ -335,7 +359,7 @@ export function runTokenPoolBehaviorTests( }) const result = await ctx.pool.sendTokenPoolReleaseOrMint( - ctx.offRamp.getSender(), + ctx.deployer.getSender(), toNano('0.3'), { queryId: 907n, @@ -346,7 +370,7 @@ export function runTokenPoolBehaviorTests( ) expect(result.transactions).toHaveTransaction({ - from: ctx.offRamp.address, + from: ctx.deployer.address, to: ctx.pool.address, success: false, }) @@ -371,64 +395,6 @@ export function runTokenPoolBehaviorTests( }) }) - it('can replace off-ramp mapping via updateRampAccess', async () => { - const ctx = await setup() - const result = await ctx.pool.sendTokenPoolUpdateRampAccess( - ctx.deployer.getSender(), - toNano('0.2'), - { - queryId: 909n, - updates: [ - TokenPool_RampUpdate.create({ - remoteChainSelector: ctx.remoteChainSelector, - onRamp: ctx.onRampAddress, - offRamp: ctx.unauthorized.address, - }), - ], - }, - ) - - expect(result.transactions).toHaveTransaction({ - from: ctx.deployer.address, - to: ctx.pool.address, - success: true, - }) - expect(await ctx.pool.getOffRamp(ctx.remoteChainSelector)).toEqualAddress( - ctx.unauthorized.address, - ) - }) - - it('rejects old off-ramp sender after remapping off-ramp', async () => { - const ctx = await setup() - await ctx.pool.sendTokenPoolUpdateRampAccess(ctx.deployer.getSender(), toNano('0.2'), { - queryId: 910n, - updates: [ - TokenPool_RampUpdate.create({ - remoteChainSelector: ctx.remoteChainSelector, - onRamp: ctx.onRampAddress, - offRamp: ctx.unauthorized.address, - }), - ], - }) - - const result = await ctx.pool.sendTokenPoolReleaseOrMint( - ctx.offRamp.getSender(), - toNano('0.3'), - { - queryId: 911n, - request: releaseRequest(ctx), - requestedFinalityConfig: 0n, - replyTo: ctx.deployer.address, - }, - ) - - expect(result.transactions).toHaveTransaction({ - from: ctx.offRamp.address, - to: ctx.pool.address, - success: false, - }) - }) - it('rejects releaseOrMint when source pool is not configured', async () => { const ctx = await setup() const wrongSourcePoolAddress = beginCell() @@ -437,7 +403,7 @@ export function runTokenPoolBehaviorTests( .endCell() .beginParse() const result = await ctx.pool.sendTokenPoolReleaseOrMint( - ctx.offRamp.getSender(), + ctx.deployer.getSender(), toNano('0.3'), { queryId: 912n, @@ -448,7 +414,7 @@ export function runTokenPoolBehaviorTests( ) expect(result.transactions).toHaveTransaction({ - from: ctx.offRamp.address, + from: ctx.deployer.address, to: ctx.pool.address, success: false, }) @@ -458,7 +424,7 @@ export function runTokenPoolBehaviorTests( const ctx = await setup() const wrongLocalToken = ctx.deployer.address const result = await ctx.pool.sendTokenPoolReleaseOrMint( - ctx.offRamp.getSender(), + ctx.deployer.getSender(), toNano('0.3'), { queryId: 913n, @@ -480,54 +446,7 @@ export function runTokenPoolBehaviorTests( ) expect(result.transactions).toHaveTransaction({ - from: ctx.offRamp.address, - to: ctx.pool.address, - success: false, - }) - }) - - it('clears existing off-ramp when update passes null off-ramp', async () => { - const ctx = await setup() - await ctx.pool.sendTokenPoolUpdateRampAccess(ctx.deployer.getSender(), toNano('0.2'), { - queryId: 914n, - updates: [ - TokenPool_RampUpdate.create({ - remoteChainSelector: ctx.remoteChainSelector, - onRamp: ctx.onRampAddress, - offRamp: null, - }), - ], - }) - - expect(await ctx.pool.getOffRamp(ctx.remoteChainSelector)).toBeNull() - }) - - it('rejects existing off-ramp sender after null off-ramp update', async () => { - const ctx = await setup() - await ctx.pool.sendTokenPoolUpdateRampAccess(ctx.deployer.getSender(), toNano('0.2'), { - queryId: 915n, - updates: [ - TokenPool_RampUpdate.create({ - remoteChainSelector: ctx.remoteChainSelector, - onRamp: ctx.onRampAddress, - offRamp: null, - }), - ], - }) - - const result = await ctx.pool.sendTokenPoolReleaseOrMint( - ctx.offRamp.getSender(), - toNano('0.3'), - { - queryId: 916n, - request: releaseRequest(ctx), - requestedFinalityConfig: 0n, - replyTo: ctx.deployer.address, - }, - ) - - expect(result.transactions).toHaveTransaction({ - from: ctx.offRamp.address, + from: ctx.deployer.address, to: ctx.pool.address, success: false, }) @@ -602,12 +521,12 @@ export function runTokenPoolBehaviorTests( } const first = await ctx.pool.sendTokenPoolReleaseOrMint( - ctx.offRamp.getSender(), + ctx.deployer.getSender(), toNano('0.6'), repeatedRequest, ) const second = await ctx.pool.sendTokenPoolReleaseOrMint( - ctx.offRamp.getSender(), + ctx.deployer.getSender(), toNano('0.6'), repeatedRequest, ) diff --git a/contracts/tests/ccip/router/Router.ccipReceive.spec.ts b/contracts/tests/ccip/router/Router.ccipReceive.spec.ts index 7c888bbf8..3f5424729 100644 --- a/contracts/tests/ccip/router/Router.ccipReceive.spec.ts +++ b/contracts/tests/ccip/router/Router.ccipReceive.spec.ts @@ -120,6 +120,30 @@ describe('Router', () => { }) }) + it('should reject routeMessage while the source chain is cursed', async () => { + await router.sendRouterRMNRemoteCurse(deployer.getSender(), toNano('1'), { + queryId: 4n, + subjects: [any2tvmMessage.sourceChainSelector], + }) + + const result = await router.sendRouterRouteMessage(offRamp.getSender(), toNano('1'), { + message: any2tvmMessage, + execId: genExecID({ + sourceChainSelector: any2tvmMessage.sourceChainSelector, + messageID: 4n, + }), + receiver: receiver.address, + gasLimit: toNano('0.5'), + }) + + expect(result.transactions).toHaveTransaction({ + from: offRamp.address, + to: router.address, + success: false, + exitCode: rt.Router.Errors['Router_Error.SubjectCursed'], + }) + }) + afterAll(async () => { if (process.env['COVERAGE'] === 'true') { await coverage.generateCoverageArtifacts( diff --git a/contracts/tests/ccip/router/Router.cursing.spec.ts b/contracts/tests/ccip/router/Router.cursing.spec.ts index 24ec80db7..2aac01f89 100644 --- a/contracts/tests/ccip/router/Router.cursing.spec.ts +++ b/contracts/tests/ccip/router/Router.cursing.spec.ts @@ -19,6 +19,7 @@ describe('Router.cursing', () => { let router: SandboxContract let feeQuoter: SandboxContract let onRamp: SandboxContract + let offRamp: SandboxContract beforeAll(async () => { blockchain = await Blockchain.create() @@ -35,10 +36,11 @@ describe('Router.cursing', () => { } feeQuoter = await blockchain.treasury('feeQuoter') onRamp = await blockchain.treasury('onRamp') + offRamp = await blockchain.treasury('offRamp') }) beforeEach(async () => { - ;({ deployer, sender, router } = await setup(blockchain, { feeQuoter, onRamp })) + ;({ deployer, sender, router } = await setup(blockchain, { feeQuoter, onRamp, offRamp })) }) it('router respects cursing', async () => { @@ -126,6 +128,95 @@ describe('Router.cursing', () => { } }) + it('rejects LockOrBurn through the executor failure channel while cursed', async () => { + const remoteChainSelector = ChainSelectors.testselectors.CHAINSEL_EVM_TEST_90000001 + await router.sendRouterRMNRemoteCurse(deployer.getSender(), toNano('1'), { + queryId: 10n, + subjects: [remoteChainSelector], + }) + + const result = await router.sendRouterLockOrBurn(onRamp.getSender(), toNano('1'), { + queryID: 11n, + tokenPool: deployer.address, + request: rt.TokenPool_LockOrBurnInV1.create({ + transfer: rt.TokenPool_Transfer.create({ + id: 11n, + details: rt.TokenPool_TransferDetails.create({ + originalSender: sender.address, + remoteChainSelector, + receiver: EVM_ADDRESS, + amount: 1n, + localToken: sender.address, + }), + }), + }), + executorAddress: sender.address, + }) + + expect(result.transactions).toHaveTransaction({ + from: onRamp.address, + to: router.address, + success: true, + }) + expect(result.transactions).toHaveTransaction({ + from: router.address, + to: sender.address, + success: true, + op: 0xb76e3a84, // Router_TokenPoolLockOrBurnFailed + }) + expect(result.transactions).not.toHaveTransaction({ + from: router.address, + to: deployer.address, + }) + }) + + it('rejects ReleaseOrMint through replyTo while the source lane is cursed', async () => { + const sourceChainSelector = ChainSelectors.testselectors.CHAINSEL_EVM_TEST_90000001 + await router.sendRouterRMNRemoteCurse(deployer.getSender(), toNano('1'), { + queryId: 20n, + subjects: [sourceChainSelector], + }) + + const result = await router.sendRouterRelayReleaseOrMint(offRamp.getSender(), toNano('1'), { + queryID: 21n, + sourceChainSelector, + tokenPool: deployer.address, + request: rt.TokenPool_ReleaseOrMintInV1.create({ + transfer: rt.TokenPool_Transfer.create({ + id: 21n, + details: rt.TokenPool_TransferDetails.create({ + originalSender: EVM_ADDRESS, + remoteChainSelector: sourceChainSelector, + receiver: sender.address, + amount: 1n, + localToken: sender.address, + }), + }), + sourcePoolAddress: EVM_ADDRESS, + sourcePoolData: null, + offchainTokenData: null, + }), + requestedFinalityConfig: 0n, + replyTo: sender.address, + }) + + expect(result.transactions).toHaveTransaction({ + from: offRamp.address, + to: router.address, + success: true, + }) + expect(result.transactions).toHaveTransaction({ + from: router.address, + to: sender.address, + success: true, + op: rt.Router_TokenPoolReleaseOrMintFailed.PREFIX, + }) + expect(result.transactions).not.toHaveTransaction({ + from: router.address, + to: deployer.address, + }) + }) + it('router respect global cursing', async () => { // Curse all lanes { diff --git a/contracts/wrappers/gen/ccip/CCIPSendExecutor.ts b/contracts/wrappers/gen/ccip/CCIPSendExecutor.ts index aebfc099b..0d47e613b 100644 --- a/contracts/wrappers/gen/ccip/CCIPSendExecutor.ts +++ b/contracts/wrappers/gen/ccip/CCIPSendExecutor.ts @@ -160,6 +160,8 @@ function invokeCustomUnpackFromSlice(typeName: string, s: c.Slice): T { type coins = bigint +type int32 = bigint + type uint16 = bigint type uint32 = bigint type uint64 = bigint @@ -530,6 +532,49 @@ export const TokenPool_LockOrBurnFinished = { } } +/** + > struct (0x3476ea72) TokenPool_LockOrBurnFailure { + > queryId: uint64 + > errorCode: uint16 + > } + */ +export interface TokenPool_LockOrBurnFailure { + readonly $: 'TokenPool_LockOrBurnFailure' + queryId: uint64 + errorCode: uint16 +} + +export const TokenPool_LockOrBurnFailure = { + PREFIX: 0x3476ea72, + + create(args: { + queryId?: uint64 + errorCode: uint16 + }): TokenPool_LockOrBurnFailure { + return { + $: 'TokenPool_LockOrBurnFailure', + ...args, + queryId: args.queryId ?? 0n + } + }, + fromSlice(s: c.Slice): TokenPool_LockOrBurnFailure { + loadAndCheckPrefix32(s, 0x3476ea72, 'TokenPool_LockOrBurnFailure'); + return { + $: 'TokenPool_LockOrBurnFailure', + queryId: s.loadUintBig(64), + errorCode: s.loadUintBig(16), + } + }, + store(self: TokenPool_LockOrBurnFailure, b: c.Builder): void { + b.storeUint(0x3476ea72, 32); + b.storeUint(self.queryId, 64); + b.storeUint(self.errorCode, 16); + }, + toCell(self: TokenPool_LockOrBurnFailure): c.Cell { + return makeCellFrom(self, TokenPool_LockOrBurnFailure.store); + } +} + /** > struct TokenPool_LockOrBurnPrepared { > feeAmount: coins @@ -1436,6 +1481,54 @@ export const Router_WithdrawRequest = { } } +/** + > struct (0xb76e3a84) Router_TokenPoolLockOrBurnFailed { + > queryID: uint64 + > tokenPool: address + > exitCode: int32 + > } + */ +export interface Router_TokenPoolLockOrBurnFailed { + readonly $: 'Router_TokenPoolLockOrBurnFailed' + queryID: uint64 + tokenPool: c.Address + exitCode: int32 +} + +export const Router_TokenPoolLockOrBurnFailed = { + PREFIX: 0xb76e3a84, + + create(args: { + queryID?: uint64 + tokenPool: c.Address + exitCode: int32 + }): Router_TokenPoolLockOrBurnFailed { + return { + $: 'Router_TokenPoolLockOrBurnFailed', + ...args, + queryID: args.queryID ?? 0n + } + }, + fromSlice(s: c.Slice): Router_TokenPoolLockOrBurnFailed { + loadAndCheckPrefix32(s, 0xb76e3a84, 'Router_TokenPoolLockOrBurnFailed'); + return { + $: 'Router_TokenPoolLockOrBurnFailed', + queryID: s.loadUintBig(64), + tokenPool: s.loadAddress(), + exitCode: s.loadIntBig(32), + } + }, + store(self: Router_TokenPoolLockOrBurnFailed, b: c.Builder): void { + b.storeUint(0xb76e3a84, 32); + b.storeUint(self.queryID, 64); + b.storeAddress(self.tokenPool); + b.storeInt(self.exitCode, 32); + }, + toCell(self: Router_TokenPoolLockOrBurnFailed): c.Cell { + return makeCellFrom(self, Router_TokenPoolLockOrBurnFailed.store); + } +} + /** > type CrossChainAddress = slice */ @@ -2286,7 +2379,7 @@ export const CCIPSendExecutor_Execute = { } /** - > enum CCIPSendExecutor_Error { 6 variants } + > enum CCIPSendExecutor_Error { 7 variants } */ export type CCIPSendExecutor_Error = bigint @@ -2297,6 +2390,7 @@ export const CCIPSendExecutor_Error = { InsufficientFee: 17803n, FeeQuoterBounce: 17804n, TokenNotEnabled: 17805n, + TokenPoolBounce: 17806n, fromSlice(s: c.Slice): CCIPSendExecutor_Error { return s.loadUintBig(15); @@ -2348,7 +2442,7 @@ function calculateDeployedAddress(code: c.Cell, data: c.Cell, options: DeployedA } export class CCIPSendExecutor implements c.Contract { - static CodeCell = c.Cell.fromBase64('te6ccgECKgEACysAART/APSkE/S88sgLAQIBYgIDAgLOBAUCAUgmJwIBIAYHABVCBukjBt4Mj6UsmARdPiRjo/THzHXLCOkt/q0MeMC8j/gINcsJXnjFZzjAtcsIP0wG6TjAtcsJeeFWHyAICQoLA/UWybQ1ywhi7RsrPK/0z8x0z8x0wchwUHyhQGqAtcYMdQx1PpQMdQx0YIJMS0AggnZBcCCEAVdSoCCEATjOICCC8FNwLYJoIIQC+vCAKCgoCOgJrzjAtDHAOMCI9D6SDH6SDH6SDH0BNGCEB8N1EAB0PpI0cjPhYj6UgGAiIyQD/u1E0NPf1ywm58yeFPK/1PpI+gDU1ywIgJQwgQCKjkfXLAmAlDCBAIuOO9csCoCUMIEAjI4v1ywLgJQwgQCNjiPXLAyAlDCBAI6OF9csDYCUMIEAj5zXLA6AMZLyP+GBAJDi4uLi4uKBRYiBAItYuvL0iFR1Q1NUBMjL34nPFhMlDA0C/DHXLCbnzJ4U8r/U+kj6ANdM0PpI+kj6UNHtRND6SNcL3wLwAgHI+lIU+lIS+lIS9ADJgUWJ+JL4KMcF8vSBRYv4l4IQBV1KgIIQBOM4gIILwU3AtgmgghAL68IAoL7y9CDQ+kgx+kgx+kj0BDHRiwjIz5HSW/1aJ88UzsnIiQ4PAfwx7UTQ09/XLCbnzJ4U8r/U+kj6ANTXLAiAlddMgQCKjk3XLAmAlddMgQCLjkDXLAqAlddMgQCMjjPXLAuAlddMgQCNjibXLAyAlddMgQCOjhnXLA2AlddMgQCPndcsDoCS8j/h10yBAJDi4uLi4uKBRYiBAItYuvL0gUWJItAQBDbjAtcsIFLHM8TjAtcsJouaoATjAtcsJz0aggwREhMUAAjc+ZPCAIjM+lIB+gLMz4dAzMntVND6SPpIMfpIMfQEMdHIz5MQGjiGFcvfgUWMzwv/E8z6UgH6AsnIz4WIEvpScc8LbszJgwb7AAABYgFkzxYS+lJxzwtuzMmAQPsAiFRyVCY2NjY2BcjL38+Tc+ZPChTMEvpSAfoCzM+EwMzJ7VQlAEz6SDH6SDH6SPQEMdH4kscF8vQG+gDTX9QQiRB4EGcQVhBF8AFfBgH+Me1E0NPf1ywm58yeFPK/1PpI+gDU1ywIgJQwgQCKjkfXLAmAlDCBAIuOO9csCoCUMIEAjI4v1ywLgJQwgQCNjiPXLAyAlDCBAI6OF9csDYCUMIEAj5zXLA6AMZLyP+GBAJDi4uLi4uKBRYiBAItYuvL0gUWJIdD6SDH6SDH6SBUB/DHtRNDT39csJufMnhTyv9T6SPoA1NcsCICV10yBAIqOTdcsCYCV10yBAIuOQNcsCoCV10yBAIyOM9csC4CV10yBAI2OJtcsDICV10yBAI6OGdcsDYCV10yBAI+d1ywOgJLyP+HXTIEAkOLi4uLi4oFFiIEAjFi68vSBRYki0BYB/DHtRNDT39csJufMnhTyv9T6SPoA1NcsCICV10yBAIqOTdcsCYCV10yBAIuOQNcsCoCV10yBAIyOM9csC4CV10yBAI2OJtcsDICV10yBAI6OGdcsDYCV10yBAI+d1ywOgJLyP+HXTIEAkOLi4uLi4oFFiIEAjVi68vSBRYkh0BgCJuMC1ywnoZUnHOMCMIQPAccA8vQaGwHa9AQx0fiSxwXy9AXXC/+IVHVDU1kEyMvfz5Nz5k8KE8z6UgH6AszPh0DMye1UJdA2BfpI+kgx+kgx9AQx0cjPkxAaOIYlzwvfNVBUy/8izxQyUgL6UjEi+gJsEsnIz4WIEvpScc8LbszJgwb7ACUB/PpIMfpIMfpIMfQE0dD6SNH4kscF8vQG0z8x+kj6UDAn0DgH+gDTX9GBRY0pbrPy9IIQHc1lACTQ+kgx+kj6SDH0BDHRyM+FiFJQ+lJY+gKNBkAAAAAAAAAAAAAAAAABY7XLmAAAAAAAAAAEzxb6Us+ByXH7AMhY+gLLX/pSFhcATPpSyVR0MigFNjY2NgXIy9/Pk3PmTwoUzBL6UgH6AszPhcDMye1UAf76ADHTXzH6SPpIMdH4kscF8vQG0z8x+lAwJtA3BvoA01/6SPpI0SfQ1ywhi7RsrPK/0z/TP9MHIcFB8oUBqgLXGNQx10zQINdLAZEwm4E0vAHAAfL010zQ4voA+kgwKdD6SDCCEDuaygDIUAT6AhL6UsnIJNdJIKk4AvJFqwIgGQDcwUHyhc8LBxTOycjPkm+H7YYWyz8TzFJQ+lITyz8szwvfE8xSkPpSycjPhYgT+lIB+gJxzwtqzMlx+wDIUAT6AhLLX/pS+lIW+lLJVHQyKAU2NjY2BcjL38+Tc+ZPChTMEvpSAfoCzM+GQMzJ7VQB/DHtRNDT39csJufMnhTyv9T6SPoA1NcsCICV10yBAIqOTdcsCYCV10yBAIuOQNcsCoCV10yBAIyOM9csC4CV10yBAI2OJtcsDICV10yBAI6OGdcsDYCV10yBAI+d1ywOgJLyP+HXTIEAkOLi4uLi4oFFiIEAjli68vSBRYkh0BwB/DHtRNDT39csJufMnhTyv9T6SPoA1NcsCICV10yBAIqOTdcsCYCV10yBAIuOQNcsCoCV10yBAIyOM9csC4CV10yBAI2OJtcsDICV10yBAI6OGdcsDYCV10yBAI+d1ywOgJLyP+HXTIEAkOLi4uLi4oFFiIEAj1i68vSBRYkh0B8B/PoAMdNfMfpIMfpI+kgx0fiSxwXy9AbTPzH6SNTXTCjQOQj6ANNf+kj6SPpI0chQBfoCE8tf+lJSEPpSUiD6UslUeYcoCjsCyMvfz5Nz5k8KzPpSUAj6AhbMz4bAFszJ7VQl0NcsIYu0bKzyv9N/MdMHIcFB8oUBqgLXGDHUMR0B/tdM0CDXSwGRMJuBNLwBwAHy9NdM0OL6ADAj0DQD+kj6SDH6SDH0BDHRJtDXLCGLtGys8r/TP9M/MdMHIcFB8oUBqgLXGDHUMdQx+lAx1DHRJ9A4B9csIYu0bKzyv9M/MdM/0wchwUHyhQGqAtcYMdQx1DH6UDHUMdEDyPpSEsweAGIYzMkEyPpSWPoCEvpSEszJyM+FiBX6UoIQBeR6ic8LjhLLPyLPC98yzws/zMmAQPsAA/z6ADHTXzH6SDH6SPpIMdH4kscF8vQG0z8x1PoAMPgAJ9A4B/oA01/6SDH6SPpIMdED0NTU0cjPkAAFfkLJBcj6UhvL/8wZzBLMyYhUd2VTdgTIy9/Pk3PmTwoTzPpSAfoCzM+HQMzJ7VQi0DMC+kj6SDH6SDH0BDHRyInPFiclICEACM+mszYAWs8L3zdQZvoCFstfI88UM1IT+lIxIfoCMRL0AMnIz4WIEvpScc8LbszJgwb7AAG4XwOIVHZUU2UEyMvfz5Nz5k8KE8z6UgH6AszPh0DMye1UIdD6SPpIMfpIMfQEMdHIz5MQGjiGJ88L34FFis8L/ybPFFJQ+lIk+gLJyM+FiBL6UnHPC27MyYMG+wAlAcD4AG2IVHmHU5gEyMvfz5Nz5k8KE8z6UgH6AszPh0DMye1UJND6SPpIMfpIMfQEMdHIz5M+mszaKs8L31AE+gISy18nzxRSYPpSJfoC9ADJyM+FiBL6UnHPC27MyYMG+wAlAJL6Ao0GQAAAAAAAAAAAAAAAAAPXemFoAAAAAAAAAATPFslx+wDIWPoCy1/JVHZUU2UEyMvfz5Nz5k8KE8z6UgH6AszPhUDMye1UAAACASAoKQALuGhYEAsoAGG2K/GhI2NLc1lzG0MLS3Fzo3txcxsbS4FyGhpKgpsrcyIrwysbq6N7lBFqYlxsXGMQABm1xRAosRQEEIH3flCQ'); + static CodeCell = c.Cell.fromBase64('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'); static Errors = { 'Utils_Error.InvalidData': 13500, @@ -2359,6 +2453,7 @@ export class CCIPSendExecutor implements c.Contract { 'CCIPSendExecutor_Error.InsufficientFee': 17803, 'CCIPSendExecutor_Error.FeeQuoterBounce': 17804, 'CCIPSendExecutor_Error.TokenNotEnabled': 17805, + 'CCIPSendExecutor_Error.TokenPoolBounce': 17806, } readonly address: c.Address @@ -2443,6 +2538,21 @@ export class CCIPSendExecutor implements c.Contract { return TokenPool_LockOrBurnFinished.toCell(TokenPool_LockOrBurnFinished.create(body)); } + static createCellOfTokenPoolLockOrBurnFailure(body: { + queryId?: uint64 + errorCode: uint16 + }) { + return TokenPool_LockOrBurnFailure.toCell(TokenPool_LockOrBurnFailure.create(body)); + } + + static createCellOfRouterTokenPoolLockOrBurnFailed(body: { + queryID?: uint64 + tokenPool: c.Address + exitCode: int32 + }) { + return Router_TokenPoolLockOrBurnFailed.toCell(Router_TokenPoolLockOrBurnFailed.create(body)); + } + async sendDeploy(provider: ContractProvider, via: Sender, msgValue: coins, extraOptions?: ExtraSendOptions) { return provider.internal(via, { value: msgValue, @@ -2534,6 +2644,29 @@ export class CCIPSendExecutor implements c.Contract { }); } + async sendTokenPoolLockOrBurnFailure(provider: ContractProvider, via: Sender, msgValue: coins, body: { + queryId?: uint64 + errorCode: uint16 + }, extraOptions?: ExtraSendOptions) { + return provider.internal(via, { + value: msgValue, + body: TokenPool_LockOrBurnFailure.toCell(TokenPool_LockOrBurnFailure.create(body)), + ...extraOptions + }); + } + + async sendRouterTokenPoolLockOrBurnFailed(provider: ContractProvider, via: Sender, msgValue: coins, body: { + queryID?: uint64 + tokenPool: c.Address + exitCode: int32 + }, extraOptions?: ExtraSendOptions) { + return provider.internal(via, { + value: msgValue, + body: Router_TokenPoolLockOrBurnFailed.toCell(Router_TokenPoolLockOrBurnFailed.create(body)), + ...extraOptions + }); + } + async getTypeAndVersion(provider: ContractProvider): Promise<[ c.Slice, c.Slice, diff --git a/contracts/wrappers/gen/ccip/MockTokenPool.ts b/contracts/wrappers/gen/ccip/MockTokenPool.ts new file mode 100644 index 000000000..d8d1dcedc --- /dev/null +++ b/contracts/wrappers/gen/ccip/MockTokenPool.ts @@ -0,0 +1,5178 @@ +// AUTO-GENERATED, do not edit +// It's a TypeScript wrapper for a MockTokenPool contract in Tolk. +/* eslint-disable */ + +import * as c from '@ton/core'; +import { beginCell, ContractProvider, Sender, SendMode } from '@ton/core'; + +// ———————————————————————————————————————————— +// predefined types and functions +// + +type RemainingBitsAndRefs = c.Slice + +type array = T[] + +type StoreCallback = (obj: T, b: c.Builder) => void +type LoadCallback = (s: c.Slice) => T + + +function makeCellFrom(self: T, storeFn_T: StoreCallback): c.Cell { + let b = beginCell(); + storeFn_T(self, b); + return b.endCell(); +} + +function loadAndCheckPrefix32(s: c.Slice, expected: number, structName: string): void { + let prefix = s.loadUint(32); + if (prefix !== expected) { + throw new Error(`Incorrect prefix for '${structName}': expected 0x${expected.toString(16).padStart(8, '0')}, got 0x${prefix.toString(16).padStart(8, '0')}`); + } +} + +function lookupPrefix(s: c.Slice, expected: number, prefixLen: number): boolean { + return s.remainingBits >= prefixLen && s.preloadUint(prefixLen) === expected; +} + +function throwNonePrefixMatch(fieldPath: string): never { + throw new Error(`Incorrect prefix for '${fieldPath}': none of variants matched`); +} + +function storeCellRef(value: T, b: c.Builder, storeFn_T: StoreCallback): void { + let b_ref = c.beginCell(); + storeFn_T(value, b_ref); + b.storeRef(b_ref.endCell()); +} + +function loadCellRef(s: c.Slice, loadFn_T: LoadCallback): T { + let s_ref = s.loadRef().beginParse(); + return loadFn_T(s_ref); +} + +function dictToMap(d: c.Dictionary): Map { + const map = new Map(); + for (const [k, v] of d) { + map.set(k, v); + } + return map; +} + +function mapToDict(m: Map, keySerializer: c.DictionaryKey, valueSerializer: c.DictionaryValue): c.Dictionary { + const d = c.Dictionary.empty(keySerializer, valueSerializer); + for (const [k, v] of m) { + d.set(k, v); + } + return d; +} + + +function dictToSet(d: c.Dictionary): Set { + const set = new Set(); + for (const k of d.keys()) { + set.add(k); + } + return set; +} + +function setToDict(s: Set, keySerializer: c.DictionaryKey, valueSerializer: c.DictionaryValue<[]>): c.Dictionary { + const d = c.Dictionary.empty(keySerializer, valueSerializer); + for (const k of s) { + d.set(k, []); + } + return d; +} + + +function storeTolkRemaining(v: RemainingBitsAndRefs, b: c.Builder): void { + b.storeSlice(v); +} + +function loadTolkRemaining(s: c.Slice): RemainingBitsAndRefs { + let rest = s.clone(); + s.loadBits(s.remainingBits); + while (s.remainingRefs) { + s.loadRef(); + } + return rest; +} + +function storeTolkNullable(v: T | null, b: c.Builder, storeFn_T: StoreCallback): void { + if (v === null) { + b.storeUint(0, 1); + } else { + b.storeUint(1, 1); + storeFn_T(v, b); + } +} + +function storeArrayOf(v: array, b: c.Builder, storeFn_T: StoreCallback): void { + // the compiler stores array in chunks; in TypeScript, for simplicity, store "1 elem = 1 ref" + let tail = null as c.Cell | null; + for (let i = 0; i < v.length; ++i) { + let chunkB = beginCell().storeMaybeRef(tail); + storeFn_T(v[v.length - 1 - i], chunkB); + tail = chunkB.endCell(); + } + b.storeUint(v.length, 8); + b.storeMaybeRef(tail); +} + +function loadArrayOf(s: c.Slice, loadFn_T: LoadCallback): array { + let len = s.loadUint(8); + let head = s.loadMaybeRef(); + let outArr = [] as array; + while (head != null) { + let s = head.beginParse(); + head = s.loadMaybeRef(); + while (s.remainingBits || s.remainingRefs) { + outArr.push(loadFn_T(s)); + } + } + if (len !== outArr.length) { + throw new Error(`mismatch array binary data: expected ${len} elements, got ${outArr.length}`); + } + return outArr; +} + +function createDictionaryValue(loadFn_V: LoadCallback, storeFn_V: StoreCallback): c.DictionaryValue { + return { + serialize(self: V, b: c.Builder) { + storeFn_V(self, b); + }, + parse(s: c.Slice): V { + const value = loadFn_V(s); + s.endParse(); + return value; + } + } +} + +// ———————————————————————————————————————————— +// parse get methods result from a TVM stack +// + +class StackReader { + constructor(private tuple: c.TupleItem[]) { + } + + static fromGetMethod(expectedN: number, getMethodResult: { stack: c.TupleReader }): StackReader { + let tuple = [] as c.TupleItem[]; + while (getMethodResult.stack.remaining) { + tuple.push(getMethodResult.stack.pop()); + } + if (tuple.length !== expectedN) { + throw new Error(`expected ${expectedN} stack width, got ${tuple.length}`); + } + return new StackReader(tuple); + } + + private popExpecting(itemType: string): ItemT { + const item = this.tuple.shift(); + if (item?.type === itemType) { + return item as ItemT; + } + throw new Error(`not '${itemType}' on a stack`); + } + + private popCellLike(): c.Cell { + const item = this.tuple.shift(); + if (item && (item.type === 'cell' || item.type === 'slice' || item.type === 'builder')) { + return item.cell; + } + throw new Error(`not cell/slice on a stack`); + } + + readBigInt(): bigint { + return this.popExpecting('int').value; + } + + readBoolean(): boolean { + return this.popExpecting('int').value !== 0n; + } + + readCell(): c.Cell { + return this.popCellLike(); + } + + readSlice(): c.Slice { + return this.popCellLike().beginParse(); + } +} + +// ———————————————————————————————————————————— +// custom packToBuilder and unpackFromSlice +// + +type CustomPackToBuilderFn = (self: T, b: c.Builder) => void +type CustomUnpackFromSliceFn = (s: c.Slice) => T + +let customSerializersRegistry: Map | null, CustomUnpackFromSliceFn | null]> = new Map; + +function ensureCustomSerializerRegistered(typeName: string) { + if (!customSerializersRegistry.has(typeName)) { + throw new Error(`Custom packToBuilder/unpackFromSlice was not registered for type 'MockTokenPool.${typeName}'.\n(in Tolk code, they have custom logic \`fun ${typeName}__packToBuilder\`)\nSteps to fix:\n1) in your code, create and implement\n > function ${typeName}__packToBuilder(self: ${typeName}, b: Builder): void { ... }\n > function ${typeName}__unpackFromSlice(s: Slice): ${typeName} { ... }\n2) register them in advance by calling\n > MockTokenPool.registerCustomPackUnpack('${typeName}', ${typeName}__packToBuilder, ${typeName}__unpackFromSlice);`); + } +} + +function invokeCustomPackToBuilder(typeName: string, self: T, b: c.Builder) { + ensureCustomSerializerRegistered(typeName); + customSerializersRegistry.get(typeName)![0]!(self, b); +} + +function invokeCustomUnpackFromSlice(typeName: string, s: c.Slice): T { + ensureCustomSerializerRegistered(typeName); + return customSerializersRegistry.get(typeName)![1]!(s); +} + +// ———————————————————————————————————————————— +// auto-generated serializers to/from cells +// + +type coins = bigint + +type uint8 = bigint +type uint16 = bigint +type uint32 = bigint +type uint64 = bigint +type uint120 = bigint +type uint128 = bigint +type uint256 = bigint + +/** + > struct Storage { + > poolData: Cell + > } + */ +export interface Storage { + readonly $: 'Storage' + poolData: TokenPool_Data +} + +export const Storage = { + create(args: { + poolData: TokenPool_Data + }): Storage { + return { + $: 'Storage', + ...args + } + }, + fromSlice(s: c.Slice): Storage { + return { + $: 'Storage', + poolData: loadCellRef(s, TokenPool_Data.fromSlice), + } + }, + store(self: Storage, b: c.Builder): void { + storeCellRef(self.poolData, b, TokenPool_Data.store); + }, + toCell(self: Storage): c.Cell { + return makeCellFrom(self, Storage.store); + } +} + +/** + > struct TokenPool_AdminConfig { + > ownable: Cell + > rmnProxy: address? + > dynamicConfig: Cell + > jettonClient: JettonClient + > allowedFinalityConfig: uint32 + > advancedPoolHooks: address? + > deployableCode: cell? + > } + */ +export interface TokenPool_AdminConfig { + readonly $: 'TokenPool_AdminConfig' + ownable: Ownable2Step + rmnProxy: c.Address | null + dynamicConfig: TokenPool_DynamicConfig + jettonClient: JettonClient + allowedFinalityConfig: uint32 /* = 0 as uint32 */ + advancedPoolHooks: c.Address | null /* = null */ + deployableCode: c.Cell | null /* = null */ +} + +export const TokenPool_AdminConfig = { + create(args: { + ownable: Ownable2Step + rmnProxy: c.Address | null + dynamicConfig: TokenPool_DynamicConfig + jettonClient: JettonClient + allowedFinalityConfig?: uint32 /* = 0 as uint32 */ + advancedPoolHooks?: c.Address | null /* = null */ + deployableCode?: c.Cell | null /* = null */ + }): TokenPool_AdminConfig { + return { + $: 'TokenPool_AdminConfig', + allowedFinalityConfig: 0n, + advancedPoolHooks: null, + deployableCode: null, + ...args + } + }, + fromSlice(s: c.Slice): TokenPool_AdminConfig { + return { + $: 'TokenPool_AdminConfig', + ownable: loadCellRef(s, Ownable2Step.fromSlice), + rmnProxy: s.loadMaybeAddress(), + dynamicConfig: loadCellRef(s, TokenPool_DynamicConfig.fromSlice), + jettonClient: JettonClient.fromSlice(s), + allowedFinalityConfig: s.loadUintBig(32), + advancedPoolHooks: s.loadMaybeAddress(), + deployableCode: s.loadBoolean() ? s.loadRef() : null, + } + }, + store(self: TokenPool_AdminConfig, b: c.Builder): void { + storeCellRef(self.ownable, b, Ownable2Step.store); + b.storeAddress(self.rmnProxy); + storeCellRef(self.dynamicConfig, b, TokenPool_DynamicConfig.store); + JettonClient.store(self.jettonClient, b); + b.storeUint(self.allowedFinalityConfig, 32); + b.storeAddress(self.advancedPoolHooks); + storeTolkNullable(self.deployableCode, b, + (v,b) => b.storeRef(v) + ); + }, + toCell(self: TokenPool_AdminConfig): c.Cell { + return makeCellFrom(self, TokenPool_AdminConfig.store); + } +} + +/** + > struct TokenPool_Data { + > adminConfig: Cell + > localPolicy: Cell + > tokenDecimals: uint8 + > remoteChainConfigs: map + > tokenTransferFeeConfigs: map + > } + */ +export interface TokenPool_Data { + readonly $: 'TokenPool_Data' + adminConfig: TokenPool_AdminConfig + localPolicy: TokenPool_LocalPolicy + tokenDecimals: uint8 + remoteChainConfigs: Map /* = [] as map */ + tokenTransferFeeConfigs: Map /* = [] as map */ +} + +export const TokenPool_Data = { + create(args: { + adminConfig: TokenPool_AdminConfig + localPolicy: TokenPool_LocalPolicy + tokenDecimals: uint8 + remoteChainConfigs: Map /* = [] as map */ + tokenTransferFeeConfigs: Map /* = [] as map */ + }): TokenPool_Data { + return { + $: 'TokenPool_Data', + ...args + } + }, + fromSlice(s: c.Slice): TokenPool_Data { + return { + $: 'TokenPool_Data', + adminConfig: loadCellRef(s, TokenPool_AdminConfig.fromSlice), + localPolicy: loadCellRef(s, TokenPool_LocalPolicy.fromSlice), + tokenDecimals: s.loadUintBig(8), + remoteChainConfigs: dictToMap(c.Dictionary.load(c.Dictionary.Keys.BigUint(64), createDictionaryValue(TokenPool_RemoteChainConfig.fromSlice, TokenPool_RemoteChainConfig.store), s)), + tokenTransferFeeConfigs: dictToMap(c.Dictionary.load(c.Dictionary.Keys.BigUint(64), createDictionaryValue(TokenPool_TokenTransferFeeConfig.fromSlice, TokenPool_TokenTransferFeeConfig.store), s)), + } + }, + store(self: TokenPool_Data, b: c.Builder): void { + storeCellRef(self.adminConfig, b, TokenPool_AdminConfig.store); + storeCellRef(self.localPolicy, b, TokenPool_LocalPolicy.store); + b.storeUint(self.tokenDecimals, 8); + b.storeDict(mapToDict(self.remoteChainConfigs, c.Dictionary.Keys.BigUint(64), createDictionaryValue(TokenPool_RemoteChainConfig.fromSlice, TokenPool_RemoteChainConfig.store)), c.Dictionary.Keys.BigUint(64), createDictionaryValue(TokenPool_RemoteChainConfig.fromSlice, TokenPool_RemoteChainConfig.store)); + b.storeDict(mapToDict(self.tokenTransferFeeConfigs, c.Dictionary.Keys.BigUint(64), createDictionaryValue(TokenPool_TokenTransferFeeConfig.fromSlice, TokenPool_TokenTransferFeeConfig.store)), c.Dictionary.Keys.BigUint(64), createDictionaryValue(TokenPool_TokenTransferFeeConfig.fromSlice, TokenPool_TokenTransferFeeConfig.store)); + }, + toCell(self: TokenPool_Data): c.Cell { + return makeCellFrom(self, TokenPool_Data.store); + } +} + +/** + > struct (0x56f73d37) TokenPool_ApplyChainUpdates { + > queryId: uint64 + > remoteChainSelectorsToRemove: SnakedCell + > chainsToAdd: SnakedCell + > } + */ +export interface TokenPool_ApplyChainUpdates { + readonly $: 'TokenPool_ApplyChainUpdates' + queryId: uint64 + remoteChainSelectorsToRemove: SnakedCell + chainsToAdd: SnakedCell +} + +export const TokenPool_ApplyChainUpdates = { + PREFIX: 0x56f73d37, + + create(args: { + queryId?: uint64 + remoteChainSelectorsToRemove: SnakedCell + chainsToAdd: SnakedCell + }): TokenPool_ApplyChainUpdates { + return { + $: 'TokenPool_ApplyChainUpdates', + ...args, + queryId: args.queryId ?? 0n + } + }, + fromSlice(s: c.Slice): TokenPool_ApplyChainUpdates { + loadAndCheckPrefix32(s, 0x56f73d37, 'TokenPool_ApplyChainUpdates'); + return { + $: 'TokenPool_ApplyChainUpdates', + queryId: s.loadUintBig(64), + remoteChainSelectorsToRemove: loadSnakedCellOf(s, (s) => s.loadUintBig(64)), + chainsToAdd: loadSnakedCellOf(s, TokenPool_ChainUpdate.fromSlice), + } + }, + store(self: TokenPool_ApplyChainUpdates, b: c.Builder): void { + b.storeUint(0x56f73d37, 32); + b.storeUint(self.queryId, 64); + storeSnakedCellOf(self.remoteChainSelectorsToRemove, b, (v, b) => b.storeUint(v, 64)); + storeSnakedCellOf(self.chainsToAdd, b, TokenPool_ChainUpdate.store); + }, + toCell(self: TokenPool_ApplyChainUpdates): c.Cell { + return makeCellFrom(self, TokenPool_ApplyChainUpdates.store); + } +} + +/** + > struct (0x17c242dc) TokenPool_AddRemotePool { + > queryId: uint64 + > remoteChainSelector: uint64 + > remotePoolAddress: Cell + > } + */ +export interface TokenPool_AddRemotePool { + readonly $: 'TokenPool_AddRemotePool' + queryId: uint64 + remoteChainSelector: uint64 + remotePoolAddress: CrossChainAddress +} + +export const TokenPool_AddRemotePool = { + PREFIX: 0x17c242dc, + + create(args: { + queryId?: uint64 + remoteChainSelector: uint64 + remotePoolAddress: CrossChainAddress + }): TokenPool_AddRemotePool { + return { + $: 'TokenPool_AddRemotePool', + ...args, + queryId: args.queryId ?? 0n + } + }, + fromSlice(s: c.Slice): TokenPool_AddRemotePool { + loadAndCheckPrefix32(s, 0x17c242dc, 'TokenPool_AddRemotePool'); + return { + $: 'TokenPool_AddRemotePool', + queryId: s.loadUintBig(64), + remoteChainSelector: s.loadUintBig(64), + remotePoolAddress: loadCellRef(s, CrossChainAddress.fromSlice), + } + }, + store(self: TokenPool_AddRemotePool, b: c.Builder): void { + b.storeUint(0x17c242dc, 32); + b.storeUint(self.queryId, 64); + b.storeUint(self.remoteChainSelector, 64); + storeCellRef(self.remotePoolAddress, b, CrossChainAddress.store); + }, + toCell(self: TokenPool_AddRemotePool): c.Cell { + return makeCellFrom(self, TokenPool_AddRemotePool.store); + } +} + +/** + > struct (0x426b8cc4) TokenPool_RemoveRemotePool { + > queryId: uint64 + > remoteChainSelector: uint64 + > remotePoolAddress: Cell + > } + */ +export interface TokenPool_RemoveRemotePool { + readonly $: 'TokenPool_RemoveRemotePool' + queryId: uint64 + remoteChainSelector: uint64 + remotePoolAddress: CrossChainAddress +} + +export const TokenPool_RemoveRemotePool = { + PREFIX: 0x426b8cc4, + + create(args: { + queryId?: uint64 + remoteChainSelector: uint64 + remotePoolAddress: CrossChainAddress + }): TokenPool_RemoveRemotePool { + return { + $: 'TokenPool_RemoveRemotePool', + ...args, + queryId: args.queryId ?? 0n + } + }, + fromSlice(s: c.Slice): TokenPool_RemoveRemotePool { + loadAndCheckPrefix32(s, 0x426b8cc4, 'TokenPool_RemoveRemotePool'); + return { + $: 'TokenPool_RemoveRemotePool', + queryId: s.loadUintBig(64), + remoteChainSelector: s.loadUintBig(64), + remotePoolAddress: loadCellRef(s, CrossChainAddress.fromSlice), + } + }, + store(self: TokenPool_RemoveRemotePool, b: c.Builder): void { + b.storeUint(0x426b8cc4, 32); + b.storeUint(self.queryId, 64); + b.storeUint(self.remoteChainSelector, 64); + storeCellRef(self.remotePoolAddress, b, CrossChainAddress.store); + }, + toCell(self: TokenPool_RemoveRemotePool): c.Cell { + return makeCellFrom(self, TokenPool_RemoveRemotePool.store); + } +} + +/** + > struct (0xd7712810) TokenPool_SetDynamicConfig { + > queryId: uint64 + > router: address + > rateLimitAdmin: address? + > feeAdmin: address? + > } + */ +export interface TokenPool_SetDynamicConfig { + readonly $: 'TokenPool_SetDynamicConfig' + queryId: uint64 + router: c.Address + rateLimitAdmin: c.Address | null /* = null */ + feeAdmin: c.Address | null /* = null */ +} + +export const TokenPool_SetDynamicConfig = { + PREFIX: 0xd7712810, + + create(args: { + queryId?: uint64 + router: c.Address + rateLimitAdmin?: c.Address | null /* = null */ + feeAdmin?: c.Address | null /* = null */ + }): TokenPool_SetDynamicConfig { + return { + $: 'TokenPool_SetDynamicConfig', + rateLimitAdmin: null, + feeAdmin: null, + ...args, + queryId: args.queryId ?? 0n + } + }, + fromSlice(s: c.Slice): TokenPool_SetDynamicConfig { + loadAndCheckPrefix32(s, 0xd7712810, 'TokenPool_SetDynamicConfig'); + return { + $: 'TokenPool_SetDynamicConfig', + queryId: s.loadUintBig(64), + router: s.loadAddress(), + rateLimitAdmin: s.loadMaybeAddress(), + feeAdmin: s.loadMaybeAddress(), + } + }, + store(self: TokenPool_SetDynamicConfig, b: c.Builder): void { + b.storeUint(0xd7712810, 32); + b.storeUint(self.queryId, 64); + b.storeAddress(self.router); + b.storeAddress(self.rateLimitAdmin); + b.storeAddress(self.feeAdmin); + }, + toCell(self: TokenPool_SetDynamicConfig): c.Cell { + return makeCellFrom(self, TokenPool_SetDynamicConfig.store); + } +} + +/** + > struct (0x3c50a39b) TokenPool_SetAllowedFinalityConfig { + > queryId: uint64 + > allowedFinalityConfig: uint32 + > } + */ +export interface TokenPool_SetAllowedFinalityConfig { + readonly $: 'TokenPool_SetAllowedFinalityConfig' + queryId: uint64 + allowedFinalityConfig: uint32 +} + +export const TokenPool_SetAllowedFinalityConfig = { + PREFIX: 0x3c50a39b, + + create(args: { + queryId?: uint64 + allowedFinalityConfig: uint32 + }): TokenPool_SetAllowedFinalityConfig { + return { + $: 'TokenPool_SetAllowedFinalityConfig', + ...args, + queryId: args.queryId ?? 0n + } + }, + fromSlice(s: c.Slice): TokenPool_SetAllowedFinalityConfig { + loadAndCheckPrefix32(s, 0x3c50a39b, 'TokenPool_SetAllowedFinalityConfig'); + return { + $: 'TokenPool_SetAllowedFinalityConfig', + queryId: s.loadUintBig(64), + allowedFinalityConfig: s.loadUintBig(32), + } + }, + store(self: TokenPool_SetAllowedFinalityConfig, b: c.Builder): void { + b.storeUint(0x3c50a39b, 32); + b.storeUint(self.queryId, 64); + b.storeUint(self.allowedFinalityConfig, 32); + }, + toCell(self: TokenPool_SetAllowedFinalityConfig): c.Cell { + return makeCellFrom(self, TokenPool_SetAllowedFinalityConfig.store); + } +} + +/** + > struct (0x3f5c9f57) TokenPool_SetAdvancedPoolHooks { + > queryId: uint64 + > advancedPoolHooks: address? + > } + */ +export interface TokenPool_SetAdvancedPoolHooks { + readonly $: 'TokenPool_SetAdvancedPoolHooks' + queryId: uint64 + advancedPoolHooks: c.Address | null +} + +export const TokenPool_SetAdvancedPoolHooks = { + PREFIX: 0x3f5c9f57, + + create(args: { + queryId?: uint64 + advancedPoolHooks: c.Address | null + }): TokenPool_SetAdvancedPoolHooks { + return { + $: 'TokenPool_SetAdvancedPoolHooks', + ...args, + queryId: args.queryId ?? 0n + } + }, + fromSlice(s: c.Slice): TokenPool_SetAdvancedPoolHooks { + loadAndCheckPrefix32(s, 0x3f5c9f57, 'TokenPool_SetAdvancedPoolHooks'); + return { + $: 'TokenPool_SetAdvancedPoolHooks', + queryId: s.loadUintBig(64), + advancedPoolHooks: s.loadMaybeAddress(), + } + }, + store(self: TokenPool_SetAdvancedPoolHooks, b: c.Builder): void { + b.storeUint(0x3f5c9f57, 32); + b.storeUint(self.queryId, 64); + b.storeAddress(self.advancedPoolHooks); + }, + toCell(self: TokenPool_SetAdvancedPoolHooks): c.Cell { + return makeCellFrom(self, TokenPool_SetAdvancedPoolHooks.store); + } +} + +/** + > struct (0x3868e309) TokenPool_SetDeployableCode { + > queryId: uint64 + > deployableCode: cell? + > } + */ +export interface TokenPool_SetDeployableCode { + readonly $: 'TokenPool_SetDeployableCode' + queryId: uint64 + deployableCode: c.Cell | null +} + +export const TokenPool_SetDeployableCode = { + PREFIX: 0x3868e309, + + create(args: { + queryId?: uint64 + deployableCode: c.Cell | null + }): TokenPool_SetDeployableCode { + return { + $: 'TokenPool_SetDeployableCode', + ...args, + queryId: args.queryId ?? 0n + } + }, + fromSlice(s: c.Slice): TokenPool_SetDeployableCode { + loadAndCheckPrefix32(s, 0x3868e309, 'TokenPool_SetDeployableCode'); + return { + $: 'TokenPool_SetDeployableCode', + queryId: s.loadUintBig(64), + deployableCode: s.loadBoolean() ? s.loadRef() : null, + } + }, + store(self: TokenPool_SetDeployableCode, b: c.Builder): void { + b.storeUint(0x3868e309, 32); + b.storeUint(self.queryId, 64); + storeTolkNullable(self.deployableCode, b, + (v,b) => b.storeRef(v) + ); + }, + toCell(self: TokenPool_SetDeployableCode): c.Cell { + return makeCellFrom(self, TokenPool_SetDeployableCode.store); + } +} + +/** + > struct (0x89d602e5) TokenPool_DeployableCodeSet { + > queryId: uint64 + > deployableCode: cell? + > } + */ +export interface TokenPool_DeployableCodeSet { + readonly $: 'TokenPool_DeployableCodeSet' + queryId: uint64 + deployableCode: c.Cell | null +} + +export const TokenPool_DeployableCodeSet = { + PREFIX: 0x89d602e5, + + create(args: { + queryId?: uint64 + deployableCode: c.Cell | null + }): TokenPool_DeployableCodeSet { + return { + $: 'TokenPool_DeployableCodeSet', + ...args, + queryId: args.queryId ?? 0n + } + }, + fromSlice(s: c.Slice): TokenPool_DeployableCodeSet { + loadAndCheckPrefix32(s, 0x89d602e5, 'TokenPool_DeployableCodeSet'); + return { + $: 'TokenPool_DeployableCodeSet', + queryId: s.loadUintBig(64), + deployableCode: s.loadBoolean() ? s.loadRef() : null, + } + }, + store(self: TokenPool_DeployableCodeSet, b: c.Builder): void { + b.storeUint(0x89d602e5, 32); + b.storeUint(self.queryId, 64); + storeTolkNullable(self.deployableCode, b, + (v,b) => b.storeRef(v) + ); + }, + toCell(self: TokenPool_DeployableCodeSet): c.Cell { + return makeCellFrom(self, TokenPool_DeployableCodeSet.store); + } +} + +/** + > struct (0x84384142) TokenPool_SetAllowedDepositNamespaces { + > queryId: uint64 + > allowedDepositNamespaces: map + > } + */ +export interface TokenPool_SetAllowedDepositNamespaces { + readonly $: 'TokenPool_SetAllowedDepositNamespaces' + queryId: uint64 + allowedDepositNamespaces: Map +} + +export const TokenPool_SetAllowedDepositNamespaces = { + PREFIX: 0x84384142, + + create(args: { + queryId?: uint64 + allowedDepositNamespaces: Map + }): TokenPool_SetAllowedDepositNamespaces { + return { + $: 'TokenPool_SetAllowedDepositNamespaces', + ...args, + queryId: args.queryId ?? 0n + } + }, + fromSlice(s: c.Slice): TokenPool_SetAllowedDepositNamespaces { + loadAndCheckPrefix32(s, 0x84384142, 'TokenPool_SetAllowedDepositNamespaces'); + return { + $: 'TokenPool_SetAllowedDepositNamespaces', + queryId: s.loadUintBig(64), + allowedDepositNamespaces: dictToMap(c.Dictionary.load(c.Dictionary.Keys.BigUint(32), c.Dictionary.Values.Bool(), s)), + } + }, + store(self: TokenPool_SetAllowedDepositNamespaces, b: c.Builder): void { + b.storeUint(0x84384142, 32); + b.storeUint(self.queryId, 64); + b.storeDict(mapToDict(self.allowedDepositNamespaces, c.Dictionary.Keys.BigUint(32), c.Dictionary.Values.Bool()), c.Dictionary.Keys.BigUint(32), c.Dictionary.Values.Bool()); + }, + toCell(self: TokenPool_SetAllowedDepositNamespaces): c.Cell { + return makeCellFrom(self, TokenPool_SetAllowedDepositNamespaces.store); + } +} + +/** + > struct (0xc1ffe3a6) TokenPool_AllowedDepositNamespacesSet { + > queryId: uint64 + > } + */ +export interface TokenPool_AllowedDepositNamespacesSet { + readonly $: 'TokenPool_AllowedDepositNamespacesSet' + queryId: uint64 +} + +export const TokenPool_AllowedDepositNamespacesSet = { + PREFIX: 0xc1ffe3a6, + + create(args: { + queryId?: uint64 + }): TokenPool_AllowedDepositNamespacesSet { + return { + $: 'TokenPool_AllowedDepositNamespacesSet', + ...args, + queryId: args.queryId ?? 0n + } + }, + fromSlice(s: c.Slice): TokenPool_AllowedDepositNamespacesSet { + loadAndCheckPrefix32(s, 0xc1ffe3a6, 'TokenPool_AllowedDepositNamespacesSet'); + return { + $: 'TokenPool_AllowedDepositNamespacesSet', + queryId: s.loadUintBig(64), + } + }, + store(self: TokenPool_AllowedDepositNamespacesSet, b: c.Builder): void { + b.storeUint(0xc1ffe3a6, 32); + b.storeUint(self.queryId, 64); + }, + toCell(self: TokenPool_AllowedDepositNamespacesSet): c.Cell { + return makeCellFrom(self, TokenPool_AllowedDepositNamespacesSet.store); + } +} + +/** + > struct (0x4fe2d26c) TokenPool_SetRateLimitConfig { + > queryId: uint64 + > updates: SnakedCell + > } + */ +export interface TokenPool_SetRateLimitConfig { + readonly $: 'TokenPool_SetRateLimitConfig' + queryId: uint64 + updates: SnakedCell +} + +export const TokenPool_SetRateLimitConfig = { + PREFIX: 0x4fe2d26c, + + create(args: { + queryId?: uint64 + updates: SnakedCell + }): TokenPool_SetRateLimitConfig { + return { + $: 'TokenPool_SetRateLimitConfig', + ...args, + queryId: args.queryId ?? 0n + } + }, + fromSlice(s: c.Slice): TokenPool_SetRateLimitConfig { + loadAndCheckPrefix32(s, 0x4fe2d26c, 'TokenPool_SetRateLimitConfig'); + return { + $: 'TokenPool_SetRateLimitConfig', + queryId: s.loadUintBig(64), + updates: loadSnakedCellOf(s, TokenPool_RateLimitConfigArgs.fromSlice), + } + }, + store(self: TokenPool_SetRateLimitConfig, b: c.Builder): void { + b.storeUint(0x4fe2d26c, 32); + b.storeUint(self.queryId, 64); + storeSnakedCellOf(self.updates, b, TokenPool_RateLimitConfigArgs.store); + }, + toCell(self: TokenPool_SetRateLimitConfig): c.Cell { + return makeCellFrom(self, TokenPool_SetRateLimitConfig.store); + } +} + +/** + > struct (0x30a1d1f7) TokenPool_ApplyTokenTransferFeeConfigUpdates { + > queryId: uint64 + > updates: SnakedCell + > disableChainSelectors: SnakedCell + > } + */ +export interface TokenPool_ApplyTokenTransferFeeConfigUpdates { + readonly $: 'TokenPool_ApplyTokenTransferFeeConfigUpdates' + queryId: uint64 + updates: SnakedCell + disableChainSelectors: SnakedCell +} + +export const TokenPool_ApplyTokenTransferFeeConfigUpdates = { + PREFIX: 0x30a1d1f7, + + create(args: { + queryId?: uint64 + updates: SnakedCell + disableChainSelectors: SnakedCell + }): TokenPool_ApplyTokenTransferFeeConfigUpdates { + return { + $: 'TokenPool_ApplyTokenTransferFeeConfigUpdates', + ...args, + queryId: args.queryId ?? 0n + } + }, + fromSlice(s: c.Slice): TokenPool_ApplyTokenTransferFeeConfigUpdates { + loadAndCheckPrefix32(s, 0x30a1d1f7, 'TokenPool_ApplyTokenTransferFeeConfigUpdates'); + return { + $: 'TokenPool_ApplyTokenTransferFeeConfigUpdates', + queryId: s.loadUintBig(64), + updates: loadSnakedCellOf(s, TokenPool_TokenTransferFeeConfigArgs.fromSlice), + disableChainSelectors: loadSnakedCellOf(s, (s) => s.loadUintBig(64)), + } + }, + store(self: TokenPool_ApplyTokenTransferFeeConfigUpdates, b: c.Builder): void { + b.storeUint(0x30a1d1f7, 32); + b.storeUint(self.queryId, 64); + storeSnakedCellOf(self.updates, b, TokenPool_TokenTransferFeeConfigArgs.store); + storeSnakedCellOf(self.disableChainSelectors, b, (v, b) => b.storeUint(v, 64)); + }, + toCell(self: TokenPool_ApplyTokenTransferFeeConfigUpdates): c.Cell { + return makeCellFrom(self, TokenPool_ApplyTokenTransferFeeConfigUpdates.store); + } +} + +/** + > struct (0x9929b642) TokenPool_SetRMNProxy { + > queryId: uint64 + > rmnProxy: address? + > } + */ +export interface TokenPool_SetRMNProxy { + readonly $: 'TokenPool_SetRMNProxy' + queryId: uint64 + rmnProxy: c.Address | null +} + +export const TokenPool_SetRMNProxy = { + PREFIX: 0x9929b642, + + create(args: { + queryId?: uint64 + rmnProxy: c.Address | null + }): TokenPool_SetRMNProxy { + return { + $: 'TokenPool_SetRMNProxy', + ...args, + queryId: args.queryId ?? 0n + } + }, + fromSlice(s: c.Slice): TokenPool_SetRMNProxy { + loadAndCheckPrefix32(s, 0x9929b642, 'TokenPool_SetRMNProxy'); + return { + $: 'TokenPool_SetRMNProxy', + queryId: s.loadUintBig(64), + rmnProxy: s.loadMaybeAddress(), + } + }, + store(self: TokenPool_SetRMNProxy, b: c.Builder): void { + b.storeUint(0x9929b642, 32); + b.storeUint(self.queryId, 64); + b.storeAddress(self.rmnProxy); + }, + toCell(self: TokenPool_SetRMNProxy): c.Cell { + return makeCellFrom(self, TokenPool_SetRMNProxy.store); + } +} + +/** + > struct (0x9da4da09) TokenPool_SetCursedSubjects { + > queryId: uint64 + > cursedSubjects: CursedSubjects + > } + */ +export interface TokenPool_SetCursedSubjects { + readonly $: 'TokenPool_SetCursedSubjects' + queryId: uint64 + cursedSubjects: CursedSubjects +} + +export const TokenPool_SetCursedSubjects = { + PREFIX: 0x9da4da09, + + create(args: { + queryId?: uint64 + cursedSubjects: CursedSubjects + }): TokenPool_SetCursedSubjects { + return { + $: 'TokenPool_SetCursedSubjects', + ...args, + queryId: args.queryId ?? 0n + } + }, + fromSlice(s: c.Slice): TokenPool_SetCursedSubjects { + loadAndCheckPrefix32(s, 0x9da4da09, 'TokenPool_SetCursedSubjects'); + return { + $: 'TokenPool_SetCursedSubjects', + queryId: s.loadUintBig(64), + cursedSubjects: CursedSubjects.fromSlice(s), + } + }, + store(self: TokenPool_SetCursedSubjects, b: c.Builder): void { + b.storeUint(0x9da4da09, 32); + b.storeUint(self.queryId, 64); + CursedSubjects.store(self.cursedSubjects, b); + }, + toCell(self: TokenPool_SetCursedSubjects): c.Cell { + return makeCellFrom(self, TokenPool_SetCursedSubjects.store); + } +} + +/** + > struct (0xfa7da444) TokenPool_LockOrBurn { + > queryId: uint64 + > request: Cell + > requestedFinalityConfig: uint32 + > tokenArgs: cell? + > replyTo: address? + > } + */ +export interface TokenPool_LockOrBurn { + readonly $: 'TokenPool_LockOrBurn' + queryId: uint64 + request: TokenPool_LockOrBurnInV1 + requestedFinalityConfig: uint32 + tokenArgs: c.Cell | null + replyTo: c.Address | null +} + +export const TokenPool_LockOrBurn = { + PREFIX: 0xfa7da444, + + create(args: { + queryId?: uint64 + request: TokenPool_LockOrBurnInV1 + requestedFinalityConfig: uint32 + tokenArgs: c.Cell | null + replyTo: c.Address | null + }): TokenPool_LockOrBurn { + return { + $: 'TokenPool_LockOrBurn', + ...args, + queryId: args.queryId ?? 0n + } + }, + fromSlice(s: c.Slice): TokenPool_LockOrBurn { + loadAndCheckPrefix32(s, 0xfa7da444, 'TokenPool_LockOrBurn'); + return { + $: 'TokenPool_LockOrBurn', + queryId: s.loadUintBig(64), + request: loadCellRef(s, TokenPool_LockOrBurnInV1.fromSlice), + requestedFinalityConfig: s.loadUintBig(32), + tokenArgs: s.loadBoolean() ? s.loadRef() : null, + replyTo: s.loadMaybeAddress(), + } + }, + store(self: TokenPool_LockOrBurn, b: c.Builder): void { + b.storeUint(0xfa7da444, 32); + b.storeUint(self.queryId, 64); + storeCellRef(self.request, b, TokenPool_LockOrBurnInV1.store); + b.storeUint(self.requestedFinalityConfig, 32); + storeTolkNullable(self.tokenArgs, b, + (v,b) => b.storeRef(v) + ); + b.storeAddress(self.replyTo); + }, + toCell(self: TokenPool_LockOrBurn): c.Cell { + return makeCellFrom(self, TokenPool_LockOrBurn.store); + } +} + +/** + > struct TokenPool_LockOrBurnForwardPayload { + > originalSender: address + > requestMsg: Cell + > prepared: Cell + > } + */ +export interface TokenPool_LockOrBurnForwardPayload { + readonly $: 'TokenPool_LockOrBurnForwardPayload' + originalSender: c.Address + requestMsg: TokenPool_LockOrBurn + prepared: TokenPool_LockOrBurnPrepared +} + +export const TokenPool_LockOrBurnForwardPayload = { + create(args: { + originalSender: c.Address + requestMsg: TokenPool_LockOrBurn + prepared: TokenPool_LockOrBurnPrepared + }): TokenPool_LockOrBurnForwardPayload { + return { + $: 'TokenPool_LockOrBurnForwardPayload', + ...args + } + }, + fromSlice(s: c.Slice): TokenPool_LockOrBurnForwardPayload { + return { + $: 'TokenPool_LockOrBurnForwardPayload', + originalSender: s.loadAddress(), + requestMsg: loadCellRef(s, TokenPool_LockOrBurn.fromSlice), + prepared: loadCellRef(s, TokenPool_LockOrBurnPrepared.fromSlice), + } + }, + store(self: TokenPool_LockOrBurnForwardPayload, b: c.Builder): void { + b.storeAddress(self.originalSender); + storeCellRef(self.requestMsg, b, TokenPool_LockOrBurn.store); + storeCellRef(self.prepared, b, TokenPool_LockOrBurnPrepared.store); + }, + toCell(self: TokenPool_LockOrBurnForwardPayload): c.Cell { + return makeCellFrom(self, TokenPool_LockOrBurnForwardPayload.store); + } +} + +/** + > struct (0x351f77e3) TokenPool_ReleaseOrMint { + > queryId: uint64 + > request: Cell + > requestedFinalityConfig: uint32 + > replyTo: address? + > } + */ +export interface TokenPool_ReleaseOrMint { + readonly $: 'TokenPool_ReleaseOrMint' + queryId: uint64 + request: TokenPool_ReleaseOrMintInV1 + requestedFinalityConfig: uint32 + replyTo: c.Address | null /* = null */ +} + +export const TokenPool_ReleaseOrMint = { + PREFIX: 0x351f77e3, + + create(args: { + queryId?: uint64 + request: TokenPool_ReleaseOrMintInV1 + requestedFinalityConfig: uint32 + replyTo?: c.Address | null /* = null */ + }): TokenPool_ReleaseOrMint { + return { + $: 'TokenPool_ReleaseOrMint', + replyTo: null, + ...args, + queryId: args.queryId ?? 0n + } + }, + fromSlice(s: c.Slice): TokenPool_ReleaseOrMint { + loadAndCheckPrefix32(s, 0x351f77e3, 'TokenPool_ReleaseOrMint'); + return { + $: 'TokenPool_ReleaseOrMint', + queryId: s.loadUintBig(64), + request: loadCellRef(s, TokenPool_ReleaseOrMintInV1.fromSlice), + requestedFinalityConfig: s.loadUintBig(32), + replyTo: s.loadMaybeAddress(), + } + }, + store(self: TokenPool_ReleaseOrMint, b: c.Builder): void { + b.storeUint(0x351f77e3, 32); + b.storeUint(self.queryId, 64); + storeCellRef(self.request, b, TokenPool_ReleaseOrMintInV1.store); + b.storeUint(self.requestedFinalityConfig, 32); + b.storeAddress(self.replyTo); + }, + toCell(self: TokenPool_ReleaseOrMint): c.Cell { + return makeCellFrom(self, TokenPool_ReleaseOrMint.store); + } +} + +/** + > struct (0x08f2ffb7) TokenPool_PreflightCheckFinished { + > queryId: uint64 + > forwardPayload: Cell + > } + */ +export interface TokenPool_PreflightCheckFinished { + readonly $: 'TokenPool_PreflightCheckFinished' + queryId: uint64 + forwardPayload: TokenPool_LockOrBurnForwardPayload +} + +export const TokenPool_PreflightCheckFinished = { + PREFIX: 0x08f2ffb7, + + create(args: { + queryId?: uint64 + forwardPayload: TokenPool_LockOrBurnForwardPayload + }): TokenPool_PreflightCheckFinished { + return { + $: 'TokenPool_PreflightCheckFinished', + ...args, + queryId: args.queryId ?? 0n + } + }, + fromSlice(s: c.Slice): TokenPool_PreflightCheckFinished { + loadAndCheckPrefix32(s, 0x08f2ffb7, 'TokenPool_PreflightCheckFinished'); + return { + $: 'TokenPool_PreflightCheckFinished', + queryId: s.loadUintBig(64), + forwardPayload: loadCellRef(s, TokenPool_LockOrBurnForwardPayload.fromSlice), + } + }, + store(self: TokenPool_PreflightCheckFinished, b: c.Builder): void { + b.storeUint(0x08f2ffb7, 32); + b.storeUint(self.queryId, 64); + storeCellRef(self.forwardPayload, b, TokenPool_LockOrBurnForwardPayload.store); + }, + toCell(self: TokenPool_PreflightCheckFinished): c.Cell { + return makeCellFrom(self, TokenPool_PreflightCheckFinished.store); + } +} + +/** + > struct (0xa6dfa623) TokenPool_PreflightCheckFailed { + > queryId: uint64 + > forwardPayload: Cell + > } + */ +export interface TokenPool_PreflightCheckFailed { + readonly $: 'TokenPool_PreflightCheckFailed' + queryId: uint64 + forwardPayload: TokenPool_LockOrBurnForwardPayload +} + +export const TokenPool_PreflightCheckFailed = { + PREFIX: 0xa6dfa623, + + create(args: { + queryId?: uint64 + forwardPayload: TokenPool_LockOrBurnForwardPayload + }): TokenPool_PreflightCheckFailed { + return { + $: 'TokenPool_PreflightCheckFailed', + ...args, + queryId: args.queryId ?? 0n + } + }, + fromSlice(s: c.Slice): TokenPool_PreflightCheckFailed { + loadAndCheckPrefix32(s, 0xa6dfa623, 'TokenPool_PreflightCheckFailed'); + return { + $: 'TokenPool_PreflightCheckFailed', + queryId: s.loadUintBig(64), + forwardPayload: loadCellRef(s, TokenPool_LockOrBurnForwardPayload.fromSlice), + } + }, + store(self: TokenPool_PreflightCheckFailed, b: c.Builder): void { + b.storeUint(0xa6dfa623, 32); + b.storeUint(self.queryId, 64); + storeCellRef(self.forwardPayload, b, TokenPool_LockOrBurnForwardPayload.store); + }, + toCell(self: TokenPool_PreflightCheckFailed): c.Cell { + return makeCellFrom(self, TokenPool_PreflightCheckFailed.store); + } +} + +/** + > struct TokenPool_ReleaseOrMintForwardPayload { + > originalSender: address + > requestMsg: Cell + > prepared: Cell + > } + */ +export interface TokenPool_ReleaseOrMintForwardPayload { + readonly $: 'TokenPool_ReleaseOrMintForwardPayload' + originalSender: c.Address + requestMsg: TokenPool_ReleaseOrMint + prepared: TokenPool_ReleaseOrMintPrepared +} + +export const TokenPool_ReleaseOrMintForwardPayload = { + create(args: { + originalSender: c.Address + requestMsg: TokenPool_ReleaseOrMint + prepared: TokenPool_ReleaseOrMintPrepared + }): TokenPool_ReleaseOrMintForwardPayload { + return { + $: 'TokenPool_ReleaseOrMintForwardPayload', + ...args + } + }, + fromSlice(s: c.Slice): TokenPool_ReleaseOrMintForwardPayload { + return { + $: 'TokenPool_ReleaseOrMintForwardPayload', + originalSender: s.loadAddress(), + requestMsg: loadCellRef(s, TokenPool_ReleaseOrMint.fromSlice), + prepared: loadCellRef(s, TokenPool_ReleaseOrMintPrepared.fromSlice), + } + }, + store(self: TokenPool_ReleaseOrMintForwardPayload, b: c.Builder): void { + b.storeAddress(self.originalSender); + storeCellRef(self.requestMsg, b, TokenPool_ReleaseOrMint.store); + storeCellRef(self.prepared, b, TokenPool_ReleaseOrMintPrepared.store); + }, + toCell(self: TokenPool_ReleaseOrMintForwardPayload): c.Cell { + return makeCellFrom(self, TokenPool_ReleaseOrMintForwardPayload.store); + } +} + +/** + > struct (0x9e2a6b66) TokenPool_PostflightCheckFinished { + > queryId: uint64 + > forwardPayload: Cell + > } + */ +export interface TokenPool_PostflightCheckFinished { + readonly $: 'TokenPool_PostflightCheckFinished' + queryId: uint64 + forwardPayload: TokenPool_ReleaseOrMintForwardPayload +} + +export const TokenPool_PostflightCheckFinished = { + PREFIX: 0x9e2a6b66, + + create(args: { + queryId?: uint64 + forwardPayload: TokenPool_ReleaseOrMintForwardPayload + }): TokenPool_PostflightCheckFinished { + return { + $: 'TokenPool_PostflightCheckFinished', + ...args, + queryId: args.queryId ?? 0n + } + }, + fromSlice(s: c.Slice): TokenPool_PostflightCheckFinished { + loadAndCheckPrefix32(s, 0x9e2a6b66, 'TokenPool_PostflightCheckFinished'); + return { + $: 'TokenPool_PostflightCheckFinished', + queryId: s.loadUintBig(64), + forwardPayload: loadCellRef(s, TokenPool_ReleaseOrMintForwardPayload.fromSlice), + } + }, + store(self: TokenPool_PostflightCheckFinished, b: c.Builder): void { + b.storeUint(0x9e2a6b66, 32); + b.storeUint(self.queryId, 64); + storeCellRef(self.forwardPayload, b, TokenPool_ReleaseOrMintForwardPayload.store); + }, + toCell(self: TokenPool_PostflightCheckFinished): c.Cell { + return makeCellFrom(self, TokenPool_PostflightCheckFinished.store); + } +} + +/** + > struct (0x21e71d87) TokenPool_PostflightCheckFailed { + > queryId: uint64 + > forwardPayload: Cell + > } + */ +export interface TokenPool_PostflightCheckFailed { + readonly $: 'TokenPool_PostflightCheckFailed' + queryId: uint64 + forwardPayload: TokenPool_ReleaseOrMintForwardPayload +} + +export const TokenPool_PostflightCheckFailed = { + PREFIX: 0x21e71d87, + + create(args: { + queryId?: uint64 + forwardPayload: TokenPool_ReleaseOrMintForwardPayload + }): TokenPool_PostflightCheckFailed { + return { + $: 'TokenPool_PostflightCheckFailed', + ...args, + queryId: args.queryId ?? 0n + } + }, + fromSlice(s: c.Slice): TokenPool_PostflightCheckFailed { + loadAndCheckPrefix32(s, 0x21e71d87, 'TokenPool_PostflightCheckFailed'); + return { + $: 'TokenPool_PostflightCheckFailed', + queryId: s.loadUintBig(64), + forwardPayload: loadCellRef(s, TokenPool_ReleaseOrMintForwardPayload.fromSlice), + } + }, + store(self: TokenPool_PostflightCheckFailed, b: c.Builder): void { + b.storeUint(0x21e71d87, 32); + b.storeUint(self.queryId, 64); + storeCellRef(self.forwardPayload, b, TokenPool_ReleaseOrMintForwardPayload.store); + }, + toCell(self: TokenPool_PostflightCheckFailed): c.Cell { + return makeCellFrom(self, TokenPool_PostflightCheckFailed.store); + } +} + +/** + > struct (0x4129d109) TokenPool_PreflightCheck { + > queryId: uint64 + > request: Cell + > requestedFinalityConfig: uint32 + > tokenArgs: cell? + > amountPostFee: coins + > replyTo: address + > replyPayload: cell? + > } + */ +export interface TokenPool_PreflightCheck { + readonly $: 'TokenPool_PreflightCheck' + queryId: uint64 + request: TokenPool_LockOrBurnInV1 + requestedFinalityConfig: uint32 + tokenArgs: c.Cell | null + amountPostFee: coins + replyTo: c.Address + replyPayload: c.Cell | null +} + +export const TokenPool_PreflightCheck = { + PREFIX: 0x4129d109, + + create(args: { + queryId?: uint64 + request: TokenPool_LockOrBurnInV1 + requestedFinalityConfig: uint32 + tokenArgs: c.Cell | null + amountPostFee: coins + replyTo: c.Address + replyPayload: c.Cell | null + }): TokenPool_PreflightCheck { + return { + $: 'TokenPool_PreflightCheck', + ...args, + queryId: args.queryId ?? 0n + } + }, + fromSlice(s: c.Slice): TokenPool_PreflightCheck { + loadAndCheckPrefix32(s, 0x4129d109, 'TokenPool_PreflightCheck'); + return { + $: 'TokenPool_PreflightCheck', + queryId: s.loadUintBig(64), + request: loadCellRef(s, TokenPool_LockOrBurnInV1.fromSlice), + requestedFinalityConfig: s.loadUintBig(32), + tokenArgs: s.loadBoolean() ? s.loadRef() : null, + amountPostFee: s.loadCoins(), + replyTo: s.loadAddress(), + replyPayload: s.loadBoolean() ? s.loadRef() : null, + } + }, + store(self: TokenPool_PreflightCheck, b: c.Builder): void { + b.storeUint(0x4129d109, 32); + b.storeUint(self.queryId, 64); + storeCellRef(self.request, b, TokenPool_LockOrBurnInV1.store); + b.storeUint(self.requestedFinalityConfig, 32); + storeTolkNullable(self.tokenArgs, b, + (v,b) => b.storeRef(v) + ); + b.storeCoins(self.amountPostFee); + b.storeAddress(self.replyTo); + storeTolkNullable(self.replyPayload, b, + (v,b) => b.storeRef(v) + ); + }, + toCell(self: TokenPool_PreflightCheck): c.Cell { + return makeCellFrom(self, TokenPool_PreflightCheck.store); + } +} + +/** + > struct (0x703c2b58) TokenPool_PostflightCheck { + > queryId: uint64 + > request: Cell + > localAmount: coins + > requestedFinalityConfig: uint32 + > replyTo: address + > replyPayload: cell? + > } + */ +export interface TokenPool_PostflightCheck { + readonly $: 'TokenPool_PostflightCheck' + queryId: uint64 + request: TokenPool_ReleaseOrMintInV1 + localAmount: coins + requestedFinalityConfig: uint32 + replyTo: c.Address + replyPayload: c.Cell | null +} + +export const TokenPool_PostflightCheck = { + PREFIX: 0x703c2b58, + + create(args: { + queryId?: uint64 + request: TokenPool_ReleaseOrMintInV1 + localAmount: coins + requestedFinalityConfig: uint32 + replyTo: c.Address + replyPayload: c.Cell | null + }): TokenPool_PostflightCheck { + return { + $: 'TokenPool_PostflightCheck', + ...args, + queryId: args.queryId ?? 0n + } + }, + fromSlice(s: c.Slice): TokenPool_PostflightCheck { + loadAndCheckPrefix32(s, 0x703c2b58, 'TokenPool_PostflightCheck'); + return { + $: 'TokenPool_PostflightCheck', + queryId: s.loadUintBig(64), + request: loadCellRef(s, TokenPool_ReleaseOrMintInV1.fromSlice), + localAmount: s.loadCoins(), + requestedFinalityConfig: s.loadUintBig(32), + replyTo: s.loadAddress(), + replyPayload: s.loadBoolean() ? s.loadRef() : null, + } + }, + store(self: TokenPool_PostflightCheck, b: c.Builder): void { + b.storeUint(0x703c2b58, 32); + b.storeUint(self.queryId, 64); + storeCellRef(self.request, b, TokenPool_ReleaseOrMintInV1.store); + b.storeCoins(self.localAmount); + b.storeUint(self.requestedFinalityConfig, 32); + b.storeAddress(self.replyTo); + storeTolkNullable(self.replyPayload, b, + (v,b) => b.storeRef(v) + ); + }, + toCell(self: TokenPool_PostflightCheck): c.Cell { + return makeCellFrom(self, TokenPool_PostflightCheck.store); + } +} + +/** + > struct (0xc5476d2b) TokenPool_GetCCVs { + > queryId: uint64 + > localToken: address + > remoteChainSelector: uint64 + > amount: coins + > requestedFinalityConfig: uint32 + > direction: uint8 + > extraData: cell? + > replyTo: address + > forwardPayload: cell? + > } + */ +export interface TokenPool_GetCCVs { + readonly $: 'TokenPool_GetCCVs' + queryId: uint64 + localToken: c.Address + remoteChainSelector: uint64 + amount: coins + requestedFinalityConfig: uint32 + direction: uint8 + extraData: c.Cell | null + replyTo: c.Address + forwardPayload: c.Cell | null +} + +export const TokenPool_GetCCVs = { + PREFIX: 0xc5476d2b, + + create(args: { + queryId?: uint64 + localToken: c.Address + remoteChainSelector: uint64 + amount: coins + requestedFinalityConfig: uint32 + direction: uint8 + extraData: c.Cell | null + replyTo: c.Address + forwardPayload: c.Cell | null + }): TokenPool_GetCCVs { + return { + $: 'TokenPool_GetCCVs', + ...args, + queryId: args.queryId ?? 0n + } + }, + fromSlice(s: c.Slice): TokenPool_GetCCVs { + loadAndCheckPrefix32(s, 0xc5476d2b, 'TokenPool_GetCCVs'); + return { + $: 'TokenPool_GetCCVs', + queryId: s.loadUintBig(64), + localToken: s.loadAddress(), + remoteChainSelector: s.loadUintBig(64), + amount: s.loadCoins(), + requestedFinalityConfig: s.loadUintBig(32), + direction: s.loadUintBig(8), + extraData: s.loadBoolean() ? s.loadRef() : null, + replyTo: s.loadAddress(), + forwardPayload: s.loadBoolean() ? s.loadRef() : null, + } + }, + store(self: TokenPool_GetCCVs, b: c.Builder): void { + b.storeUint(0xc5476d2b, 32); + b.storeUint(self.queryId, 64); + b.storeAddress(self.localToken); + b.storeUint(self.remoteChainSelector, 64); + b.storeCoins(self.amount); + b.storeUint(self.requestedFinalityConfig, 32); + b.storeUint(self.direction, 8); + storeTolkNullable(self.extraData, b, + (v,b) => b.storeRef(v) + ); + b.storeAddress(self.replyTo); + storeTolkNullable(self.forwardPayload, b, + (v,b) => b.storeRef(v) + ); + }, + toCell(self: TokenPool_GetCCVs): c.Cell { + return makeCellFrom(self, TokenPool_GetCCVs.store); + } +} + +/** + > struct (0xd22944d5) TokenPool_GetCCVsAndFees { + > queryId: uint64 + > localToken: address + > remoteChainSelector: uint64 + > amount: coins + > requestedFinalityConfig: uint32 + > direction: uint8 + > extraData: cell? + > forwardPayload: cell? + > } + */ +export interface TokenPool_GetCCVsAndFees { + readonly $: 'TokenPool_GetCCVsAndFees' + queryId: uint64 + localToken: c.Address + remoteChainSelector: uint64 + amount: coins + requestedFinalityConfig: uint32 + direction: uint8 + extraData: c.Cell | null + forwardPayload: c.Cell | null +} + +export const TokenPool_GetCCVsAndFees = { + PREFIX: 0xd22944d5, + + create(args: { + queryId?: uint64 + localToken: c.Address + remoteChainSelector: uint64 + amount: coins + requestedFinalityConfig: uint32 + direction: uint8 + extraData: c.Cell | null + forwardPayload: c.Cell | null + }): TokenPool_GetCCVsAndFees { + return { + $: 'TokenPool_GetCCVsAndFees', + ...args, + queryId: args.queryId ?? 0n + } + }, + fromSlice(s: c.Slice): TokenPool_GetCCVsAndFees { + loadAndCheckPrefix32(s, 0xd22944d5, 'TokenPool_GetCCVsAndFees'); + return { + $: 'TokenPool_GetCCVsAndFees', + queryId: s.loadUintBig(64), + localToken: s.loadAddress(), + remoteChainSelector: s.loadUintBig(64), + amount: s.loadCoins(), + requestedFinalityConfig: s.loadUintBig(32), + direction: s.loadUintBig(8), + extraData: s.loadBoolean() ? s.loadRef() : null, + forwardPayload: s.loadBoolean() ? s.loadRef() : null, + } + }, + store(self: TokenPool_GetCCVsAndFees, b: c.Builder): void { + b.storeUint(0xd22944d5, 32); + b.storeUint(self.queryId, 64); + b.storeAddress(self.localToken); + b.storeUint(self.remoteChainSelector, 64); + b.storeCoins(self.amount); + b.storeUint(self.requestedFinalityConfig, 32); + b.storeUint(self.direction, 8); + storeTolkNullable(self.extraData, b, + (v,b) => b.storeRef(v) + ); + storeTolkNullable(self.forwardPayload, b, + (v,b) => b.storeRef(v) + ); + }, + toCell(self: TokenPool_GetCCVsAndFees): c.Cell { + return makeCellFrom(self, TokenPool_GetCCVsAndFees.store); + } +} + +/** + > struct (0x30612b17) TokenPool_QueryCCVsReply { + > queryId: uint64 + > requiredCCVs: SnakedCell
+ > replyPayload: cell? + > } + */ +export interface TokenPool_QueryCCVsReply { + readonly $: 'TokenPool_QueryCCVsReply' + queryId: uint64 + requiredCCVs: SnakedCell + replyPayload: c.Cell | null +} + +export const TokenPool_QueryCCVsReply = { + PREFIX: 0x30612b17, + + create(args: { + queryId?: uint64 + requiredCCVs: SnakedCell + replyPayload: c.Cell | null + }): TokenPool_QueryCCVsReply { + return { + $: 'TokenPool_QueryCCVsReply', + ...args, + queryId: args.queryId ?? 0n + } + }, + fromSlice(s: c.Slice): TokenPool_QueryCCVsReply { + loadAndCheckPrefix32(s, 0x30612b17, 'TokenPool_QueryCCVsReply'); + return { + $: 'TokenPool_QueryCCVsReply', + queryId: s.loadUintBig(64), + requiredCCVs: loadSnakedCellOf(s, (s) => s.loadAddress()), + replyPayload: s.loadBoolean() ? s.loadRef() : null, + } + }, + store(self: TokenPool_QueryCCVsReply, b: c.Builder): void { + b.storeUint(0x30612b17, 32); + b.storeUint(self.queryId, 64); + storeSnakedCellOf(self.requiredCCVs, b, (v, b) => b.storeAddress(v)); + storeTolkNullable(self.replyPayload, b, + (v,b) => b.storeRef(v) + ); + }, + toCell(self: TokenPool_QueryCCVsReply): c.Cell { + return makeCellFrom(self, TokenPool_QueryCCVsReply.store); + } +} + +/** + > struct (0xe7a35041) TokenPool_LockOrBurnWithdraw { + > queryId: uint64 + > forwardPayload: TokenPool_LockOrBurnForwardPayload + > } + */ +export interface TokenPool_LockOrBurnWithdraw { + readonly $: 'TokenPool_LockOrBurnWithdraw' + queryId: uint64 + forwardPayload: TokenPool_LockOrBurnForwardPayload +} + +export const TokenPool_LockOrBurnWithdraw = { + PREFIX: 0xe7a35041, + + create(args: { + queryId?: uint64 + forwardPayload: TokenPool_LockOrBurnForwardPayload + }): TokenPool_LockOrBurnWithdraw { + return { + $: 'TokenPool_LockOrBurnWithdraw', + ...args, + queryId: args.queryId ?? 0n + } + }, + fromSlice(s: c.Slice): TokenPool_LockOrBurnWithdraw { + loadAndCheckPrefix32(s, 0xe7a35041, 'TokenPool_LockOrBurnWithdraw'); + return { + $: 'TokenPool_LockOrBurnWithdraw', + queryId: s.loadUintBig(64), + forwardPayload: TokenPool_LockOrBurnForwardPayload.fromSlice(s), + } + }, + store(self: TokenPool_LockOrBurnWithdraw, b: c.Builder): void { + b.storeUint(0xe7a35041, 32); + b.storeUint(self.queryId, 64); + TokenPool_LockOrBurnForwardPayload.store(self.forwardPayload, b); + }, + toCell(self: TokenPool_LockOrBurnWithdraw): c.Cell { + return makeCellFrom(self, TokenPool_LockOrBurnWithdraw.store); + } +} + +/** + > struct (0xf432a4e3) TokenPool_LockOrBurnFinished { + > queryId: uint64 + > out: Cell + > destTokenAmount: coins + > } + */ +export interface TokenPool_LockOrBurnFinished { + readonly $: 'TokenPool_LockOrBurnFinished' + queryId: uint64 + out: TokenPool_LockOrBurnOutV1 + destTokenAmount: coins +} + +export const TokenPool_LockOrBurnFinished = { + PREFIX: 0xf432a4e3, + + create(args: { + queryId?: uint64 + out: TokenPool_LockOrBurnOutV1 + destTokenAmount: coins + }): TokenPool_LockOrBurnFinished { + return { + $: 'TokenPool_LockOrBurnFinished', + ...args, + queryId: args.queryId ?? 0n + } + }, + fromSlice(s: c.Slice): TokenPool_LockOrBurnFinished { + loadAndCheckPrefix32(s, 0xf432a4e3, 'TokenPool_LockOrBurnFinished'); + return { + $: 'TokenPool_LockOrBurnFinished', + queryId: s.loadUintBig(64), + out: loadCellRef(s, TokenPool_LockOrBurnOutV1.fromSlice), + destTokenAmount: s.loadCoins(), + } + }, + store(self: TokenPool_LockOrBurnFinished, b: c.Builder): void { + b.storeUint(0xf432a4e3, 32); + b.storeUint(self.queryId, 64); + storeCellRef(self.out, b, TokenPool_LockOrBurnOutV1.store); + b.storeCoins(self.destTokenAmount); + }, + toCell(self: TokenPool_LockOrBurnFinished): c.Cell { + return makeCellFrom(self, TokenPool_LockOrBurnFinished.store); + } +} + +/** + > struct (0x3476ea72) TokenPool_LockOrBurnFailure { + > queryId: uint64 + > errorCode: uint16 + > } + */ +export interface TokenPool_LockOrBurnFailure { + readonly $: 'TokenPool_LockOrBurnFailure' + queryId: uint64 + errorCode: uint16 +} + +export const TokenPool_LockOrBurnFailure = { + PREFIX: 0x3476ea72, + + create(args: { + queryId?: uint64 + errorCode: uint16 + }): TokenPool_LockOrBurnFailure { + return { + $: 'TokenPool_LockOrBurnFailure', + ...args, + queryId: args.queryId ?? 0n + } + }, + fromSlice(s: c.Slice): TokenPool_LockOrBurnFailure { + loadAndCheckPrefix32(s, 0x3476ea72, 'TokenPool_LockOrBurnFailure'); + return { + $: 'TokenPool_LockOrBurnFailure', + queryId: s.loadUintBig(64), + errorCode: s.loadUintBig(16), + } + }, + store(self: TokenPool_LockOrBurnFailure, b: c.Builder): void { + b.storeUint(0x3476ea72, 32); + b.storeUint(self.queryId, 64); + b.storeUint(self.errorCode, 16); + }, + toCell(self: TokenPool_LockOrBurnFailure): c.Cell { + return makeCellFrom(self, TokenPool_LockOrBurnFailure.store); + } +} + +/** + > struct (0xe0e882f5) TokenPool_ReleaseOrMintFinished { + > queryId: uint64 + > out: Cell + > } + */ +export interface TokenPool_ReleaseOrMintFinished { + readonly $: 'TokenPool_ReleaseOrMintFinished' + queryId: uint64 + out: TokenPool_ReleaseOrMintOutV1 +} + +export const TokenPool_ReleaseOrMintFinished = { + PREFIX: 0xe0e882f5, + + create(args: { + queryId?: uint64 + out: TokenPool_ReleaseOrMintOutV1 + }): TokenPool_ReleaseOrMintFinished { + return { + $: 'TokenPool_ReleaseOrMintFinished', + ...args, + queryId: args.queryId ?? 0n + } + }, + fromSlice(s: c.Slice): TokenPool_ReleaseOrMintFinished { + loadAndCheckPrefix32(s, 0xe0e882f5, 'TokenPool_ReleaseOrMintFinished'); + return { + $: 'TokenPool_ReleaseOrMintFinished', + queryId: s.loadUintBig(64), + out: loadCellRef(s, TokenPool_ReleaseOrMintOutV1.fromSlice), + } + }, + store(self: TokenPool_ReleaseOrMintFinished, b: c.Builder): void { + b.storeUint(0xe0e882f5, 32); + b.storeUint(self.queryId, 64); + storeCellRef(self.out, b, TokenPool_ReleaseOrMintOutV1.store); + }, + toCell(self: TokenPool_ReleaseOrMintFinished): c.Cell { + return makeCellFrom(self, TokenPool_ReleaseOrMintFinished.store); + } +} + +/** + > struct (0xef0cb36e) TokenPool_ReleaseOrMintFailure { + > queryId: uint64 + > errorCode: uint16 + > } + */ +export interface TokenPool_ReleaseOrMintFailure { + readonly $: 'TokenPool_ReleaseOrMintFailure' + queryId: uint64 + errorCode: uint16 +} + +export const TokenPool_ReleaseOrMintFailure = { + PREFIX: 0xef0cb36e, + + create(args: { + queryId?: uint64 + errorCode: uint16 + }): TokenPool_ReleaseOrMintFailure { + return { + $: 'TokenPool_ReleaseOrMintFailure', + ...args, + queryId: args.queryId ?? 0n + } + }, + fromSlice(s: c.Slice): TokenPool_ReleaseOrMintFailure { + loadAndCheckPrefix32(s, 0xef0cb36e, 'TokenPool_ReleaseOrMintFailure'); + return { + $: 'TokenPool_ReleaseOrMintFailure', + queryId: s.loadUintBig(64), + errorCode: s.loadUintBig(16), + } + }, + store(self: TokenPool_ReleaseOrMintFailure, b: c.Builder): void { + b.storeUint(0xef0cb36e, 32); + b.storeUint(self.queryId, 64); + b.storeUint(self.errorCode, 16); + }, + toCell(self: TokenPool_ReleaseOrMintFailure): c.Cell { + return makeCellFrom(self, TokenPool_ReleaseOrMintFailure.store); + } +} + +/** + > struct (0x12cc4985) TokenPool_RemotePoolAddedNotification { + > queryId: uint64 + > remoteChainSelector: uint64 + > remotePoolAddress: Cell + > } + */ +export interface TokenPool_RemotePoolAddedNotification { + readonly $: 'TokenPool_RemotePoolAddedNotification' + queryId: uint64 + remoteChainSelector: uint64 + remotePoolAddress: CrossChainAddress +} + +export const TokenPool_RemotePoolAddedNotification = { + PREFIX: 0x12cc4985, + + create(args: { + queryId?: uint64 + remoteChainSelector: uint64 + remotePoolAddress: CrossChainAddress + }): TokenPool_RemotePoolAddedNotification { + return { + $: 'TokenPool_RemotePoolAddedNotification', + ...args, + queryId: args.queryId ?? 0n + } + }, + fromSlice(s: c.Slice): TokenPool_RemotePoolAddedNotification { + loadAndCheckPrefix32(s, 0x12cc4985, 'TokenPool_RemotePoolAddedNotification'); + return { + $: 'TokenPool_RemotePoolAddedNotification', + queryId: s.loadUintBig(64), + remoteChainSelector: s.loadUintBig(64), + remotePoolAddress: loadCellRef(s, CrossChainAddress.fromSlice), + } + }, + store(self: TokenPool_RemotePoolAddedNotification, b: c.Builder): void { + b.storeUint(0x12cc4985, 32); + b.storeUint(self.queryId, 64); + b.storeUint(self.remoteChainSelector, 64); + storeCellRef(self.remotePoolAddress, b, CrossChainAddress.store); + }, + toCell(self: TokenPool_RemotePoolAddedNotification): c.Cell { + return makeCellFrom(self, TokenPool_RemotePoolAddedNotification.store); + } +} + +/** + > struct (0xe17bf3cc) TokenPool_RemotePoolRemovedNotification { + > queryId: uint64 + > remoteChainSelector: uint64 + > remotePoolAddress: Cell + > } + */ +export interface TokenPool_RemotePoolRemovedNotification { + readonly $: 'TokenPool_RemotePoolRemovedNotification' + queryId: uint64 + remoteChainSelector: uint64 + remotePoolAddress: CrossChainAddress +} + +export const TokenPool_RemotePoolRemovedNotification = { + PREFIX: 0xe17bf3cc, + + create(args: { + queryId?: uint64 + remoteChainSelector: uint64 + remotePoolAddress: CrossChainAddress + }): TokenPool_RemotePoolRemovedNotification { + return { + $: 'TokenPool_RemotePoolRemovedNotification', + ...args, + queryId: args.queryId ?? 0n + } + }, + fromSlice(s: c.Slice): TokenPool_RemotePoolRemovedNotification { + loadAndCheckPrefix32(s, 0xe17bf3cc, 'TokenPool_RemotePoolRemovedNotification'); + return { + $: 'TokenPool_RemotePoolRemovedNotification', + queryId: s.loadUintBig(64), + remoteChainSelector: s.loadUintBig(64), + remotePoolAddress: loadCellRef(s, CrossChainAddress.fromSlice), + } + }, + store(self: TokenPool_RemotePoolRemovedNotification, b: c.Builder): void { + b.storeUint(0xe17bf3cc, 32); + b.storeUint(self.queryId, 64); + b.storeUint(self.remoteChainSelector, 64); + storeCellRef(self.remotePoolAddress, b, CrossChainAddress.store); + }, + toCell(self: TokenPool_RemotePoolRemovedNotification): c.Cell { + return makeCellFrom(self, TokenPool_RemotePoolRemovedNotification.store); + } +} + +/** + > struct (0x426a713b) TokenPool_FinalityConfigSet { + > queryId: uint64 + > allowedFinalityConfig: uint32 + > } + */ +export interface TokenPool_FinalityConfigSet { + readonly $: 'TokenPool_FinalityConfigSet' + queryId: uint64 + allowedFinalityConfig: uint32 +} + +export const TokenPool_FinalityConfigSet = { + PREFIX: 0x426a713b, + + create(args: { + queryId?: uint64 + allowedFinalityConfig: uint32 + }): TokenPool_FinalityConfigSet { + return { + $: 'TokenPool_FinalityConfigSet', + ...args, + queryId: args.queryId ?? 0n + } + }, + fromSlice(s: c.Slice): TokenPool_FinalityConfigSet { + loadAndCheckPrefix32(s, 0x426a713b, 'TokenPool_FinalityConfigSet'); + return { + $: 'TokenPool_FinalityConfigSet', + queryId: s.loadUintBig(64), + allowedFinalityConfig: s.loadUintBig(32), + } + }, + store(self: TokenPool_FinalityConfigSet, b: c.Builder): void { + b.storeUint(0x426a713b, 32); + b.storeUint(self.queryId, 64); + b.storeUint(self.allowedFinalityConfig, 32); + }, + toCell(self: TokenPool_FinalityConfigSet): c.Cell { + return makeCellFrom(self, TokenPool_FinalityConfigSet.store); + } +} + +/** + > struct (0xb735e30c) TokenPool_DynamicConfigSet { + > queryId: uint64 + > router: address + > rateLimitAdmin: address? + > feeAdmin: address? + > } + */ +export interface TokenPool_DynamicConfigSet { + readonly $: 'TokenPool_DynamicConfigSet' + queryId: uint64 + router: c.Address + rateLimitAdmin: c.Address | null + feeAdmin: c.Address | null +} + +export const TokenPool_DynamicConfigSet = { + PREFIX: 0xb735e30c, + + create(args: { + queryId?: uint64 + router: c.Address + rateLimitAdmin: c.Address | null + feeAdmin: c.Address | null + }): TokenPool_DynamicConfigSet { + return { + $: 'TokenPool_DynamicConfigSet', + ...args, + queryId: args.queryId ?? 0n + } + }, + fromSlice(s: c.Slice): TokenPool_DynamicConfigSet { + loadAndCheckPrefix32(s, 0xb735e30c, 'TokenPool_DynamicConfigSet'); + return { + $: 'TokenPool_DynamicConfigSet', + queryId: s.loadUintBig(64), + router: s.loadAddress(), + rateLimitAdmin: s.loadMaybeAddress(), + feeAdmin: s.loadMaybeAddress(), + } + }, + store(self: TokenPool_DynamicConfigSet, b: c.Builder): void { + b.storeUint(0xb735e30c, 32); + b.storeUint(self.queryId, 64); + b.storeAddress(self.router); + b.storeAddress(self.rateLimitAdmin); + b.storeAddress(self.feeAdmin); + }, + toCell(self: TokenPool_DynamicConfigSet): c.Cell { + return makeCellFrom(self, TokenPool_DynamicConfigSet.store); + } +} + +/** + > struct (0xdd7b0c71) TokenPool_RateLimitConfiguredNotification { + > queryId: uint64 + > } + */ +export interface TokenPool_RateLimitConfiguredNotification { + readonly $: 'TokenPool_RateLimitConfiguredNotification' + queryId: uint64 +} + +export const TokenPool_RateLimitConfiguredNotification = { + PREFIX: 0xdd7b0c71, + + create(args: { + queryId?: uint64 + }): TokenPool_RateLimitConfiguredNotification { + return { + $: 'TokenPool_RateLimitConfiguredNotification', + ...args, + queryId: args.queryId ?? 0n + } + }, + fromSlice(s: c.Slice): TokenPool_RateLimitConfiguredNotification { + loadAndCheckPrefix32(s, 0xdd7b0c71, 'TokenPool_RateLimitConfiguredNotification'); + return { + $: 'TokenPool_RateLimitConfiguredNotification', + queryId: s.loadUintBig(64), + } + }, + store(self: TokenPool_RateLimitConfiguredNotification, b: c.Builder): void { + b.storeUint(0xdd7b0c71, 32); + b.storeUint(self.queryId, 64); + }, + toCell(self: TokenPool_RateLimitConfiguredNotification): c.Cell { + return makeCellFrom(self, TokenPool_RateLimitConfiguredNotification.store); + } +} + +/** + > struct (0xe5d08b2e) TokenPool_RMNProxySet { + > queryId: uint64 + > rmnProxy: address? + > } + */ +export interface TokenPool_RMNProxySet { + readonly $: 'TokenPool_RMNProxySet' + queryId: uint64 + rmnProxy: c.Address | null +} + +export const TokenPool_RMNProxySet = { + PREFIX: 0xe5d08b2e, + + create(args: { + queryId?: uint64 + rmnProxy: c.Address | null + }): TokenPool_RMNProxySet { + return { + $: 'TokenPool_RMNProxySet', + ...args, + queryId: args.queryId ?? 0n + } + }, + fromSlice(s: c.Slice): TokenPool_RMNProxySet { + loadAndCheckPrefix32(s, 0xe5d08b2e, 'TokenPool_RMNProxySet'); + return { + $: 'TokenPool_RMNProxySet', + queryId: s.loadUintBig(64), + rmnProxy: s.loadMaybeAddress(), + } + }, + store(self: TokenPool_RMNProxySet, b: c.Builder): void { + b.storeUint(0xe5d08b2e, 32); + b.storeUint(self.queryId, 64); + b.storeAddress(self.rmnProxy); + }, + toCell(self: TokenPool_RMNProxySet): c.Cell { + return makeCellFrom(self, TokenPool_RMNProxySet.store); + } +} + +/** + > struct (0x15800161) TokenPool_CursedSubjectsSet { + > queryId: uint64 + > cursedSubjects: CursedSubjects + > } + */ +export interface TokenPool_CursedSubjectsSet { + readonly $: 'TokenPool_CursedSubjectsSet' + queryId: uint64 + cursedSubjects: CursedSubjects +} + +export const TokenPool_CursedSubjectsSet = { + PREFIX: 0x15800161, + + create(args: { + queryId?: uint64 + cursedSubjects: CursedSubjects + }): TokenPool_CursedSubjectsSet { + return { + $: 'TokenPool_CursedSubjectsSet', + ...args, + queryId: args.queryId ?? 0n + } + }, + fromSlice(s: c.Slice): TokenPool_CursedSubjectsSet { + loadAndCheckPrefix32(s, 0x15800161, 'TokenPool_CursedSubjectsSet'); + return { + $: 'TokenPool_CursedSubjectsSet', + queryId: s.loadUintBig(64), + cursedSubjects: CursedSubjects.fromSlice(s), + } + }, + store(self: TokenPool_CursedSubjectsSet, b: c.Builder): void { + b.storeUint(0x15800161, 32); + b.storeUint(self.queryId, 64); + CursedSubjects.store(self.cursedSubjects, b); + }, + toCell(self: TokenPool_CursedSubjectsSet): c.Cell { + return makeCellFrom(self, TokenPool_CursedSubjectsSet.store); + } +} + +/** + > struct (0xad7833d7) TokenPool_ChainUpdatesApplied { + > queryId: uint64 + > } + */ +export interface TokenPool_ChainUpdatesApplied { + readonly $: 'TokenPool_ChainUpdatesApplied' + queryId: uint64 +} + +export const TokenPool_ChainUpdatesApplied = { + PREFIX: 0xad7833d7, + + create(args: { + queryId?: uint64 + }): TokenPool_ChainUpdatesApplied { + return { + $: 'TokenPool_ChainUpdatesApplied', + ...args, + queryId: args.queryId ?? 0n + } + }, + fromSlice(s: c.Slice): TokenPool_ChainUpdatesApplied { + loadAndCheckPrefix32(s, 0xad7833d7, 'TokenPool_ChainUpdatesApplied'); + return { + $: 'TokenPool_ChainUpdatesApplied', + queryId: s.loadUintBig(64), + } + }, + store(self: TokenPool_ChainUpdatesApplied, b: c.Builder): void { + b.storeUint(0xad7833d7, 32); + b.storeUint(self.queryId, 64); + }, + toCell(self: TokenPool_ChainUpdatesApplied): c.Cell { + return makeCellFrom(self, TokenPool_ChainUpdatesApplied.store); + } +} + +/** + > struct (0x28cbcc64) TokenPool_FeeConfigApplied { + > queryId: uint64 + > } + */ +export interface TokenPool_FeeConfigApplied { + readonly $: 'TokenPool_FeeConfigApplied' + queryId: uint64 +} + +export const TokenPool_FeeConfigApplied = { + PREFIX: 0x28cbcc64, + + create(args: { + queryId?: uint64 + }): TokenPool_FeeConfigApplied { + return { + $: 'TokenPool_FeeConfigApplied', + ...args, + queryId: args.queryId ?? 0n + } + }, + fromSlice(s: c.Slice): TokenPool_FeeConfigApplied { + loadAndCheckPrefix32(s, 0x28cbcc64, 'TokenPool_FeeConfigApplied'); + return { + $: 'TokenPool_FeeConfigApplied', + queryId: s.loadUintBig(64), + } + }, + store(self: TokenPool_FeeConfigApplied, b: c.Builder): void { + b.storeUint(0x28cbcc64, 32); + b.storeUint(self.queryId, 64); + }, + toCell(self: TokenPool_FeeConfigApplied): c.Cell { + return makeCellFrom(self, TokenPool_FeeConfigApplied.store); + } +} + +/** + > struct (0x3c869d80) TokenPool_AdvancedPoolHooksSet { + > queryId: uint64 + > advancedPoolHooks: address? + > } + */ +export interface TokenPool_AdvancedPoolHooksSet { + readonly $: 'TokenPool_AdvancedPoolHooksSet' + queryId: uint64 + advancedPoolHooks: c.Address | null +} + +export const TokenPool_AdvancedPoolHooksSet = { + PREFIX: 0x3c869d80, + + create(args: { + queryId?: uint64 + advancedPoolHooks: c.Address | null + }): TokenPool_AdvancedPoolHooksSet { + return { + $: 'TokenPool_AdvancedPoolHooksSet', + ...args, + queryId: args.queryId ?? 0n + } + }, + fromSlice(s: c.Slice): TokenPool_AdvancedPoolHooksSet { + loadAndCheckPrefix32(s, 0x3c869d80, 'TokenPool_AdvancedPoolHooksSet'); + return { + $: 'TokenPool_AdvancedPoolHooksSet', + queryId: s.loadUintBig(64), + advancedPoolHooks: s.loadMaybeAddress(), + } + }, + store(self: TokenPool_AdvancedPoolHooksSet, b: c.Builder): void { + b.storeUint(0x3c869d80, 32); + b.storeUint(self.queryId, 64); + b.storeAddress(self.advancedPoolHooks); + }, + toCell(self: TokenPool_AdvancedPoolHooksSet): c.Cell { + return makeCellFrom(self, TokenPool_AdvancedPoolHooksSet.store); + } +} + +/** + > type SnakedCell = cell + */ +export type SnakedCell = T[] + +function storeSnakedCellOf(v: SnakedCell, b: c.Builder, storeFn_T: StoreCallback): void { + if (v.length === 0) { + b.storeRef(c.Cell.EMPTY); + return; + } + const cells: c.Builder[] = []; + let builder = c.beginCell(); + for (const value of v) { + let itemB = c.beginCell(); + storeFn_T(value, itemB); + if (builder.availableBits < itemB.bits || builder.availableRefs <= 1) { + cells.push(builder); + builder = c.beginCell(); + } + builder.storeBuilder(itemB); + } + cells.push(builder); + let current = cells[cells.length - 1].endCell(); + for (let i = cells.length - 2; i >= 0; i--) { + cells[i].storeRef(current); + current = cells[i].endCell(); + } + b.storeRef(current); +} + +function loadSnakedCellOf(s: c.Slice, loadFn_T: LoadCallback): SnakedCell { + let outArr = [] as T[]; + let head = s.loadRef().beginParse(); + while (head.remainingBits > 0 || head.remainingRefs > 0) { + if (head.remainingBits > 0) { + outArr.push(loadFn_T(head)); + } + if (head.remainingRefs > 0) { + head = head.loadRef().beginParse(); + } else { + break; + } + } + return outArr; +} + + +/** + > type ForwardPayloadRemainder = RemainingBitsAndRefs + */ +export type ForwardPayloadRemainder = RemainingBitsAndRefs + +export const ForwardPayloadRemainder = { + fromSlice(s: c.Slice): ForwardPayloadRemainder { + return loadTolkRemaining(s); + }, + store(self: ForwardPayloadRemainder, b: c.Builder): void { + storeTolkRemaining(self, b); + }, + toCell(self: ForwardPayloadRemainder): c.Cell { + return makeCellFrom(self, ForwardPayloadRemainder.store); + } +} + +/** + > struct (0x0f8a7ea5) AskToTransfer { + > queryId: uint64 + > jettonAmount: coins + > transferRecipient: address + > sendExcessesTo: address? + > customPayload: cell? + > forwardTonAmount: coins + > forwardPayload: ForwardPayloadRemainder + > } + */ +export interface AskToTransfer { + readonly $: 'AskToTransfer' + queryId: uint64 + jettonAmount: coins + transferRecipient: c.Address + sendExcessesTo: c.Address | null + customPayload: c.Cell | null + forwardTonAmount: coins + forwardPayload: ForwardPayloadRemainder +} + +export const AskToTransfer = { + PREFIX: 0x0f8a7ea5, + + create(args: { + queryId?: uint64 + jettonAmount: coins + transferRecipient: c.Address + sendExcessesTo: c.Address | null + customPayload: c.Cell | null + forwardTonAmount: coins + forwardPayload: ForwardPayloadRemainder + }): AskToTransfer { + return { + $: 'AskToTransfer', + ...args, + queryId: args.queryId ?? 0n + } + }, + fromSlice(s: c.Slice): AskToTransfer { + loadAndCheckPrefix32(s, 0x0f8a7ea5, 'AskToTransfer'); + return { + $: 'AskToTransfer', + queryId: s.loadUintBig(64), + jettonAmount: s.loadCoins(), + transferRecipient: s.loadAddress(), + sendExcessesTo: s.loadMaybeAddress(), + customPayload: s.loadBoolean() ? s.loadRef() : null, + forwardTonAmount: s.loadCoins(), + forwardPayload: ForwardPayloadRemainder.fromSlice(s), + } + }, + store(self: AskToTransfer, b: c.Builder): void { + b.storeUint(0x0f8a7ea5, 32); + b.storeUint(self.queryId, 64); + b.storeCoins(self.jettonAmount); + b.storeAddress(self.transferRecipient); + b.storeAddress(self.sendExcessesTo); + storeTolkNullable(self.customPayload, b, + (v,b) => b.storeRef(v) + ); + b.storeCoins(self.forwardTonAmount); + ForwardPayloadRemainder.store(self.forwardPayload, b); + }, + toCell(self: AskToTransfer): c.Cell { + return makeCellFrom(self, AskToTransfer.store); + } +} + +/** + > struct (0x7362d09c) TransferNotificationForRecipient { + > queryId: uint64 + > jettonAmount: coins + > transferInitiator: address? + > forwardPayload: ForwardPayloadRemainder + > } + */ +export interface TransferNotificationForRecipient { + readonly $: 'TransferNotificationForRecipient' + queryId: uint64 + jettonAmount: coins + transferInitiator: c.Address | null + forwardPayload: ForwardPayloadRemainder +} + +export const TransferNotificationForRecipient = { + PREFIX: 0x7362d09c, + + create(args: { + queryId?: uint64 + jettonAmount: coins + transferInitiator: c.Address | null + forwardPayload: ForwardPayloadRemainder + }): TransferNotificationForRecipient { + return { + $: 'TransferNotificationForRecipient', + ...args, + queryId: args.queryId ?? 0n + } + }, + fromSlice(s: c.Slice): TransferNotificationForRecipient { + loadAndCheckPrefix32(s, 0x7362d09c, 'TransferNotificationForRecipient'); + return { + $: 'TransferNotificationForRecipient', + queryId: s.loadUintBig(64), + jettonAmount: s.loadCoins(), + transferInitiator: s.loadMaybeAddress(), + forwardPayload: ForwardPayloadRemainder.fromSlice(s), + } + }, + store(self: TransferNotificationForRecipient, b: c.Builder): void { + b.storeUint(0x7362d09c, 32); + b.storeUint(self.queryId, 64); + b.storeCoins(self.jettonAmount); + b.storeAddress(self.transferInitiator); + ForwardPayloadRemainder.store(self.forwardPayload, b); + }, + toCell(self: TransferNotificationForRecipient): c.Cell { + return makeCellFrom(self, TransferNotificationForRecipient.store); + } +} + +/** + > struct JettonClient { + > masterAddress: address + > jettonWalletCode: cell + > } + */ +export interface JettonClient { + readonly $: 'JettonClient' + masterAddress: c.Address + jettonWalletCode: c.Cell +} + +export const JettonClient = { + create(args: { + masterAddress: c.Address + jettonWalletCode: c.Cell + }): JettonClient { + return { + $: 'JettonClient', + ...args + } + }, + fromSlice(s: c.Slice): JettonClient { + return { + $: 'JettonClient', + masterAddress: s.loadAddress(), + jettonWalletCode: s.loadRef(), + } + }, + store(self: JettonClient, b: c.Builder): void { + b.storeAddress(self.masterAddress); + b.storeRef(self.jettonWalletCode); + }, + toCell(self: JettonClient): c.Cell { + return makeCellFrom(self, JettonClient.store); + } +} + +/** + > struct Ownable2Step { + > owner: address + > pendingOwner: address? + > } + */ +export interface Ownable2Step { + readonly $: 'Ownable2Step' + owner: c.Address + pendingOwner: c.Address | null /* = null */ +} + +export const Ownable2Step = { + create(args: { + owner: c.Address + pendingOwner?: c.Address | null /* = null */ + }): Ownable2Step { + return { + $: 'Ownable2Step', + pendingOwner: null, + ...args + } + }, + fromSlice(s: c.Slice): Ownable2Step { + return { + $: 'Ownable2Step', + owner: s.loadAddress(), + pendingOwner: s.loadMaybeAddress(), + } + }, + store(self: Ownable2Step, b: c.Builder): void { + b.storeAddress(self.owner); + b.storeAddress(self.pendingOwner); + }, + toCell(self: Ownable2Step): c.Cell { + return makeCellFrom(self, Ownable2Step.store); + } +} + +/** + > struct Ownable2Step_OwnershipTransferRequested { + > queryId: uint64 + > newOwner: address + > } + */ +export interface Ownable2Step_OwnershipTransferRequested { + readonly $: 'Ownable2Step_OwnershipTransferRequested' + queryId: uint64 + newOwner: c.Address +} + +export const Ownable2Step_OwnershipTransferRequested = { + create(args: { + queryId?: uint64 + newOwner: c.Address + }): Ownable2Step_OwnershipTransferRequested { + return { + $: 'Ownable2Step_OwnershipTransferRequested', + ...args, + queryId: args.queryId ?? 0n + } + }, + fromSlice(s: c.Slice): Ownable2Step_OwnershipTransferRequested { + return { + $: 'Ownable2Step_OwnershipTransferRequested', + queryId: s.loadUintBig(64), + newOwner: s.loadAddress(), + } + }, + store(self: Ownable2Step_OwnershipTransferRequested, b: c.Builder): void { + b.storeUint(self.queryId, 64); + b.storeAddress(self.newOwner); + }, + toCell(self: Ownable2Step_OwnershipTransferRequested): c.Cell { + return makeCellFrom(self, Ownable2Step_OwnershipTransferRequested.store); + } +} + +/** + > struct Ownable2Step_OwnershipTransferred { + > queryId: uint64 + > oldOwner: address + > newOwner: address + > } + */ +export interface Ownable2Step_OwnershipTransferred { + readonly $: 'Ownable2Step_OwnershipTransferred' + queryId: uint64 + oldOwner: c.Address + newOwner: c.Address +} + +export const Ownable2Step_OwnershipTransferred = { + create(args: { + queryId?: uint64 + oldOwner: c.Address + newOwner: c.Address + }): Ownable2Step_OwnershipTransferred { + return { + $: 'Ownable2Step_OwnershipTransferred', + ...args, + queryId: args.queryId ?? 0n + } + }, + fromSlice(s: c.Slice): Ownable2Step_OwnershipTransferred { + return { + $: 'Ownable2Step_OwnershipTransferred', + queryId: s.loadUintBig(64), + oldOwner: s.loadAddress(), + newOwner: s.loadAddress(), + } + }, + store(self: Ownable2Step_OwnershipTransferred, b: c.Builder): void { + b.storeUint(self.queryId, 64); + b.storeAddress(self.oldOwner); + b.storeAddress(self.newOwner); + }, + toCell(self: Ownable2Step_OwnershipTransferred): c.Cell { + return makeCellFrom(self, Ownable2Step_OwnershipTransferred.store); + } +} + +/** + > struct JettonWithdrawable_WithdrawFeeTransfer { + > wallet: address + > value: coins + > msg: AskToTransfer + > } + */ +export interface JettonWithdrawable_WithdrawFeeTransfer { + readonly $: 'JettonWithdrawable_WithdrawFeeTransfer' + wallet: c.Address + value: coins + msg: AskToTransfer +} + +export const JettonWithdrawable_WithdrawFeeTransfer = { + create(args: { + wallet: c.Address + value: coins + msg: AskToTransfer + }): JettonWithdrawable_WithdrawFeeTransfer { + return { + $: 'JettonWithdrawable_WithdrawFeeTransfer', + ...args + } + }, + fromSlice(s: c.Slice): JettonWithdrawable_WithdrawFeeTransfer { + return { + $: 'JettonWithdrawable_WithdrawFeeTransfer', + wallet: s.loadAddress(), + value: s.loadCoins(), + msg: AskToTransfer.fromSlice(s), + } + }, + store(self: JettonWithdrawable_WithdrawFeeTransfer, b: c.Builder): void { + b.storeAddress(self.wallet); + b.storeCoins(self.value); + AskToTransfer.store(self.msg, b); + }, + toCell(self: JettonWithdrawable_WithdrawFeeTransfer): c.Cell { + return makeCellFrom(self, JettonWithdrawable_WithdrawFeeTransfer.store); + } +} + +/** + > struct (0x0d00995c) JettonWithdrawable_Withdraw { + > queryId: uint64 + > transfers: array + > } + */ +export interface JettonWithdrawable_Withdraw { + readonly $: 'JettonWithdrawable_Withdraw' + queryId: uint64 + transfers: array +} + +export const JettonWithdrawable_Withdraw = { + PREFIX: 0x0d00995c, + + create(args: { + queryId?: uint64 + transfers: array + }): JettonWithdrawable_Withdraw { + return { + $: 'JettonWithdrawable_Withdraw', + ...args, + queryId: args.queryId ?? 0n + } + }, + fromSlice(s: c.Slice): JettonWithdrawable_Withdraw { + loadAndCheckPrefix32(s, 0x0d00995c, 'JettonWithdrawable_Withdraw'); + return { + $: 'JettonWithdrawable_Withdraw', + queryId: s.loadUintBig(64), + transfers: loadArrayOf(s, JettonWithdrawable_WithdrawFeeTransfer.fromSlice), + } + }, + store(self: JettonWithdrawable_Withdraw, b: c.Builder): void { + b.storeUint(0x0d00995c, 32); + b.storeUint(self.queryId, 64); + storeArrayOf(self.transfers, b, JettonWithdrawable_WithdrawFeeTransfer.store); + }, + toCell(self: JettonWithdrawable_Withdraw): c.Cell { + return makeCellFrom(self, JettonWithdrawable_Withdraw.store); + } +} + +/** + > struct JettonWithdrawable_FeeTokenWithdrawn { + > wallet: address + > amount: coins + > } + */ +export interface JettonWithdrawable_FeeTokenWithdrawn { + readonly $: 'JettonWithdrawable_FeeTokenWithdrawn' + wallet: c.Address + amount: coins +} + +export const JettonWithdrawable_FeeTokenWithdrawn = { + create(args: { + wallet: c.Address + amount: coins + }): JettonWithdrawable_FeeTokenWithdrawn { + return { + $: 'JettonWithdrawable_FeeTokenWithdrawn', + ...args + } + }, + fromSlice(s: c.Slice): JettonWithdrawable_FeeTokenWithdrawn { + return { + $: 'JettonWithdrawable_FeeTokenWithdrawn', + wallet: s.loadAddress(), + amount: s.loadCoins(), + } + }, + store(self: JettonWithdrawable_FeeTokenWithdrawn, b: c.Builder): void { + b.storeAddress(self.wallet); + b.storeCoins(self.amount); + }, + toCell(self: JettonWithdrawable_FeeTokenWithdrawn): c.Cell { + return makeCellFrom(self, JettonWithdrawable_FeeTokenWithdrawn.store); + } +} + +/** + > type CrossChainAddress = slice + */ +export type CrossChainAddress = c.Slice + +export const CrossChainAddress = { + fromSlice(s: c.Slice): CrossChainAddress { + return invokeCustomUnpackFromSlice('CrossChainAddress', s); + }, + store(self: CrossChainAddress, b: c.Builder): void { + invokeCustomPackToBuilder('CrossChainAddress', self, b); + }, + toCell(self: CrossChainAddress): c.Cell { + return makeCellFrom(self, CrossChainAddress.store); + } +} + +/** + > struct CursedSubjects { + > data: map + > } + */ +export interface CursedSubjects { + readonly $: 'CursedSubjects' + data: Set /* = [] as map */ +} + +export const CursedSubjects = { + create(args: { + data: Set /* = [] as map */ + }): CursedSubjects { + return { + $: 'CursedSubjects', + ...args + } + }, + fromSlice(s: c.Slice): CursedSubjects { + return { + $: 'CursedSubjects', + data: dictToSet(c.Dictionary.load(c.Dictionary.Keys.BigUint(128), createDictionaryValue<[]>( + (s) => [], + (v,b) => { {} } + ), s)), + } + }, + store(self: CursedSubjects, b: c.Builder): void { + b.storeDict(setToDict(self.data, c.Dictionary.Keys.BigUint(128), createDictionaryValue<[]>( + (s) => [], + (v,b) => { {} } + )), c.Dictionary.Keys.BigUint(128), createDictionaryValue<[]>( + (s) => [], + (v,b) => { {} } + )); + }, + toCell(self: CursedSubjects): c.Cell { + return makeCellFrom(self, CursedSubjects.store); + } +} + +/** + > struct TokenPool_DynamicConfig { + > router: address + > rateLimitAdmin: address? + > feeAdmin: address? + > allowedDepositNamespaces: map + > } + */ +export interface TokenPool_DynamicConfig { + readonly $: 'TokenPool_DynamicConfig' + router: c.Address + rateLimitAdmin: c.Address | null /* = null */ + feeAdmin: c.Address | null + allowedDepositNamespaces: Map /* = [] as map */ +} + +export const TokenPool_DynamicConfig = { + create(args: { + router: c.Address + rateLimitAdmin?: c.Address | null /* = null */ + feeAdmin: c.Address | null + allowedDepositNamespaces: Map /* = [] as map */ + }): TokenPool_DynamicConfig { + return { + $: 'TokenPool_DynamicConfig', + rateLimitAdmin: null, + ...args + } + }, + fromSlice(s: c.Slice): TokenPool_DynamicConfig { + return { + $: 'TokenPool_DynamicConfig', + router: s.loadAddress(), + rateLimitAdmin: s.loadMaybeAddress(), + feeAdmin: s.loadMaybeAddress(), + allowedDepositNamespaces: dictToMap(c.Dictionary.load(c.Dictionary.Keys.BigUint(32), c.Dictionary.Values.Bool(), s)), + } + }, + store(self: TokenPool_DynamicConfig, b: c.Builder): void { + b.storeAddress(self.router); + b.storeAddress(self.rateLimitAdmin); + b.storeAddress(self.feeAdmin); + b.storeDict(mapToDict(self.allowedDepositNamespaces, c.Dictionary.Keys.BigUint(32), c.Dictionary.Values.Bool()), c.Dictionary.Keys.BigUint(32), c.Dictionary.Values.Bool()); + }, + toCell(self: TokenPool_DynamicConfig): c.Cell { + return makeCellFrom(self, TokenPool_DynamicConfig.store); + } +} + +/** + > struct TokenPool_LocalPolicy { + > cursedSubjects: CursedSubjects + > } + */ +export interface TokenPool_LocalPolicy { + readonly $: 'TokenPool_LocalPolicy' + cursedSubjects: CursedSubjects +} + +export const TokenPool_LocalPolicy = { + create(args: { + cursedSubjects: CursedSubjects + }): TokenPool_LocalPolicy { + return { + $: 'TokenPool_LocalPolicy', + ...args + } + }, + fromSlice(s: c.Slice): TokenPool_LocalPolicy { + return { + $: 'TokenPool_LocalPolicy', + cursedSubjects: CursedSubjects.fromSlice(s), + } + }, + store(self: TokenPool_LocalPolicy, b: c.Builder): void { + CursedSubjects.store(self.cursedSubjects, b); + }, + toCell(self: TokenPool_LocalPolicy): c.Cell { + return makeCellFrom(self, TokenPool_LocalPolicy.store); + } +} + +/** + > struct TokenPool_RateLimiterPair { + > outbound: Cell + > inbound: Cell + > } + */ +export interface TokenPool_RateLimiterPair { + readonly $: 'TokenPool_RateLimiterPair' + outbound: RateLimiter_TokenBucket + inbound: RateLimiter_TokenBucket +} + +export const TokenPool_RateLimiterPair = { + create(args: { + outbound: RateLimiter_TokenBucket + inbound: RateLimiter_TokenBucket + }): TokenPool_RateLimiterPair { + return { + $: 'TokenPool_RateLimiterPair', + ...args + } + }, + fromSlice(s: c.Slice): TokenPool_RateLimiterPair { + return { + $: 'TokenPool_RateLimiterPair', + outbound: loadCellRef(s, RateLimiter_TokenBucket.fromSlice), + inbound: loadCellRef(s, RateLimiter_TokenBucket.fromSlice), + } + }, + store(self: TokenPool_RateLimiterPair, b: c.Builder): void { + storeCellRef(self.outbound, b, RateLimiter_TokenBucket.store); + storeCellRef(self.inbound, b, RateLimiter_TokenBucket.store); + }, + toCell(self: TokenPool_RateLimiterPair): c.Cell { + return makeCellFrom(self, TokenPool_RateLimiterPair.store); + } +} + +/** + > struct TokenPool_RateLimitConfigPair { + > outbound: Cell + > inbound: Cell + > } + */ +export interface TokenPool_RateLimitConfigPair { + readonly $: 'TokenPool_RateLimitConfigPair' + outbound: RateLimiter_Config + inbound: RateLimiter_Config +} + +export const TokenPool_RateLimitConfigPair = { + create(args: { + outbound: RateLimiter_Config + inbound: RateLimiter_Config + }): TokenPool_RateLimitConfigPair { + return { + $: 'TokenPool_RateLimitConfigPair', + ...args + } + }, + fromSlice(s: c.Slice): TokenPool_RateLimitConfigPair { + return { + $: 'TokenPool_RateLimitConfigPair', + outbound: loadCellRef(s, RateLimiter_Config.fromSlice), + inbound: loadCellRef(s, RateLimiter_Config.fromSlice), + } + }, + store(self: TokenPool_RateLimitConfigPair, b: c.Builder): void { + storeCellRef(self.outbound, b, RateLimiter_Config.store); + storeCellRef(self.inbound, b, RateLimiter_Config.store); + }, + toCell(self: TokenPool_RateLimitConfigPair): c.Cell { + return makeCellFrom(self, TokenPool_RateLimitConfigPair.store); + } +} + +/** + > struct TokenPool_ChainUpdate { + > remoteChainSelector: uint64 + > remotePoolAddresses: SnakedCell + > remoteTokenAddress: Cell + > rateLimitConfigs: Cell + > } + */ +export interface TokenPool_ChainUpdate { + readonly $: 'TokenPool_ChainUpdate' + remoteChainSelector: uint64 + remotePoolAddresses: SnakedCell + remoteTokenAddress: CrossChainAddress + rateLimitConfigs: TokenPool_RateLimitConfigPair +} + +export const TokenPool_ChainUpdate = { + create(args: { + remoteChainSelector: uint64 + remotePoolAddresses: SnakedCell + remoteTokenAddress: CrossChainAddress + rateLimitConfigs: TokenPool_RateLimitConfigPair + }): TokenPool_ChainUpdate { + return { + $: 'TokenPool_ChainUpdate', + ...args + } + }, + fromSlice(s: c.Slice): TokenPool_ChainUpdate { + return { + $: 'TokenPool_ChainUpdate', + remoteChainSelector: s.loadUintBig(64), + remotePoolAddresses: loadSnakedCellOf(s, CrossChainAddress.fromSlice), + remoteTokenAddress: loadCellRef(s, CrossChainAddress.fromSlice), + rateLimitConfigs: loadCellRef(s, TokenPool_RateLimitConfigPair.fromSlice), + } + }, + store(self: TokenPool_ChainUpdate, b: c.Builder): void { + b.storeUint(self.remoteChainSelector, 64); + storeSnakedCellOf(self.remotePoolAddresses, b, CrossChainAddress.store); + storeCellRef(self.remoteTokenAddress, b, CrossChainAddress.store); + storeCellRef(self.rateLimitConfigs, b, TokenPool_RateLimitConfigPair.store); + }, + toCell(self: TokenPool_ChainUpdate): c.Cell { + return makeCellFrom(self, TokenPool_ChainUpdate.store); + } +} + +/** + > struct TokenPool_RemoteChainConfig { + > remoteTokenAddress: Cell + > remotePools: map> + > rateLimiters: Cell + > fastFinalityRateLimiters: Cell + > } + */ +export interface TokenPool_RemoteChainConfig { + readonly $: 'TokenPool_RemoteChainConfig' + remoteTokenAddress: CrossChainAddress + remotePools: Map /* = [] as map> */ + rateLimiters: TokenPool_RateLimiterPair + fastFinalityRateLimiters: TokenPool_RateLimiterPair +} + +export const TokenPool_RemoteChainConfig = { + create(args: { + remoteTokenAddress: CrossChainAddress + remotePools: Map /* = [] as map> */ + rateLimiters: TokenPool_RateLimiterPair + fastFinalityRateLimiters: TokenPool_RateLimiterPair + }): TokenPool_RemoteChainConfig { + return { + $: 'TokenPool_RemoteChainConfig', + ...args + } + }, + fromSlice(s: c.Slice): TokenPool_RemoteChainConfig { + return { + $: 'TokenPool_RemoteChainConfig', + remoteTokenAddress: loadCellRef(s, CrossChainAddress.fromSlice), + remotePools: dictToMap(c.Dictionary.load(c.Dictionary.Keys.BigUint(256), createDictionaryValue( + (s) => loadCellRef(s, CrossChainAddress.fromSlice), + (v,b) => storeCellRef(v, b, CrossChainAddress.store) + ), s)), + rateLimiters: loadCellRef(s, TokenPool_RateLimiterPair.fromSlice), + fastFinalityRateLimiters: loadCellRef(s, TokenPool_RateLimiterPair.fromSlice), + } + }, + store(self: TokenPool_RemoteChainConfig, b: c.Builder): void { + storeCellRef(self.remoteTokenAddress, b, CrossChainAddress.store); + b.storeDict(mapToDict(self.remotePools, c.Dictionary.Keys.BigUint(256), createDictionaryValue( + (s) => loadCellRef(s, CrossChainAddress.fromSlice), + (v,b) => storeCellRef(v, b, CrossChainAddress.store) + )), c.Dictionary.Keys.BigUint(256), createDictionaryValue( + (s) => loadCellRef(s, CrossChainAddress.fromSlice), + (v,b) => storeCellRef(v, b, CrossChainAddress.store) + )); + storeCellRef(self.rateLimiters, b, TokenPool_RateLimiterPair.store); + storeCellRef(self.fastFinalityRateLimiters, b, TokenPool_RateLimiterPair.store); + }, + toCell(self: TokenPool_RemoteChainConfig): c.Cell { + return makeCellFrom(self, TokenPool_RemoteChainConfig.store); + } +} + +/** + > struct TokenPool_RateLimitConfigArgs { + > remoteChainSelector: uint64 + > fastFinality: bool + > outboundRateLimiterConfig: Cell + > inboundRateLimiterConfig: Cell + > } + */ +export interface TokenPool_RateLimitConfigArgs { + readonly $: 'TokenPool_RateLimitConfigArgs' + remoteChainSelector: uint64 + fastFinality: boolean + outboundRateLimiterConfig: RateLimiter_Config + inboundRateLimiterConfig: RateLimiter_Config +} + +export const TokenPool_RateLimitConfigArgs = { + create(args: { + remoteChainSelector: uint64 + fastFinality: boolean + outboundRateLimiterConfig: RateLimiter_Config + inboundRateLimiterConfig: RateLimiter_Config + }): TokenPool_RateLimitConfigArgs { + return { + $: 'TokenPool_RateLimitConfigArgs', + ...args + } + }, + fromSlice(s: c.Slice): TokenPool_RateLimitConfigArgs { + return { + $: 'TokenPool_RateLimitConfigArgs', + remoteChainSelector: s.loadUintBig(64), + fastFinality: s.loadBoolean(), + outboundRateLimiterConfig: loadCellRef(s, RateLimiter_Config.fromSlice), + inboundRateLimiterConfig: loadCellRef(s, RateLimiter_Config.fromSlice), + } + }, + store(self: TokenPool_RateLimitConfigArgs, b: c.Builder): void { + b.storeUint(self.remoteChainSelector, 64); + b.storeBit(self.fastFinality); + storeCellRef(self.outboundRateLimiterConfig, b, RateLimiter_Config.store); + storeCellRef(self.inboundRateLimiterConfig, b, RateLimiter_Config.store); + }, + toCell(self: TokenPool_RateLimitConfigArgs): c.Cell { + return makeCellFrom(self, TokenPool_RateLimitConfigArgs.store); + } +} + +/** + > struct TokenPool_TokenTransferFeeConfigArgs { + > destChainSelector: uint64 + > tokenTransferFeeConfig: TokenPool_TokenTransferFeeConfig + > } + */ +export interface TokenPool_TokenTransferFeeConfigArgs { + readonly $: 'TokenPool_TokenTransferFeeConfigArgs' + destChainSelector: uint64 + tokenTransferFeeConfig: TokenPool_TokenTransferFeeConfig +} + +export const TokenPool_TokenTransferFeeConfigArgs = { + create(args: { + destChainSelector: uint64 + tokenTransferFeeConfig: TokenPool_TokenTransferFeeConfig + }): TokenPool_TokenTransferFeeConfigArgs { + return { + $: 'TokenPool_TokenTransferFeeConfigArgs', + ...args + } + }, + fromSlice(s: c.Slice): TokenPool_TokenTransferFeeConfigArgs { + return { + $: 'TokenPool_TokenTransferFeeConfigArgs', + destChainSelector: s.loadUintBig(64), + tokenTransferFeeConfig: TokenPool_TokenTransferFeeConfig.fromSlice(s), + } + }, + store(self: TokenPool_TokenTransferFeeConfigArgs, b: c.Builder): void { + b.storeUint(self.destChainSelector, 64); + TokenPool_TokenTransferFeeConfig.store(self.tokenTransferFeeConfig, b); + }, + toCell(self: TokenPool_TokenTransferFeeConfigArgs): c.Cell { + return makeCellFrom(self, TokenPool_TokenTransferFeeConfigArgs.store); + } +} + +/** + > struct TokenPool_LockOrBurnPrepared { + > feeAmount: coins + > destTokenAmount: coins + > out: TokenPool_LockOrBurnOutV1 + > } + */ +export interface TokenPool_LockOrBurnPrepared { + readonly $: 'TokenPool_LockOrBurnPrepared' + feeAmount: coins + destTokenAmount: coins + out: TokenPool_LockOrBurnOutV1 +} + +export const TokenPool_LockOrBurnPrepared = { + create(args: { + feeAmount: coins + destTokenAmount: coins + out: TokenPool_LockOrBurnOutV1 + }): TokenPool_LockOrBurnPrepared { + return { + $: 'TokenPool_LockOrBurnPrepared', + ...args + } + }, + fromSlice(s: c.Slice): TokenPool_LockOrBurnPrepared { + return { + $: 'TokenPool_LockOrBurnPrepared', + feeAmount: s.loadCoins(), + destTokenAmount: s.loadCoins(), + out: TokenPool_LockOrBurnOutV1.fromSlice(s), + } + }, + store(self: TokenPool_LockOrBurnPrepared, b: c.Builder): void { + b.storeCoins(self.feeAmount); + b.storeCoins(self.destTokenAmount); + TokenPool_LockOrBurnOutV1.store(self.out, b); + }, + toCell(self: TokenPool_LockOrBurnPrepared): c.Cell { + return makeCellFrom(self, TokenPool_LockOrBurnPrepared.store); + } +} + +/** + > struct TokenPool_ReleaseOrMintPrepared { + > requestedFinalityConfig: uint32 + > localAmount: coins + > out: TokenPool_ReleaseOrMintOutV1 + > } + */ +export interface TokenPool_ReleaseOrMintPrepared { + readonly $: 'TokenPool_ReleaseOrMintPrepared' + requestedFinalityConfig: uint32 + localAmount: coins + out: TokenPool_ReleaseOrMintOutV1 +} + +export const TokenPool_ReleaseOrMintPrepared = { + create(args: { + requestedFinalityConfig: uint32 + localAmount: coins + out: TokenPool_ReleaseOrMintOutV1 + }): TokenPool_ReleaseOrMintPrepared { + return { + $: 'TokenPool_ReleaseOrMintPrepared', + ...args + } + }, + fromSlice(s: c.Slice): TokenPool_ReleaseOrMintPrepared { + return { + $: 'TokenPool_ReleaseOrMintPrepared', + requestedFinalityConfig: s.loadUintBig(32), + localAmount: s.loadCoins(), + out: TokenPool_ReleaseOrMintOutV1.fromSlice(s), + } + }, + store(self: TokenPool_ReleaseOrMintPrepared, b: c.Builder): void { + b.storeUint(self.requestedFinalityConfig, 32); + b.storeCoins(self.localAmount); + TokenPool_ReleaseOrMintOutV1.store(self.out, b); + }, + toCell(self: TokenPool_ReleaseOrMintPrepared): c.Cell { + return makeCellFrom(self, TokenPool_ReleaseOrMintPrepared.store); + } +} + +/** + > struct TokenPool_TokenTransferFeeConfig { + > destGasOverhead: uint32 + > destBytesOverhead: uint32 + > finalityFeeUSDCents: coins + > fastFinalityFeeUSDCents: coins + > finalityTransferFeeBps: uint16 + > fastFinalityTransferFeeBps: uint16 + > isEnabled: bool + > } + */ +export interface TokenPool_TokenTransferFeeConfig { + readonly $: 'TokenPool_TokenTransferFeeConfig' + destGasOverhead: uint32 + destBytesOverhead: uint32 + finalityFeeUSDCents: coins + fastFinalityFeeUSDCents: coins + finalityTransferFeeBps: uint16 + fastFinalityTransferFeeBps: uint16 + isEnabled: boolean +} + +export const TokenPool_TokenTransferFeeConfig = { + create(args: { + destGasOverhead: uint32 + destBytesOverhead: uint32 + finalityFeeUSDCents: coins + fastFinalityFeeUSDCents: coins + finalityTransferFeeBps: uint16 + fastFinalityTransferFeeBps: uint16 + isEnabled: boolean + }): TokenPool_TokenTransferFeeConfig { + return { + $: 'TokenPool_TokenTransferFeeConfig', + ...args + } + }, + fromSlice(s: c.Slice): TokenPool_TokenTransferFeeConfig { + return { + $: 'TokenPool_TokenTransferFeeConfig', + destGasOverhead: s.loadUintBig(32), + destBytesOverhead: s.loadUintBig(32), + finalityFeeUSDCents: s.loadCoins(), + fastFinalityFeeUSDCents: s.loadCoins(), + finalityTransferFeeBps: s.loadUintBig(16), + fastFinalityTransferFeeBps: s.loadUintBig(16), + isEnabled: s.loadBoolean(), + } + }, + store(self: TokenPool_TokenTransferFeeConfig, b: c.Builder): void { + b.storeUint(self.destGasOverhead, 32); + b.storeUint(self.destBytesOverhead, 32); + b.storeCoins(self.finalityFeeUSDCents); + b.storeCoins(self.fastFinalityFeeUSDCents); + b.storeUint(self.finalityTransferFeeBps, 16); + b.storeUint(self.fastFinalityTransferFeeBps, 16); + b.storeBit(self.isEnabled); + }, + toCell(self: TokenPool_TokenTransferFeeConfig): c.Cell { + return makeCellFrom(self, TokenPool_TokenTransferFeeConfig.store); + } +} + +/** + > struct TokenPool_Transfer { + > id: uint256 + > details: Cell> + > } + */ +export interface TokenPool_Transfer { + readonly $: 'TokenPool_Transfer' + id: uint256 + details: TokenPool_TransferDetails +} + +export const TokenPool_Transfer = { + create(args: { + id: uint256 + details: TokenPool_TransferDetails + }): TokenPool_Transfer { + return { + $: 'TokenPool_Transfer', + ...args + } + }, +} + +/** + > struct TokenPool_TransferDetails { + > receiver: R + > remoteChainSelector: uint64 + > originalSender: S + > amount: C + > localToken: address + > } + */ +export interface TokenPool_TransferDetails { + readonly $: 'TokenPool_TransferDetails' + receiver: R + remoteChainSelector: uint64 + originalSender: S + amount: C + localToken: c.Address +} + +export const TokenPool_TransferDetails = { + create(args: { + receiver: R + remoteChainSelector: uint64 + originalSender: S + amount: C + localToken: c.Address + }): TokenPool_TransferDetails { + return { + $: 'TokenPool_TransferDetails', + ...args + } + }, +} + +/** + > type TokenPool_LockOrBurnTransfer = TokenPool_Transfer, coins> + */ +export type TokenPool_LockOrBurnTransfer = TokenPool_Transfer + +export const TokenPool_LockOrBurnTransfer = { + fromSlice(s: c.Slice): TokenPool_LockOrBurnTransfer { + return (() => { + return { + $: 'TokenPool_Transfer', + id: s.loadUintBig(256), + details: loadCellRef>(s, + (s) => (() => { + return { + $: 'TokenPool_TransferDetails', + receiver: loadCellRef(s, CrossChainAddress.fromSlice), + remoteChainSelector: s.loadUintBig(64), + originalSender: s.loadAddress(), + amount: s.loadCoins(), + localToken: s.loadAddress(), + } + })() + ), + } + })(); + }, + store(self: TokenPool_LockOrBurnTransfer, b: c.Builder): void { + b.storeUint(self.id, 256); + storeCellRef>(self.details, b, + (v,b) => { storeCellRef(v.receiver, b, CrossChainAddress.store); + b.storeUint(v.remoteChainSelector, 64); + b.storeAddress(v.originalSender); + b.storeCoins(v.amount); + b.storeAddress(v.localToken); } + ); + }, + toCell(self: TokenPool_LockOrBurnTransfer): c.Cell { + return makeCellFrom(self, TokenPool_LockOrBurnTransfer.store); + } +} + +/** + > type TokenPool_ReleaseOrMintTransfer = TokenPool_Transfer, address, uint256> + */ +export type TokenPool_ReleaseOrMintTransfer = TokenPool_Transfer + +export const TokenPool_ReleaseOrMintTransfer = { + fromSlice(s: c.Slice): TokenPool_ReleaseOrMintTransfer { + return (() => { + return { + $: 'TokenPool_Transfer', + id: s.loadUintBig(256), + details: loadCellRef>(s, + (s) => (() => { + return { + $: 'TokenPool_TransferDetails', + receiver: s.loadAddress(), + remoteChainSelector: s.loadUintBig(64), + originalSender: loadCellRef(s, CrossChainAddress.fromSlice), + amount: s.loadUintBig(256), + localToken: s.loadAddress(), + } + })() + ), + } + })(); + }, + store(self: TokenPool_ReleaseOrMintTransfer, b: c.Builder): void { + b.storeUint(self.id, 256); + storeCellRef>(self.details, b, + (v,b) => { b.storeAddress(v.receiver); + b.storeUint(v.remoteChainSelector, 64); + storeCellRef(v.originalSender, b, CrossChainAddress.store); + b.storeUint(v.amount, 256); + b.storeAddress(v.localToken); } + ); + }, + toCell(self: TokenPool_ReleaseOrMintTransfer): c.Cell { + return makeCellFrom(self, TokenPool_ReleaseOrMintTransfer.store); + } +} + +/** + > struct TokenPool_LockOrBurnInV1 { + > transfer: TokenPool_LockOrBurnTransfer + > } + */ +export interface TokenPool_LockOrBurnInV1 { + readonly $: 'TokenPool_LockOrBurnInV1' + transfer: TokenPool_LockOrBurnTransfer +} + +export const TokenPool_LockOrBurnInV1 = { + create(args: { + transfer: TokenPool_LockOrBurnTransfer + }): TokenPool_LockOrBurnInV1 { + return { + $: 'TokenPool_LockOrBurnInV1', + ...args + } + }, + fromSlice(s: c.Slice): TokenPool_LockOrBurnInV1 { + return { + $: 'TokenPool_LockOrBurnInV1', + transfer: TokenPool_LockOrBurnTransfer.fromSlice(s), + } + }, + store(self: TokenPool_LockOrBurnInV1, b: c.Builder): void { + TokenPool_LockOrBurnTransfer.store(self.transfer, b); + }, + toCell(self: TokenPool_LockOrBurnInV1): c.Cell { + return makeCellFrom(self, TokenPool_LockOrBurnInV1.store); + } +} + +/** + > struct TokenPool_LockOrBurnOutV1 { + > destTokenAddress: Cell + > destPoolData: cell + > } + */ +export interface TokenPool_LockOrBurnOutV1 { + readonly $: 'TokenPool_LockOrBurnOutV1' + destTokenAddress: CrossChainAddress + destPoolData: c.Cell +} + +export const TokenPool_LockOrBurnOutV1 = { + create(args: { + destTokenAddress: CrossChainAddress + destPoolData: c.Cell + }): TokenPool_LockOrBurnOutV1 { + return { + $: 'TokenPool_LockOrBurnOutV1', + ...args + } + }, + fromSlice(s: c.Slice): TokenPool_LockOrBurnOutV1 { + return { + $: 'TokenPool_LockOrBurnOutV1', + destTokenAddress: loadCellRef(s, CrossChainAddress.fromSlice), + destPoolData: s.loadRef(), + } + }, + store(self: TokenPool_LockOrBurnOutV1, b: c.Builder): void { + storeCellRef(self.destTokenAddress, b, CrossChainAddress.store); + b.storeRef(self.destPoolData); + }, + toCell(self: TokenPool_LockOrBurnOutV1): c.Cell { + return makeCellFrom(self, TokenPool_LockOrBurnOutV1.store); + } +} + +/** + > struct TokenPool_ReleaseOrMintInV1 { + > transfer: TokenPool_ReleaseOrMintTransfer + > sourcePoolAddress: Cell + > sourcePoolData: cell? + > offchainTokenData: cell? + > } + */ +export interface TokenPool_ReleaseOrMintInV1 { + readonly $: 'TokenPool_ReleaseOrMintInV1' + transfer: TokenPool_ReleaseOrMintTransfer + sourcePoolAddress: CrossChainAddress + sourcePoolData: c.Cell | null + offchainTokenData: c.Cell | null +} + +export const TokenPool_ReleaseOrMintInV1 = { + create(args: { + transfer: TokenPool_ReleaseOrMintTransfer + sourcePoolAddress: CrossChainAddress + sourcePoolData: c.Cell | null + offchainTokenData: c.Cell | null + }): TokenPool_ReleaseOrMintInV1 { + return { + $: 'TokenPool_ReleaseOrMintInV1', + ...args + } + }, + fromSlice(s: c.Slice): TokenPool_ReleaseOrMintInV1 { + return { + $: 'TokenPool_ReleaseOrMintInV1', + transfer: TokenPool_ReleaseOrMintTransfer.fromSlice(s), + sourcePoolAddress: loadCellRef(s, CrossChainAddress.fromSlice), + sourcePoolData: s.loadBoolean() ? s.loadRef() : null, + offchainTokenData: s.loadBoolean() ? s.loadRef() : null, + } + }, + store(self: TokenPool_ReleaseOrMintInV1, b: c.Builder): void { + TokenPool_ReleaseOrMintTransfer.store(self.transfer, b); + storeCellRef(self.sourcePoolAddress, b, CrossChainAddress.store); + storeTolkNullable(self.sourcePoolData, b, + (v,b) => b.storeRef(v) + ); + storeTolkNullable(self.offchainTokenData, b, + (v,b) => b.storeRef(v) + ); + }, + toCell(self: TokenPool_ReleaseOrMintInV1): c.Cell { + return makeCellFrom(self, TokenPool_ReleaseOrMintInV1.store); + } +} + +/** + > struct TokenPool_ReleaseOrMintOutV1 { + > destinationAmount: coins + > } + */ +export interface TokenPool_ReleaseOrMintOutV1 { + readonly $: 'TokenPool_ReleaseOrMintOutV1' + destinationAmount: coins +} + +export const TokenPool_ReleaseOrMintOutV1 = { + create(args: { + destinationAmount: coins + }): TokenPool_ReleaseOrMintOutV1 { + return { + $: 'TokenPool_ReleaseOrMintOutV1', + ...args + } + }, + fromSlice(s: c.Slice): TokenPool_ReleaseOrMintOutV1 { + return { + $: 'TokenPool_ReleaseOrMintOutV1', + destinationAmount: s.loadCoins(), + } + }, + store(self: TokenPool_ReleaseOrMintOutV1, b: c.Builder): void { + b.storeCoins(self.destinationAmount); + }, + toCell(self: TokenPool_ReleaseOrMintOutV1): c.Cell { + return makeCellFrom(self, TokenPool_ReleaseOrMintOutV1.store); + } +} + +/** + > struct TokenPool_LockedOrBurned { + > remoteChainSelector: uint64 + > details: Cell + > } + */ +export interface TokenPool_LockedOrBurned { + readonly $: 'TokenPool_LockedOrBurned' + remoteChainSelector: uint64 + details: TokenPool_LockedOrBurnedDetails +} + +export const TokenPool_LockedOrBurned = { + create(args: { + remoteChainSelector: uint64 + details: TokenPool_LockedOrBurnedDetails + }): TokenPool_LockedOrBurned { + return { + $: 'TokenPool_LockedOrBurned', + ...args + } + }, + fromSlice(s: c.Slice): TokenPool_LockedOrBurned { + return { + $: 'TokenPool_LockedOrBurned', + remoteChainSelector: s.loadUintBig(64), + details: loadCellRef(s, TokenPool_LockedOrBurnedDetails.fromSlice), + } + }, + store(self: TokenPool_LockedOrBurned, b: c.Builder): void { + b.storeUint(self.remoteChainSelector, 64); + storeCellRef(self.details, b, TokenPool_LockedOrBurnedDetails.store); + }, + toCell(self: TokenPool_LockedOrBurned): c.Cell { + return makeCellFrom(self, TokenPool_LockedOrBurned.store); + } +} + +/** + > struct TokenPool_LockedOrBurnedDetails { + > token: address + > sender: address + > amount: coins + > } + */ +export interface TokenPool_LockedOrBurnedDetails { + readonly $: 'TokenPool_LockedOrBurnedDetails' + token: c.Address + sender: c.Address + amount: coins +} + +export const TokenPool_LockedOrBurnedDetails = { + create(args: { + token: c.Address + sender: c.Address + amount: coins + }): TokenPool_LockedOrBurnedDetails { + return { + $: 'TokenPool_LockedOrBurnedDetails', + ...args + } + }, + fromSlice(s: c.Slice): TokenPool_LockedOrBurnedDetails { + return { + $: 'TokenPool_LockedOrBurnedDetails', + token: s.loadAddress(), + sender: s.loadAddress(), + amount: s.loadCoins(), + } + }, + store(self: TokenPool_LockedOrBurnedDetails, b: c.Builder): void { + b.storeAddress(self.token); + b.storeAddress(self.sender); + b.storeCoins(self.amount); + }, + toCell(self: TokenPool_LockedOrBurnedDetails): c.Cell { + return makeCellFrom(self, TokenPool_LockedOrBurnedDetails.store); + } +} + +/** + > struct TokenPool_ReleasedOrMinted { + > remoteChainSelector: uint64 + > details: Cell + > } + */ +export interface TokenPool_ReleasedOrMinted { + readonly $: 'TokenPool_ReleasedOrMinted' + remoteChainSelector: uint64 + details: TokenPool_ReleasedOrMintedDetails +} + +export const TokenPool_ReleasedOrMinted = { + create(args: { + remoteChainSelector: uint64 + details: TokenPool_ReleasedOrMintedDetails + }): TokenPool_ReleasedOrMinted { + return { + $: 'TokenPool_ReleasedOrMinted', + ...args + } + }, + fromSlice(s: c.Slice): TokenPool_ReleasedOrMinted { + return { + $: 'TokenPool_ReleasedOrMinted', + remoteChainSelector: s.loadUintBig(64), + details: loadCellRef(s, TokenPool_ReleasedOrMintedDetails.fromSlice), + } + }, + store(self: TokenPool_ReleasedOrMinted, b: c.Builder): void { + b.storeUint(self.remoteChainSelector, 64); + storeCellRef(self.details, b, TokenPool_ReleasedOrMintedDetails.store); + }, + toCell(self: TokenPool_ReleasedOrMinted): c.Cell { + return makeCellFrom(self, TokenPool_ReleasedOrMinted.store); + } +} + +/** + > struct TokenPool_ReleasedOrMintedDetails { + > token: address + > sender: address + > amount: coins + > recipient: Cell
+ > } + */ +export interface TokenPool_ReleasedOrMintedDetails { + readonly $: 'TokenPool_ReleasedOrMintedDetails' + token: c.Address + sender: c.Address + amount: coins + recipient: c.Address +} + +export const TokenPool_ReleasedOrMintedDetails = { + create(args: { + token: c.Address + sender: c.Address + amount: coins + recipient: c.Address + }): TokenPool_ReleasedOrMintedDetails { + return { + $: 'TokenPool_ReleasedOrMintedDetails', + ...args + } + }, + fromSlice(s: c.Slice): TokenPool_ReleasedOrMintedDetails { + return { + $: 'TokenPool_ReleasedOrMintedDetails', + token: s.loadAddress(), + sender: s.loadAddress(), + amount: s.loadCoins(), + recipient: loadCellRef(s, + (s) => s.loadAddress() + ), + } + }, + store(self: TokenPool_ReleasedOrMintedDetails, b: c.Builder): void { + b.storeAddress(self.token); + b.storeAddress(self.sender); + b.storeCoins(self.amount); + storeCellRef(self.recipient, b, + (v,b) => b.storeAddress(v) + ); + }, + toCell(self: TokenPool_ReleasedOrMintedDetails): c.Cell { + return makeCellFrom(self, TokenPool_ReleasedOrMintedDetails.store); + } +} + +/** + > struct TokenPool_ChainAdded { + > remoteChainSelector: uint64 + > remoteTokenAddress: Cell + > } + */ +export interface TokenPool_ChainAdded { + readonly $: 'TokenPool_ChainAdded' + remoteChainSelector: uint64 + remoteTokenAddress: CrossChainAddress +} + +export const TokenPool_ChainAdded = { + create(args: { + remoteChainSelector: uint64 + remoteTokenAddress: CrossChainAddress + }): TokenPool_ChainAdded { + return { + $: 'TokenPool_ChainAdded', + ...args + } + }, + fromSlice(s: c.Slice): TokenPool_ChainAdded { + return { + $: 'TokenPool_ChainAdded', + remoteChainSelector: s.loadUintBig(64), + remoteTokenAddress: loadCellRef(s, CrossChainAddress.fromSlice), + } + }, + store(self: TokenPool_ChainAdded, b: c.Builder): void { + b.storeUint(self.remoteChainSelector, 64); + storeCellRef(self.remoteTokenAddress, b, CrossChainAddress.store); + }, + toCell(self: TokenPool_ChainAdded): c.Cell { + return makeCellFrom(self, TokenPool_ChainAdded.store); + } +} + +/** + > struct TokenPool_ChainRemoved { + > remoteChainSelector: uint64 + > } + */ +export interface TokenPool_ChainRemoved { + readonly $: 'TokenPool_ChainRemoved' + remoteChainSelector: uint64 +} + +export const TokenPool_ChainRemoved = { + create(args: { + remoteChainSelector: uint64 + }): TokenPool_ChainRemoved { + return { + $: 'TokenPool_ChainRemoved', + ...args + } + }, + fromSlice(s: c.Slice): TokenPool_ChainRemoved { + return { + $: 'TokenPool_ChainRemoved', + remoteChainSelector: s.loadUintBig(64), + } + }, + store(self: TokenPool_ChainRemoved, b: c.Builder): void { + b.storeUint(self.remoteChainSelector, 64); + }, + toCell(self: TokenPool_ChainRemoved): c.Cell { + return makeCellFrom(self, TokenPool_ChainRemoved.store); + } +} + +/** + > struct TokenPool_RemotePoolAdded { + > remoteChainSelector: uint64 + > remotePoolAddress: Cell + > } + */ +export interface TokenPool_RemotePoolAdded { + readonly $: 'TokenPool_RemotePoolAdded' + remoteChainSelector: uint64 + remotePoolAddress: CrossChainAddress +} + +export const TokenPool_RemotePoolAdded = { + create(args: { + remoteChainSelector: uint64 + remotePoolAddress: CrossChainAddress + }): TokenPool_RemotePoolAdded { + return { + $: 'TokenPool_RemotePoolAdded', + ...args + } + }, + fromSlice(s: c.Slice): TokenPool_RemotePoolAdded { + return { + $: 'TokenPool_RemotePoolAdded', + remoteChainSelector: s.loadUintBig(64), + remotePoolAddress: loadCellRef(s, CrossChainAddress.fromSlice), + } + }, + store(self: TokenPool_RemotePoolAdded, b: c.Builder): void { + b.storeUint(self.remoteChainSelector, 64); + storeCellRef(self.remotePoolAddress, b, CrossChainAddress.store); + }, + toCell(self: TokenPool_RemotePoolAdded): c.Cell { + return makeCellFrom(self, TokenPool_RemotePoolAdded.store); + } +} + +/** + > struct TokenPool_RemotePoolRemoved { + > remoteChainSelector: uint64 + > remotePoolAddress: Cell + > } + */ +export interface TokenPool_RemotePoolRemoved { + readonly $: 'TokenPool_RemotePoolRemoved' + remoteChainSelector: uint64 + remotePoolAddress: CrossChainAddress +} + +export const TokenPool_RemotePoolRemoved = { + create(args: { + remoteChainSelector: uint64 + remotePoolAddress: CrossChainAddress + }): TokenPool_RemotePoolRemoved { + return { + $: 'TokenPool_RemotePoolRemoved', + ...args + } + }, + fromSlice(s: c.Slice): TokenPool_RemotePoolRemoved { + return { + $: 'TokenPool_RemotePoolRemoved', + remoteChainSelector: s.loadUintBig(64), + remotePoolAddress: loadCellRef(s, CrossChainAddress.fromSlice), + } + }, + store(self: TokenPool_RemotePoolRemoved, b: c.Builder): void { + b.storeUint(self.remoteChainSelector, 64); + storeCellRef(self.remotePoolAddress, b, CrossChainAddress.store); + }, + toCell(self: TokenPool_RemotePoolRemoved): c.Cell { + return makeCellFrom(self, TokenPool_RemotePoolRemoved.store); + } +} + +/** + > struct TokenPool_OutboundRateLimitConsumed { + > remoteChainSelector: uint64 + > token: address + > amount: coins + > } + */ +export interface TokenPool_OutboundRateLimitConsumed { + readonly $: 'TokenPool_OutboundRateLimitConsumed' + remoteChainSelector: uint64 + token: c.Address + amount: coins +} + +export const TokenPool_OutboundRateLimitConsumed = { + create(args: { + remoteChainSelector: uint64 + token: c.Address + amount: coins + }): TokenPool_OutboundRateLimitConsumed { + return { + $: 'TokenPool_OutboundRateLimitConsumed', + ...args + } + }, + fromSlice(s: c.Slice): TokenPool_OutboundRateLimitConsumed { + return { + $: 'TokenPool_OutboundRateLimitConsumed', + remoteChainSelector: s.loadUintBig(64), + token: s.loadAddress(), + amount: s.loadCoins(), + } + }, + store(self: TokenPool_OutboundRateLimitConsumed, b: c.Builder): void { + b.storeUint(self.remoteChainSelector, 64); + b.storeAddress(self.token); + b.storeCoins(self.amount); + }, + toCell(self: TokenPool_OutboundRateLimitConsumed): c.Cell { + return makeCellFrom(self, TokenPool_OutboundRateLimitConsumed.store); + } +} + +/** + > struct TokenPool_InboundRateLimitConsumed { + > remoteChainSelector: uint64 + > token: address + > amount: coins + > } + */ +export interface TokenPool_InboundRateLimitConsumed { + readonly $: 'TokenPool_InboundRateLimitConsumed' + remoteChainSelector: uint64 + token: c.Address + amount: coins +} + +export const TokenPool_InboundRateLimitConsumed = { + create(args: { + remoteChainSelector: uint64 + token: c.Address + amount: coins + }): TokenPool_InboundRateLimitConsumed { + return { + $: 'TokenPool_InboundRateLimitConsumed', + ...args + } + }, + fromSlice(s: c.Slice): TokenPool_InboundRateLimitConsumed { + return { + $: 'TokenPool_InboundRateLimitConsumed', + remoteChainSelector: s.loadUintBig(64), + token: s.loadAddress(), + amount: s.loadCoins(), + } + }, + store(self: TokenPool_InboundRateLimitConsumed, b: c.Builder): void { + b.storeUint(self.remoteChainSelector, 64); + b.storeAddress(self.token); + b.storeCoins(self.amount); + }, + toCell(self: TokenPool_InboundRateLimitConsumed): c.Cell { + return makeCellFrom(self, TokenPool_InboundRateLimitConsumed.store); + } +} + +/** + > struct TokenPool_FastFinalityOutboundRateLimitConsumed { + > remoteChainSelector: uint64 + > token: address + > amount: coins + > } + */ +export interface TokenPool_FastFinalityOutboundRateLimitConsumed { + readonly $: 'TokenPool_FastFinalityOutboundRateLimitConsumed' + remoteChainSelector: uint64 + token: c.Address + amount: coins +} + +export const TokenPool_FastFinalityOutboundRateLimitConsumed = { + create(args: { + remoteChainSelector: uint64 + token: c.Address + amount: coins + }): TokenPool_FastFinalityOutboundRateLimitConsumed { + return { + $: 'TokenPool_FastFinalityOutboundRateLimitConsumed', + ...args + } + }, + fromSlice(s: c.Slice): TokenPool_FastFinalityOutboundRateLimitConsumed { + return { + $: 'TokenPool_FastFinalityOutboundRateLimitConsumed', + remoteChainSelector: s.loadUintBig(64), + token: s.loadAddress(), + amount: s.loadCoins(), + } + }, + store(self: TokenPool_FastFinalityOutboundRateLimitConsumed, b: c.Builder): void { + b.storeUint(self.remoteChainSelector, 64); + b.storeAddress(self.token); + b.storeCoins(self.amount); + }, + toCell(self: TokenPool_FastFinalityOutboundRateLimitConsumed): c.Cell { + return makeCellFrom(self, TokenPool_FastFinalityOutboundRateLimitConsumed.store); + } +} + +/** + > struct TokenPool_FastFinalityInboundRateLimitConsumed { + > remoteChainSelector: uint64 + > token: address + > amount: coins + > } + */ +export interface TokenPool_FastFinalityInboundRateLimitConsumed { + readonly $: 'TokenPool_FastFinalityInboundRateLimitConsumed' + remoteChainSelector: uint64 + token: c.Address + amount: coins +} + +export const TokenPool_FastFinalityInboundRateLimitConsumed = { + create(args: { + remoteChainSelector: uint64 + token: c.Address + amount: coins + }): TokenPool_FastFinalityInboundRateLimitConsumed { + return { + $: 'TokenPool_FastFinalityInboundRateLimitConsumed', + ...args + } + }, + fromSlice(s: c.Slice): TokenPool_FastFinalityInboundRateLimitConsumed { + return { + $: 'TokenPool_FastFinalityInboundRateLimitConsumed', + remoteChainSelector: s.loadUintBig(64), + token: s.loadAddress(), + amount: s.loadCoins(), + } + }, + store(self: TokenPool_FastFinalityInboundRateLimitConsumed, b: c.Builder): void { + b.storeUint(self.remoteChainSelector, 64); + b.storeAddress(self.token); + b.storeCoins(self.amount); + }, + toCell(self: TokenPool_FastFinalityInboundRateLimitConsumed): c.Cell { + return makeCellFrom(self, TokenPool_FastFinalityInboundRateLimitConsumed.store); + } +} + +/** + > struct TokenPool_OutboundRateLimitRefunded { + > remoteChainSelector: uint64 + > token: address + > amount: coins + > } + */ +export interface TokenPool_OutboundRateLimitRefunded { + readonly $: 'TokenPool_OutboundRateLimitRefunded' + remoteChainSelector: uint64 + token: c.Address + amount: coins +} + +export const TokenPool_OutboundRateLimitRefunded = { + create(args: { + remoteChainSelector: uint64 + token: c.Address + amount: coins + }): TokenPool_OutboundRateLimitRefunded { + return { + $: 'TokenPool_OutboundRateLimitRefunded', + ...args + } + }, + fromSlice(s: c.Slice): TokenPool_OutboundRateLimitRefunded { + return { + $: 'TokenPool_OutboundRateLimitRefunded', + remoteChainSelector: s.loadUintBig(64), + token: s.loadAddress(), + amount: s.loadCoins(), + } + }, + store(self: TokenPool_OutboundRateLimitRefunded, b: c.Builder): void { + b.storeUint(self.remoteChainSelector, 64); + b.storeAddress(self.token); + b.storeCoins(self.amount); + }, + toCell(self: TokenPool_OutboundRateLimitRefunded): c.Cell { + return makeCellFrom(self, TokenPool_OutboundRateLimitRefunded.store); + } +} + +/** + > struct TokenPool_InboundRateLimitRefunded { + > remoteChainSelector: uint64 + > token: address + > amount: coins + > } + */ +export interface TokenPool_InboundRateLimitRefunded { + readonly $: 'TokenPool_InboundRateLimitRefunded' + remoteChainSelector: uint64 + token: c.Address + amount: coins +} + +export const TokenPool_InboundRateLimitRefunded = { + create(args: { + remoteChainSelector: uint64 + token: c.Address + amount: coins + }): TokenPool_InboundRateLimitRefunded { + return { + $: 'TokenPool_InboundRateLimitRefunded', + ...args + } + }, + fromSlice(s: c.Slice): TokenPool_InboundRateLimitRefunded { + return { + $: 'TokenPool_InboundRateLimitRefunded', + remoteChainSelector: s.loadUintBig(64), + token: s.loadAddress(), + amount: s.loadCoins(), + } + }, + store(self: TokenPool_InboundRateLimitRefunded, b: c.Builder): void { + b.storeUint(self.remoteChainSelector, 64); + b.storeAddress(self.token); + b.storeCoins(self.amount); + }, + toCell(self: TokenPool_InboundRateLimitRefunded): c.Cell { + return makeCellFrom(self, TokenPool_InboundRateLimitRefunded.store); + } +} + +/** + > struct TokenPool_FastFinalityOutboundRateLimitRefunded { + > remoteChainSelector: uint64 + > token: address + > amount: coins + > } + */ +export interface TokenPool_FastFinalityOutboundRateLimitRefunded { + readonly $: 'TokenPool_FastFinalityOutboundRateLimitRefunded' + remoteChainSelector: uint64 + token: c.Address + amount: coins +} + +export const TokenPool_FastFinalityOutboundRateLimitRefunded = { + create(args: { + remoteChainSelector: uint64 + token: c.Address + amount: coins + }): TokenPool_FastFinalityOutboundRateLimitRefunded { + return { + $: 'TokenPool_FastFinalityOutboundRateLimitRefunded', + ...args + } + }, + fromSlice(s: c.Slice): TokenPool_FastFinalityOutboundRateLimitRefunded { + return { + $: 'TokenPool_FastFinalityOutboundRateLimitRefunded', + remoteChainSelector: s.loadUintBig(64), + token: s.loadAddress(), + amount: s.loadCoins(), + } + }, + store(self: TokenPool_FastFinalityOutboundRateLimitRefunded, b: c.Builder): void { + b.storeUint(self.remoteChainSelector, 64); + b.storeAddress(self.token); + b.storeCoins(self.amount); + }, + toCell(self: TokenPool_FastFinalityOutboundRateLimitRefunded): c.Cell { + return makeCellFrom(self, TokenPool_FastFinalityOutboundRateLimitRefunded.store); + } +} + +/** + > struct TokenPool_FastFinalityInboundRateLimitRefunded { + > remoteChainSelector: uint64 + > token: address + > amount: coins + > } + */ +export interface TokenPool_FastFinalityInboundRateLimitRefunded { + readonly $: 'TokenPool_FastFinalityInboundRateLimitRefunded' + remoteChainSelector: uint64 + token: c.Address + amount: coins +} + +export const TokenPool_FastFinalityInboundRateLimitRefunded = { + create(args: { + remoteChainSelector: uint64 + token: c.Address + amount: coins + }): TokenPool_FastFinalityInboundRateLimitRefunded { + return { + $: 'TokenPool_FastFinalityInboundRateLimitRefunded', + ...args + } + }, + fromSlice(s: c.Slice): TokenPool_FastFinalityInboundRateLimitRefunded { + return { + $: 'TokenPool_FastFinalityInboundRateLimitRefunded', + remoteChainSelector: s.loadUintBig(64), + token: s.loadAddress(), + amount: s.loadCoins(), + } + }, + store(self: TokenPool_FastFinalityInboundRateLimitRefunded, b: c.Builder): void { + b.storeUint(self.remoteChainSelector, 64); + b.storeAddress(self.token); + b.storeCoins(self.amount); + }, + toCell(self: TokenPool_FastFinalityInboundRateLimitRefunded): c.Cell { + return makeCellFrom(self, TokenPool_FastFinalityInboundRateLimitRefunded.store); + } +} + +/** + > struct TokenPool_TokenTransferFeeConfigUpdated { + > destChainSelector: uint64 + > tokenTransferFeeConfig: Cell + > } + */ +export interface TokenPool_TokenTransferFeeConfigUpdated { + readonly $: 'TokenPool_TokenTransferFeeConfigUpdated' + destChainSelector: uint64 + tokenTransferFeeConfig: TokenPool_TokenTransferFeeConfig +} + +export const TokenPool_TokenTransferFeeConfigUpdated = { + create(args: { + destChainSelector: uint64 + tokenTransferFeeConfig: TokenPool_TokenTransferFeeConfig + }): TokenPool_TokenTransferFeeConfigUpdated { + return { + $: 'TokenPool_TokenTransferFeeConfigUpdated', + ...args + } + }, + fromSlice(s: c.Slice): TokenPool_TokenTransferFeeConfigUpdated { + return { + $: 'TokenPool_TokenTransferFeeConfigUpdated', + destChainSelector: s.loadUintBig(64), + tokenTransferFeeConfig: loadCellRef(s, TokenPool_TokenTransferFeeConfig.fromSlice), + } + }, + store(self: TokenPool_TokenTransferFeeConfigUpdated, b: c.Builder): void { + b.storeUint(self.destChainSelector, 64); + storeCellRef(self.tokenTransferFeeConfig, b, TokenPool_TokenTransferFeeConfig.store); + }, + toCell(self: TokenPool_TokenTransferFeeConfigUpdated): c.Cell { + return makeCellFrom(self, TokenPool_TokenTransferFeeConfigUpdated.store); + } +} + +/** + > struct TokenPool_TokenTransferFeeConfigDeleted { + > destChainSelector: uint64 + > } + */ +export interface TokenPool_TokenTransferFeeConfigDeleted { + readonly $: 'TokenPool_TokenTransferFeeConfigDeleted' + destChainSelector: uint64 +} + +export const TokenPool_TokenTransferFeeConfigDeleted = { + create(args: { + destChainSelector: uint64 + }): TokenPool_TokenTransferFeeConfigDeleted { + return { + $: 'TokenPool_TokenTransferFeeConfigDeleted', + ...args + } + }, + fromSlice(s: c.Slice): TokenPool_TokenTransferFeeConfigDeleted { + return { + $: 'TokenPool_TokenTransferFeeConfigDeleted', + destChainSelector: s.loadUintBig(64), + } + }, + store(self: TokenPool_TokenTransferFeeConfigDeleted, b: c.Builder): void { + b.storeUint(self.destChainSelector, 64); + }, + toCell(self: TokenPool_TokenTransferFeeConfigDeleted): c.Cell { + return makeCellFrom(self, TokenPool_TokenTransferFeeConfigDeleted.store); + } +} + +/** + > struct TokenPool_RateLimitConfigured { + > args: TokenPool_RateLimitConfigArgs + > } + */ +export interface TokenPool_RateLimitConfigured { + readonly $: 'TokenPool_RateLimitConfigured' + args: TokenPool_RateLimitConfigArgs +} + +export const TokenPool_RateLimitConfigured = { + create(args: { + args: TokenPool_RateLimitConfigArgs + }): TokenPool_RateLimitConfigured { + return { + $: 'TokenPool_RateLimitConfigured', + ...args + } + }, + fromSlice(s: c.Slice): TokenPool_RateLimitConfigured { + return { + $: 'TokenPool_RateLimitConfigured', + args: TokenPool_RateLimitConfigArgs.fromSlice(s), + } + }, + store(self: TokenPool_RateLimitConfigured, b: c.Builder): void { + TokenPool_RateLimitConfigArgs.store(self.args, b); + }, + toCell(self: TokenPool_RateLimitConfigured): c.Cell { + return makeCellFrom(self, TokenPool_RateLimitConfigured.store); + } +} + +/** + > struct RateLimiter_Config { + > isEnabled: bool + > capacity: uint120 + > rate: uint120 + > } + */ +export interface RateLimiter_Config { + readonly $: 'RateLimiter_Config' + isEnabled: boolean + capacity: uint120 + rate: uint120 +} + +export const RateLimiter_Config = { + create(args: { + isEnabled: boolean + capacity: uint120 + rate: uint120 + }): RateLimiter_Config { + return { + $: 'RateLimiter_Config', + ...args + } + }, + fromSlice(s: c.Slice): RateLimiter_Config { + return { + $: 'RateLimiter_Config', + isEnabled: s.loadBoolean(), + capacity: s.loadUintBig(120), + rate: s.loadUintBig(120), + } + }, + store(self: RateLimiter_Config, b: c.Builder): void { + b.storeBit(self.isEnabled); + b.storeUint(self.capacity, 120); + b.storeUint(self.rate, 120); + }, + toCell(self: RateLimiter_Config): c.Cell { + return makeCellFrom(self, RateLimiter_Config.store); + } +} + +/** + > struct RateLimiter_TokenBucket { + > tokens: uint120 + > lastUpdated: uint64 + > isEnabled: bool + > capacity: uint120 + > rate: uint120 + > } + */ +export interface RateLimiter_TokenBucket { + readonly $: 'RateLimiter_TokenBucket' + tokens: uint120 + lastUpdated: uint64 + isEnabled: boolean + capacity: uint120 + rate: uint120 +} + +export const RateLimiter_TokenBucket = { + create(args: { + tokens: uint120 + lastUpdated: uint64 + isEnabled: boolean + capacity: uint120 + rate: uint120 + }): RateLimiter_TokenBucket { + return { + $: 'RateLimiter_TokenBucket', + ...args + } + }, + fromSlice(s: c.Slice): RateLimiter_TokenBucket { + return { + $: 'RateLimiter_TokenBucket', + tokens: s.loadUintBig(120), + lastUpdated: s.loadUintBig(64), + isEnabled: s.loadBoolean(), + capacity: s.loadUintBig(120), + rate: s.loadUintBig(120), + } + }, + store(self: RateLimiter_TokenBucket, b: c.Builder): void { + b.storeUint(self.tokens, 120); + b.storeUint(self.lastUpdated, 64); + b.storeBit(self.isEnabled); + b.storeUint(self.capacity, 120); + b.storeUint(self.rate, 120); + }, + toCell(self: RateLimiter_TokenBucket): c.Cell { + return makeCellFrom(self, RateLimiter_TokenBucket.store); + } +} + +// ———————————————————————————————————————————— +// class MockTokenPool +// + +interface ExtraSendOptions { + bounce?: boolean // default: false + sendMode?: SendMode // default: SendMode.PAY_GAS_SEPARATELY + extraCurrencies?: c.ExtraCurrency // default: empty dict +} + +interface DeployedAddrOptions { + workchain?: number // default: 0 (basechain) + toShard?: { fixedPrefixLength: number; closeTo: c.Address } + overrideContractCode?: c.Cell +} + +function calculateDeployedAddress(code: c.Cell, data: c.Cell, options: DeployedAddrOptions): c.Address { + const stateInitCell = beginCell().store(c.storeStateInit({ + code, + data, + splitDepth: options.toShard?.fixedPrefixLength, + special: null, + libraries: null, + })).endCell(); + + let addrHash = stateInitCell.hash(); + if (options.toShard) { + const shardDepth = options.toShard.fixedPrefixLength; + addrHash = beginCell() + .storeBits(new c.BitString(options.toShard.closeTo.hash, 0, shardDepth)) + .storeBits(new c.BitString(stateInitCell.hash(), shardDepth, 256 - shardDepth)) + .endCell() + .beginParse().loadBuffer(32); + } + + return new c.Address(options.workchain ?? 0, addrHash); +} + +export class MockTokenPool implements c.Contract { + static CodeCell = c.Cell.fromBase64('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'); + + static Errors = { + 'Common_Error.CrossChainAddressOutOfRange': 5, + 'Utils_Error.InvalidData': 13500, + 'TokenPool_Error.InvalidTransferFeeBps': 14900, + 'TokenPool_Error.InvalidTokenTransferFeeConfig': 14901, + 'TokenPool_Error.ZeroAddressInvalid': 14903, + 'TokenPool_Error.NonExistentChain': 14904, + 'TokenPool_Error.ChainNotAllowed': 14905, + 'TokenPool_Error.CursedByRMN': 14906, + 'TokenPool_Error.ChainAlreadyExists': 14907, + 'TokenPool_Error.InvalidToken': 14909, + 'TokenPool_Error.Unauthorized': 14910, + 'TokenPool_Error.PoolAlreadyAdded': 14911, + 'TokenPool_Error.InvalidRemotePoolForChain': 14912, + 'TokenPool_Error.InvalidRemoteChainDecimals': 14913, + 'TokenPool_Error.OverflowDetected': 14914, + 'TokenPool_Error.CallerIsNotOwnerOrFeeAdmin': 14916, + 'TokenPool_Error.MissingForwardPayload': 14918, + 'TokenPool_Error.MissingTransferInitiator': 14919, + 'TokenPool_Error.AmountMismatch': 14920, + 'TokenPool_Error.InvalidRequestedFinality': 14921, + 'RateLimiter_Error.BucketOverfilled': 16300, + 'RateLimiter_Error.TokenMaxCapacityExceeded': 16301, + 'RateLimiter_Error.TokenRateLimitReached': 16302, + 'Ownable2Step_Error.OnlyCallableByOwner': 49800, + 'Ownable2Step_Error.CannotTransferToSelf': 49801, + 'Ownable2Step_Error.MustBeProposedOwner': 49802, + 'JettonWithdrawable_Error.ZeroAddressNotAllowed': 55700, + 'JettonWithdrawable_Error.UnallowedRecipient': 55701, + 'JettonWithdrawable_Error.MaxAmountExceeded': 55702, + 'JettonWithdrawable_Error.InsufficientValue': 55703, + 'JettonWithdrawable_Error.InvalidWithdrawWallet': 55704, + } + + readonly address: c.Address + readonly init: { code: c.Cell, data: c.Cell } | undefined + + protected constructor(address: c.Address, init?: { code: c.Cell, data: c.Cell }) { + this.address = address; + this.init = init; + } + + static registerCustomPackUnpack( + typeName: string, + packToBuilderFn: CustomPackToBuilderFn | null, + unpackFromSliceFn: CustomUnpackFromSliceFn | null, + ) { + if (customSerializersRegistry.has(typeName)) { + throw new Error(`Custom pack/unpack for 'MockTokenPool.${typeName}' already registered`); + } + customSerializersRegistry.set(typeName, [packToBuilderFn, unpackFromSliceFn]); + } + + static fromAddress(address: c.Address) { + return new MockTokenPool(address); + } + + static fromStorage(emptyStorage: { + poolData: TokenPool_Data + }, deployedOptions?: DeployedAddrOptions) { + const initialState = { + code: deployedOptions?.overrideContractCode ?? MockTokenPool.CodeCell, + data: Storage.toCell(Storage.create(emptyStorage)), + }; + const address = calculateDeployedAddress(initialState.code, initialState.data, deployedOptions ?? {}); + return new MockTokenPool(address, initialState); + } + + static createCellOfTokenPoolLockOrBurn(body: { + queryId?: uint64 + request: TokenPool_LockOrBurnInV1 + requestedFinalityConfig: uint32 + tokenArgs: c.Cell | null + replyTo: c.Address | null + }) { + return TokenPool_LockOrBurn.toCell(TokenPool_LockOrBurn.create(body)); + } + + static createCellOfTransferNotificationForRecipient(body: { + queryId?: uint64 + jettonAmount: coins + transferInitiator: c.Address | null + forwardPayload: ForwardPayloadRemainder + }) { + return TransferNotificationForRecipient.toCell(TransferNotificationForRecipient.create(body)); + } + + static createCellOfTokenPoolPreflightCheckFinished(body: { + queryId?: uint64 + forwardPayload: TokenPool_LockOrBurnForwardPayload + }) { + return TokenPool_PreflightCheckFinished.toCell(TokenPool_PreflightCheckFinished.create(body)); + } + + static createCellOfTokenPoolPreflightCheckFailed(body: { + queryId?: uint64 + forwardPayload: TokenPool_LockOrBurnForwardPayload + }) { + return TokenPool_PreflightCheckFailed.toCell(TokenPool_PreflightCheckFailed.create(body)); + } + + static createCellOfTokenPoolReleaseOrMint(body: { + queryId?: uint64 + request: TokenPool_ReleaseOrMintInV1 + requestedFinalityConfig: uint32 + replyTo?: c.Address | null /* = null */ + }) { + return TokenPool_ReleaseOrMint.toCell(TokenPool_ReleaseOrMint.create(body)); + } + + static createCellOfTokenPoolPostflightCheckFinished(body: { + queryId?: uint64 + forwardPayload: TokenPool_ReleaseOrMintForwardPayload + }) { + return TokenPool_PostflightCheckFinished.toCell(TokenPool_PostflightCheckFinished.create(body)); + } + + static createCellOfTokenPoolPostflightCheckFailed(body: { + queryId?: uint64 + forwardPayload: TokenPool_ReleaseOrMintForwardPayload + }) { + return TokenPool_PostflightCheckFailed.toCell(TokenPool_PostflightCheckFailed.create(body)); + } + + static createCellOfTokenPoolGetCCVs(body: { + queryId?: uint64 + localToken: c.Address + remoteChainSelector: uint64 + amount: coins + requestedFinalityConfig: uint32 + direction: uint8 + extraData: c.Cell | null + replyTo: c.Address + forwardPayload: c.Cell | null + }) { + return TokenPool_GetCCVs.toCell(TokenPool_GetCCVs.create(body)); + } + + static createCellOfTokenPoolGetCCVsAndFees(body: { + queryId?: uint64 + localToken: c.Address + remoteChainSelector: uint64 + amount: coins + requestedFinalityConfig: uint32 + direction: uint8 + extraData: c.Cell | null + forwardPayload: c.Cell | null + }) { + return TokenPool_GetCCVsAndFees.toCell(TokenPool_GetCCVsAndFees.create(body)); + } + + static createCellOfTokenPoolQueryCCVsReply(body: { + queryId?: uint64 + requiredCCVs: SnakedCell + replyPayload: c.Cell | null + }) { + return TokenPool_QueryCCVsReply.toCell(TokenPool_QueryCCVsReply.create(body)); + } + + static createCellOfTokenPoolApplyChainUpdates(body: { + queryId?: uint64 + remoteChainSelectorsToRemove: SnakedCell + chainsToAdd: SnakedCell + }) { + return TokenPool_ApplyChainUpdates.toCell(TokenPool_ApplyChainUpdates.create(body)); + } + + static createCellOfTokenPoolAddRemotePool(body: { + queryId?: uint64 + remoteChainSelector: uint64 + remotePoolAddress: CrossChainAddress + }) { + return TokenPool_AddRemotePool.toCell(TokenPool_AddRemotePool.create(body)); + } + + static createCellOfTokenPoolRemoveRemotePool(body: { + queryId?: uint64 + remoteChainSelector: uint64 + remotePoolAddress: CrossChainAddress + }) { + return TokenPool_RemoveRemotePool.toCell(TokenPool_RemoveRemotePool.create(body)); + } + + static createCellOfTokenPoolSetDynamicConfig(body: { + queryId?: uint64 + router: c.Address + rateLimitAdmin?: c.Address | null /* = null */ + feeAdmin?: c.Address | null /* = null */ + }) { + return TokenPool_SetDynamicConfig.toCell(TokenPool_SetDynamicConfig.create(body)); + } + + static createCellOfTokenPoolSetAllowedFinalityConfig(body: { + queryId?: uint64 + allowedFinalityConfig: uint32 + }) { + return TokenPool_SetAllowedFinalityConfig.toCell(TokenPool_SetAllowedFinalityConfig.create(body)); + } + + static createCellOfTokenPoolSetAdvancedPoolHooks(body: { + queryId?: uint64 + advancedPoolHooks: c.Address | null + }) { + return TokenPool_SetAdvancedPoolHooks.toCell(TokenPool_SetAdvancedPoolHooks.create(body)); + } + + static createCellOfTokenPoolSetDeployableCode(body: { + queryId?: uint64 + deployableCode: c.Cell | null + }) { + return TokenPool_SetDeployableCode.toCell(TokenPool_SetDeployableCode.create(body)); + } + + static createCellOfTokenPoolSetAllowedDepositNamespaces(body: { + queryId?: uint64 + allowedDepositNamespaces: Map + }) { + return TokenPool_SetAllowedDepositNamespaces.toCell(TokenPool_SetAllowedDepositNamespaces.create(body)); + } + + static createCellOfTokenPoolSetRateLimitConfig(body: { + queryId?: uint64 + updates: SnakedCell + }) { + return TokenPool_SetRateLimitConfig.toCell(TokenPool_SetRateLimitConfig.create(body)); + } + + static createCellOfTokenPoolApplyTokenTransferFeeConfigUpdates(body: { + queryId?: uint64 + updates: SnakedCell + disableChainSelectors: SnakedCell + }) { + return TokenPool_ApplyTokenTransferFeeConfigUpdates.toCell(TokenPool_ApplyTokenTransferFeeConfigUpdates.create(body)); + } + + static createCellOfTokenPoolSetRMNProxy(body: { + queryId?: uint64 + rmnProxy: c.Address | null + }) { + return TokenPool_SetRMNProxy.toCell(TokenPool_SetRMNProxy.create(body)); + } + + static createCellOfTokenPoolSetCursedSubjects(body: { + queryId?: uint64 + cursedSubjects: CursedSubjects + }) { + return TokenPool_SetCursedSubjects.toCell(TokenPool_SetCursedSubjects.create(body)); + } + + static createCellOfJettonWithdrawableWithdraw(body: { + queryId?: uint64 + transfers: array + }) { + return JettonWithdrawable_Withdraw.toCell(JettonWithdrawable_Withdraw.create(body)); + } + + async sendDeploy(provider: ContractProvider, via: Sender, msgValue: coins, extraOptions?: ExtraSendOptions) { + return provider.internal(via, { + value: msgValue, + body: c.Cell.EMPTY, + ...extraOptions + }); + } + + send(provider: ContractProvider, via: Sender, msgValue: coins, body: c.Cell, extraOptions?: ExtraSendOptions): Promise { + return provider.internal(via, { + value: msgValue, + body, + ...extraOptions + }); + } + + async sendTokenPoolLockOrBurn(provider: ContractProvider, via: Sender, msgValue: coins, body: { + queryId?: uint64 + request: TokenPool_LockOrBurnInV1 + requestedFinalityConfig: uint32 + tokenArgs: c.Cell | null + replyTo: c.Address | null + }, extraOptions?: ExtraSendOptions) { + return provider.internal(via, { + value: msgValue, + body: TokenPool_LockOrBurn.toCell(TokenPool_LockOrBurn.create(body)), + ...extraOptions + }); + } + + async sendTransferNotificationForRecipient(provider: ContractProvider, via: Sender, msgValue: coins, body: { + queryId?: uint64 + jettonAmount: coins + transferInitiator: c.Address | null + forwardPayload: ForwardPayloadRemainder + }, extraOptions?: ExtraSendOptions) { + return provider.internal(via, { + value: msgValue, + body: TransferNotificationForRecipient.toCell(TransferNotificationForRecipient.create(body)), + ...extraOptions + }); + } + + async sendTokenPoolPreflightCheckFinished(provider: ContractProvider, via: Sender, msgValue: coins, body: { + queryId?: uint64 + forwardPayload: TokenPool_LockOrBurnForwardPayload + }, extraOptions?: ExtraSendOptions) { + return provider.internal(via, { + value: msgValue, + body: TokenPool_PreflightCheckFinished.toCell(TokenPool_PreflightCheckFinished.create(body)), + ...extraOptions + }); + } + + async sendTokenPoolPreflightCheckFailed(provider: ContractProvider, via: Sender, msgValue: coins, body: { + queryId?: uint64 + forwardPayload: TokenPool_LockOrBurnForwardPayload + }, extraOptions?: ExtraSendOptions) { + return provider.internal(via, { + value: msgValue, + body: TokenPool_PreflightCheckFailed.toCell(TokenPool_PreflightCheckFailed.create(body)), + ...extraOptions + }); + } + + async sendTokenPoolReleaseOrMint(provider: ContractProvider, via: Sender, msgValue: coins, body: { + queryId?: uint64 + request: TokenPool_ReleaseOrMintInV1 + requestedFinalityConfig: uint32 + replyTo?: c.Address | null /* = null */ + }, extraOptions?: ExtraSendOptions) { + return provider.internal(via, { + value: msgValue, + body: TokenPool_ReleaseOrMint.toCell(TokenPool_ReleaseOrMint.create(body)), + ...extraOptions + }); + } + + async sendTokenPoolPostflightCheckFinished(provider: ContractProvider, via: Sender, msgValue: coins, body: { + queryId?: uint64 + forwardPayload: TokenPool_ReleaseOrMintForwardPayload + }, extraOptions?: ExtraSendOptions) { + return provider.internal(via, { + value: msgValue, + body: TokenPool_PostflightCheckFinished.toCell(TokenPool_PostflightCheckFinished.create(body)), + ...extraOptions + }); + } + + async sendTokenPoolPostflightCheckFailed(provider: ContractProvider, via: Sender, msgValue: coins, body: { + queryId?: uint64 + forwardPayload: TokenPool_ReleaseOrMintForwardPayload + }, extraOptions?: ExtraSendOptions) { + return provider.internal(via, { + value: msgValue, + body: TokenPool_PostflightCheckFailed.toCell(TokenPool_PostflightCheckFailed.create(body)), + ...extraOptions + }); + } + + async sendTokenPoolGetCCVs(provider: ContractProvider, via: Sender, msgValue: coins, body: { + queryId?: uint64 + localToken: c.Address + remoteChainSelector: uint64 + amount: coins + requestedFinalityConfig: uint32 + direction: uint8 + extraData: c.Cell | null + replyTo: c.Address + forwardPayload: c.Cell | null + }, extraOptions?: ExtraSendOptions) { + return provider.internal(via, { + value: msgValue, + body: TokenPool_GetCCVs.toCell(TokenPool_GetCCVs.create(body)), + ...extraOptions + }); + } + + async sendTokenPoolGetCCVsAndFees(provider: ContractProvider, via: Sender, msgValue: coins, body: { + queryId?: uint64 + localToken: c.Address + remoteChainSelector: uint64 + amount: coins + requestedFinalityConfig: uint32 + direction: uint8 + extraData: c.Cell | null + forwardPayload: c.Cell | null + }, extraOptions?: ExtraSendOptions) { + return provider.internal(via, { + value: msgValue, + body: TokenPool_GetCCVsAndFees.toCell(TokenPool_GetCCVsAndFees.create(body)), + ...extraOptions + }); + } + + async sendTokenPoolQueryCCVsReply(provider: ContractProvider, via: Sender, msgValue: coins, body: { + queryId?: uint64 + requiredCCVs: SnakedCell + replyPayload: c.Cell | null + }, extraOptions?: ExtraSendOptions) { + return provider.internal(via, { + value: msgValue, + body: TokenPool_QueryCCVsReply.toCell(TokenPool_QueryCCVsReply.create(body)), + ...extraOptions + }); + } + + async sendTokenPoolApplyChainUpdates(provider: ContractProvider, via: Sender, msgValue: coins, body: { + queryId?: uint64 + remoteChainSelectorsToRemove: SnakedCell + chainsToAdd: SnakedCell + }, extraOptions?: ExtraSendOptions) { + return provider.internal(via, { + value: msgValue, + body: TokenPool_ApplyChainUpdates.toCell(TokenPool_ApplyChainUpdates.create(body)), + ...extraOptions + }); + } + + async sendTokenPoolAddRemotePool(provider: ContractProvider, via: Sender, msgValue: coins, body: { + queryId?: uint64 + remoteChainSelector: uint64 + remotePoolAddress: CrossChainAddress + }, extraOptions?: ExtraSendOptions) { + return provider.internal(via, { + value: msgValue, + body: TokenPool_AddRemotePool.toCell(TokenPool_AddRemotePool.create(body)), + ...extraOptions + }); + } + + async sendTokenPoolRemoveRemotePool(provider: ContractProvider, via: Sender, msgValue: coins, body: { + queryId?: uint64 + remoteChainSelector: uint64 + remotePoolAddress: CrossChainAddress + }, extraOptions?: ExtraSendOptions) { + return provider.internal(via, { + value: msgValue, + body: TokenPool_RemoveRemotePool.toCell(TokenPool_RemoveRemotePool.create(body)), + ...extraOptions + }); + } + + async sendTokenPoolSetDynamicConfig(provider: ContractProvider, via: Sender, msgValue: coins, body: { + queryId?: uint64 + router: c.Address + rateLimitAdmin?: c.Address | null /* = null */ + feeAdmin?: c.Address | null /* = null */ + }, extraOptions?: ExtraSendOptions) { + return provider.internal(via, { + value: msgValue, + body: TokenPool_SetDynamicConfig.toCell(TokenPool_SetDynamicConfig.create(body)), + ...extraOptions + }); + } + + async sendTokenPoolSetAllowedFinalityConfig(provider: ContractProvider, via: Sender, msgValue: coins, body: { + queryId?: uint64 + allowedFinalityConfig: uint32 + }, extraOptions?: ExtraSendOptions) { + return provider.internal(via, { + value: msgValue, + body: TokenPool_SetAllowedFinalityConfig.toCell(TokenPool_SetAllowedFinalityConfig.create(body)), + ...extraOptions + }); + } + + async sendTokenPoolSetAdvancedPoolHooks(provider: ContractProvider, via: Sender, msgValue: coins, body: { + queryId?: uint64 + advancedPoolHooks: c.Address | null + }, extraOptions?: ExtraSendOptions) { + return provider.internal(via, { + value: msgValue, + body: TokenPool_SetAdvancedPoolHooks.toCell(TokenPool_SetAdvancedPoolHooks.create(body)), + ...extraOptions + }); + } + + async sendTokenPoolSetDeployableCode(provider: ContractProvider, via: Sender, msgValue: coins, body: { + queryId?: uint64 + deployableCode: c.Cell | null + }, extraOptions?: ExtraSendOptions) { + return provider.internal(via, { + value: msgValue, + body: TokenPool_SetDeployableCode.toCell(TokenPool_SetDeployableCode.create(body)), + ...extraOptions + }); + } + + async sendTokenPoolSetAllowedDepositNamespaces(provider: ContractProvider, via: Sender, msgValue: coins, body: { + queryId?: uint64 + allowedDepositNamespaces: Map + }, extraOptions?: ExtraSendOptions) { + return provider.internal(via, { + value: msgValue, + body: TokenPool_SetAllowedDepositNamespaces.toCell(TokenPool_SetAllowedDepositNamespaces.create(body)), + ...extraOptions + }); + } + + async sendTokenPoolSetRateLimitConfig(provider: ContractProvider, via: Sender, msgValue: coins, body: { + queryId?: uint64 + updates: SnakedCell + }, extraOptions?: ExtraSendOptions) { + return provider.internal(via, { + value: msgValue, + body: TokenPool_SetRateLimitConfig.toCell(TokenPool_SetRateLimitConfig.create(body)), + ...extraOptions + }); + } + + async sendTokenPoolApplyTokenTransferFeeConfigUpdates(provider: ContractProvider, via: Sender, msgValue: coins, body: { + queryId?: uint64 + updates: SnakedCell + disableChainSelectors: SnakedCell + }, extraOptions?: ExtraSendOptions) { + return provider.internal(via, { + value: msgValue, + body: TokenPool_ApplyTokenTransferFeeConfigUpdates.toCell(TokenPool_ApplyTokenTransferFeeConfigUpdates.create(body)), + ...extraOptions + }); + } + + async sendTokenPoolSetRMNProxy(provider: ContractProvider, via: Sender, msgValue: coins, body: { + queryId?: uint64 + rmnProxy: c.Address | null + }, extraOptions?: ExtraSendOptions) { + return provider.internal(via, { + value: msgValue, + body: TokenPool_SetRMNProxy.toCell(TokenPool_SetRMNProxy.create(body)), + ...extraOptions + }); + } + + async sendTokenPoolSetCursedSubjects(provider: ContractProvider, via: Sender, msgValue: coins, body: { + queryId?: uint64 + cursedSubjects: CursedSubjects + }, extraOptions?: ExtraSendOptions) { + return provider.internal(via, { + value: msgValue, + body: TokenPool_SetCursedSubjects.toCell(TokenPool_SetCursedSubjects.create(body)), + ...extraOptions + }); + } + + async sendJettonWithdrawableWithdraw(provider: ContractProvider, via: Sender, msgValue: coins, body: { + queryId?: uint64 + transfers: array + }, extraOptions?: ExtraSendOptions) { + return provider.internal(via, { + value: msgValue, + body: JettonWithdrawable_Withdraw.toCell(JettonWithdrawable_Withdraw.create(body)), + ...extraOptions + }); + } +} diff --git a/contracts/wrappers/gen/ccip/Router.ts b/contracts/wrappers/gen/ccip/Router.ts index b88ecde71..1b3890315 100644 --- a/contracts/wrappers/gen/ccip/Router.ts +++ b/contracts/wrappers/gen/ccip/Router.ts @@ -264,6 +264,8 @@ function invokeCustomUnpackFromSlice(typeName: string, s: c.Slice): T { type coins = bigint +type int32 = bigint + type uint16 = bigint type uint32 = bigint type uint64 = bigint @@ -1005,6 +1007,247 @@ export const CursedSubjects = { } } +/** + > type CrossChainAddress = slice + */ +export type CrossChainAddress = c.Slice + +export const CrossChainAddress = { + fromSlice(s: c.Slice): CrossChainAddress { + return invokeCustomUnpackFromSlice('CrossChainAddress', s); + }, + store(self: CrossChainAddress, b: c.Builder): void { + invokeCustomPackToBuilder('CrossChainAddress', self, b); + }, + toCell(self: CrossChainAddress): c.Cell { + return makeCellFrom(self, CrossChainAddress.store); + } +} + +/** + > type ExtraArgs = GenericExtraArgsV2 | SVMExtraArgsV1 | SuiExtraArgsV1 + */ +export type ExtraArgs = + | GenericExtraArgsV2 + | SVMExtraArgsV1 + | SuiExtraArgsV1 + +export const ExtraArgs = { + fromSlice(s: c.Slice): ExtraArgs { + return lookupPrefix(s, 0x181dcf10, 32) ? GenericExtraArgsV2.fromSlice(s) : + lookupPrefix(s, 0x1f3b3aba, 32) ? SVMExtraArgsV1.fromSlice(s) : + lookupPrefix(s, 0x21ea4ca9, 32) ? SuiExtraArgsV1.fromSlice(s) : + throwNonePrefixMatch('ExtraArgs'); + }, + store(self: ExtraArgs, b: c.Builder): void { + switch (self.$) { + case 'GenericExtraArgsV2': + GenericExtraArgsV2.store(self, b); + break; + case 'SVMExtraArgsV1': + SVMExtraArgsV1.store(self, b); + break; + case 'SuiExtraArgsV1': + SuiExtraArgsV1.store(self, b); + break; + } + }, + toCell(self: ExtraArgs): c.Cell { + return makeCellFrom(self, ExtraArgs.store); + } +} + +/** + > struct (0x181dcf10) GenericExtraArgsV2 { + > gasLimit: uint256? + > allowOutOfOrderExecution: bool + > } + */ +export interface GenericExtraArgsV2 { + readonly $: 'GenericExtraArgsV2' + gasLimit: uint256 | null + allowOutOfOrderExecution: boolean +} + +export const GenericExtraArgsV2 = { + PREFIX: 0x181dcf10, + + create(args: { + gasLimit: uint256 | null + allowOutOfOrderExecution: boolean + }): GenericExtraArgsV2 { + return { + $: 'GenericExtraArgsV2', + ...args + } + }, + fromSlice(s: c.Slice): GenericExtraArgsV2 { + loadAndCheckPrefix32(s, 0x181dcf10, 'GenericExtraArgsV2'); + return { + $: 'GenericExtraArgsV2', + gasLimit: s.loadBoolean() ? s.loadUintBig(256) : null, + allowOutOfOrderExecution: s.loadBoolean(), + } + }, + store(self: GenericExtraArgsV2, b: c.Builder): void { + b.storeUint(0x181dcf10, 32); + storeTolkNullable(self.gasLimit, b, + (v,b) => b.storeUint(v, 256) + ); + b.storeBit(self.allowOutOfOrderExecution); + }, + toCell(self: GenericExtraArgsV2): c.Cell { + return makeCellFrom(self, GenericExtraArgsV2.store); + } +} + +/** + > struct (0x1f3b3aba) SVMExtraArgsV1 { + > computeUnits: uint32 + > accountIsWritableBitmap: uint64 + > allowOutOfOrderExecution: bool + > tokenReceiver: uint256 + > accounts: SnakedCell + > } + */ +export interface SVMExtraArgsV1 { + readonly $: 'SVMExtraArgsV1' + computeUnits: uint32 + accountIsWritableBitmap: uint64 + allowOutOfOrderExecution: boolean + tokenReceiver: uint256 + accounts: SnakedCell +} + +export const SVMExtraArgsV1 = { + PREFIX: 0x1f3b3aba, + + create(args: { + computeUnits: uint32 + accountIsWritableBitmap: uint64 + allowOutOfOrderExecution: boolean + tokenReceiver: uint256 + accounts: SnakedCell + }): SVMExtraArgsV1 { + return { + $: 'SVMExtraArgsV1', + ...args + } + }, + fromSlice(s: c.Slice): SVMExtraArgsV1 { + loadAndCheckPrefix32(s, 0x1f3b3aba, 'SVMExtraArgsV1'); + return { + $: 'SVMExtraArgsV1', + computeUnits: s.loadUintBig(32), + accountIsWritableBitmap: s.loadUintBig(64), + allowOutOfOrderExecution: s.loadBoolean(), + tokenReceiver: s.loadUintBig(256), + accounts: loadSnakedCellOf(s, (s) => s.loadUintBig(256)), + } + }, + store(self: SVMExtraArgsV1, b: c.Builder): void { + b.storeUint(0x1f3b3aba, 32); + b.storeUint(self.computeUnits, 32); + b.storeUint(self.accountIsWritableBitmap, 64); + b.storeBit(self.allowOutOfOrderExecution); + b.storeUint(self.tokenReceiver, 256); + storeSnakedCellOf(self.accounts, b, (v, b) => b.storeUint(v, 256)); + }, + toCell(self: SVMExtraArgsV1): c.Cell { + return makeCellFrom(self, SVMExtraArgsV1.store); + } +} + +/** + > struct (0x21ea4ca9) SuiExtraArgsV1 { + > gasLimit: uint256 + > allowOutOfOrderExecution: bool + > tokenReceiver: uint256 + > receiverObjectIds: SnakedCell + > } + */ +export interface SuiExtraArgsV1 { + readonly $: 'SuiExtraArgsV1' + gasLimit: uint256 + allowOutOfOrderExecution: boolean + tokenReceiver: uint256 + receiverObjectIds: SnakedCell +} + +export const SuiExtraArgsV1 = { + PREFIX: 0x21ea4ca9, + + create(args: { + gasLimit: uint256 + allowOutOfOrderExecution: boolean + tokenReceiver: uint256 + receiverObjectIds: SnakedCell + }): SuiExtraArgsV1 { + return { + $: 'SuiExtraArgsV1', + ...args + } + }, + fromSlice(s: c.Slice): SuiExtraArgsV1 { + loadAndCheckPrefix32(s, 0x21ea4ca9, 'SuiExtraArgsV1'); + return { + $: 'SuiExtraArgsV1', + gasLimit: s.loadUintBig(256), + allowOutOfOrderExecution: s.loadBoolean(), + tokenReceiver: s.loadUintBig(256), + receiverObjectIds: loadSnakedCellOf(s, (s) => s.loadUintBig(256)), + } + }, + store(self: SuiExtraArgsV1, b: c.Builder): void { + b.storeUint(0x21ea4ca9, 32); + b.storeUint(self.gasLimit, 256); + b.storeBit(self.allowOutOfOrderExecution); + b.storeUint(self.tokenReceiver, 256); + storeSnakedCellOf(self.receiverObjectIds, b, (v, b) => b.storeUint(v, 256)); + }, + toCell(self: SuiExtraArgsV1): c.Cell { + return makeCellFrom(self, SuiExtraArgsV1.store); + } +} + +/** + > struct TokenAmount { + > amount: coins + > token: address + > } + */ +export interface TokenAmount { + readonly $: 'TokenAmount' + amount: coins + token: c.Address +} + +export const TokenAmount = { + create(args: { + amount: coins + token: c.Address + }): TokenAmount { + return { + $: 'TokenAmount', + ...args + } + }, + fromSlice(s: c.Slice): TokenAmount { + return { + $: 'TokenAmount', + amount: s.loadCoins(), + token: s.loadAddress(), + } + }, + store(self: TokenAmount, b: c.Builder): void { + b.storeCoins(self.amount); + b.storeAddress(self.token); + }, + toCell(self: TokenAmount): c.Cell { + return makeCellFrom(self, TokenAmount.store); + } +} + /** > struct (0xdcf993c2) OnRamp_Send { > msg: Cell @@ -1411,1900 +1654,1965 @@ export const TokenPool_LockOrBurnForwardPayload = { } /** - > struct OnRamps { - > destChainSelectors: SnakedCell - > onRamp: address? + > struct (0x351f77e3) TokenPool_ReleaseOrMint { + > queryId: uint64 + > request: Cell + > requestedFinalityConfig: uint32 + > replyTo: address? > } */ -export interface OnRamps { - readonly $: 'OnRamps' - destChainSelectors: SnakedCell - onRamp: c.Address | null +export interface TokenPool_ReleaseOrMint { + readonly $: 'TokenPool_ReleaseOrMint' + queryId: uint64 + request: TokenPool_ReleaseOrMintInV1 + requestedFinalityConfig: uint32 + replyTo: c.Address | null /* = null */ } -export const OnRamps = { +export const TokenPool_ReleaseOrMint = { + PREFIX: 0x351f77e3, + create(args: { - destChainSelectors: SnakedCell - onRamp: c.Address | null - }): OnRamps { + queryId?: uint64 + request: TokenPool_ReleaseOrMintInV1 + requestedFinalityConfig: uint32 + replyTo?: c.Address | null /* = null */ + }): TokenPool_ReleaseOrMint { return { - $: 'OnRamps', - ...args + $: 'TokenPool_ReleaseOrMint', + replyTo: null, + ...args, + queryId: args.queryId ?? 0n } }, - fromSlice(s: c.Slice): OnRamps { + fromSlice(s: c.Slice): TokenPool_ReleaseOrMint { + loadAndCheckPrefix32(s, 0x351f77e3, 'TokenPool_ReleaseOrMint'); return { - $: 'OnRamps', - destChainSelectors: loadSnakedCellOf(s, (s) => s.loadUintBig(64)), - onRamp: s.loadMaybeAddress(), + $: 'TokenPool_ReleaseOrMint', + queryId: s.loadUintBig(64), + request: loadCellRef(s, TokenPool_ReleaseOrMintInV1.fromSlice), + requestedFinalityConfig: s.loadUintBig(32), + replyTo: s.loadMaybeAddress(), } }, - store(self: OnRamps, b: c.Builder): void { - storeSnakedCellOf(self.destChainSelectors, b, (v, b) => b.storeUint(v, 64)); - b.storeAddress(self.onRamp); + store(self: TokenPool_ReleaseOrMint, b: c.Builder): void { + b.storeUint(0x351f77e3, 32); + b.storeUint(self.queryId, 64); + storeCellRef(self.request, b, TokenPool_ReleaseOrMintInV1.store); + b.storeUint(self.requestedFinalityConfig, 32); + b.storeAddress(self.replyTo); }, - toCell(self: OnRamps): c.Cell { - return makeCellFrom(self, OnRamps.store); + toCell(self: TokenPool_ReleaseOrMint): c.Cell { + return makeCellFrom(self, TokenPool_ReleaseOrMint.store); } } /** - > struct OffRamps { - > sourceChainSelectors: SnakedCell - > offRamp: address + > struct TokenPool_LockOrBurnPrepared { + > feeAmount: coins + > destTokenAmount: coins + > out: TokenPool_LockOrBurnOutV1 > } */ -export interface OffRamps { - readonly $: 'OffRamps' - sourceChainSelectors: SnakedCell - offRamp: c.Address +export interface TokenPool_LockOrBurnPrepared { + readonly $: 'TokenPool_LockOrBurnPrepared' + feeAmount: coins + destTokenAmount: coins + out: TokenPool_LockOrBurnOutV1 } -export const OffRamps = { +export const TokenPool_LockOrBurnPrepared = { create(args: { - sourceChainSelectors: SnakedCell - offRamp: c.Address - }): OffRamps { + feeAmount: coins + destTokenAmount: coins + out: TokenPool_LockOrBurnOutV1 + }): TokenPool_LockOrBurnPrepared { return { - $: 'OffRamps', + $: 'TokenPool_LockOrBurnPrepared', ...args } }, - fromSlice(s: c.Slice): OffRamps { + fromSlice(s: c.Slice): TokenPool_LockOrBurnPrepared { return { - $: 'OffRamps', - sourceChainSelectors: loadSnakedCellOf(s, (s) => s.loadUintBig(64)), - offRamp: s.loadAddress(), + $: 'TokenPool_LockOrBurnPrepared', + feeAmount: s.loadCoins(), + destTokenAmount: s.loadCoins(), + out: TokenPool_LockOrBurnOutV1.fromSlice(s), } }, - store(self: OffRamps, b: c.Builder): void { - storeSnakedCellOf(self.sourceChainSelectors, b, (v, b) => b.storeUint(v, 64)); - b.storeAddress(self.offRamp); + store(self: TokenPool_LockOrBurnPrepared, b: c.Builder): void { + b.storeCoins(self.feeAmount); + b.storeCoins(self.destTokenAmount); + TokenPool_LockOrBurnOutV1.store(self.out, b); }, - toCell(self: OffRamps): c.Cell { - return makeCellFrom(self, OffRamps.store); + toCell(self: TokenPool_LockOrBurnPrepared): c.Cell { + return makeCellFrom(self, TokenPool_LockOrBurnPrepared.store); } } /** - > type Router_GetValidatedFee_Any = Router_GetValidatedFee + > struct TokenPool_Transfer { + > id: uint256 + > details: Cell> + > } */ -export type Router_GetValidatedFee_Any = Router_GetValidatedFee +export interface TokenPool_Transfer { + readonly $: 'TokenPool_Transfer' + id: uint256 + details: TokenPool_TransferDetails +} -export const Router_GetValidatedFee_Any = { - fromSlice(s: c.Slice): Router_GetValidatedFee_Any { - return (() => { - loadAndCheckPrefix32(s, 0x4dd6aa82, 'Router_GetValidatedFee'); - return { - $: 'Router_GetValidatedFee', - ccipSend: loadCellRef(s, Router_CCIPSend.fromSlice), - context: loadTolkRemaining(s), - } - })(); +export const TokenPool_Transfer = { + create(args: { + id: uint256 + details: TokenPool_TransferDetails + }): TokenPool_Transfer { + return { + $: 'TokenPool_Transfer', + ...args + } }, - store(self: Router_GetValidatedFee_Any, b: c.Builder): void { - b.storeUint(0x4dd6aa82, 32); - storeCellRef(self.ccipSend, b, Router_CCIPSend.store); - storeTolkRemaining(self.context, b); +} + +/** + > struct TokenPool_TransferDetails { + > receiver: R + > remoteChainSelector: uint64 + > originalSender: S + > amount: C + > localToken: address + > } + */ +export interface TokenPool_TransferDetails { + readonly $: 'TokenPool_TransferDetails' + receiver: R + remoteChainSelector: uint64 + originalSender: S + amount: C + localToken: c.Address +} + +export const TokenPool_TransferDetails = { + create(args: { + receiver: R + remoteChainSelector: uint64 + originalSender: S + amount: C + localToken: c.Address + }): TokenPool_TransferDetails { + return { + $: 'TokenPool_TransferDetails', + ...args + } }, - toCell(self: Router_GetValidatedFee_Any): c.Cell { - return makeCellFrom(self, Router_GetValidatedFee_Any.store); - } } /** - > type OnRamp_MessageValidated_GetValidatedFeeContext = OnRamp_MessageValidated + > type TokenPool_LockOrBurnTransfer = TokenPool_Transfer, coins> */ -export type OnRamp_MessageValidated_GetValidatedFeeContext = OnRamp_MessageValidated +export type TokenPool_LockOrBurnTransfer = TokenPool_Transfer -export const OnRamp_MessageValidated_GetValidatedFeeContext = { - fromSlice(s: c.Slice): OnRamp_MessageValidated_GetValidatedFeeContext { +export const TokenPool_LockOrBurnTransfer = { + fromSlice(s: c.Slice): TokenPool_LockOrBurnTransfer { return (() => { - loadAndCheckPrefix32(s, 0x2afb11bd, 'OnRamp_MessageValidated'); return { - $: 'OnRamp_MessageValidated', - fee: s.loadCoins(), - msg: loadCellRef(s, Router_CCIPSend.fromSlice), - context: Router_GetValidatedFeeContext.fromSlice(s), + $: 'TokenPool_Transfer', + id: s.loadUintBig(256), + details: loadCellRef>(s, + (s) => (() => { + return { + $: 'TokenPool_TransferDetails', + receiver: loadCellRef(s, CrossChainAddress.fromSlice), + remoteChainSelector: s.loadUintBig(64), + originalSender: s.loadAddress(), + amount: s.loadCoins(), + localToken: s.loadAddress(), + } + })() + ), } })(); }, - store(self: OnRamp_MessageValidated_GetValidatedFeeContext, b: c.Builder): void { - b.storeUint(0x2afb11bd, 32); - b.storeCoins(self.fee); - storeCellRef(self.msg, b, Router_CCIPSend.store); - Router_GetValidatedFeeContext.store(self.context, b); + store(self: TokenPool_LockOrBurnTransfer, b: c.Builder): void { + b.storeUint(self.id, 256); + storeCellRef>(self.details, b, + (v,b) => { storeCellRef(v.receiver, b, CrossChainAddress.store); + b.storeUint(v.remoteChainSelector, 64); + b.storeAddress(v.originalSender); + b.storeCoins(v.amount); + b.storeAddress(v.localToken); } + ); }, - toCell(self: OnRamp_MessageValidated_GetValidatedFeeContext): c.Cell { - return makeCellFrom(self, OnRamp_MessageValidated_GetValidatedFeeContext.store); + toCell(self: TokenPool_LockOrBurnTransfer): c.Cell { + return makeCellFrom(self, TokenPool_LockOrBurnTransfer.store); } } /** - > type OnRamp_MessageValidationFailed_GetValidatedFeeContext = OnRamp_MessageValidationFailed + > type TokenPool_ReleaseOrMintTransfer = TokenPool_Transfer, address, uint256> */ -export type OnRamp_MessageValidationFailed_GetValidatedFeeContext = OnRamp_MessageValidationFailed +export type TokenPool_ReleaseOrMintTransfer = TokenPool_Transfer -export const OnRamp_MessageValidationFailed_GetValidatedFeeContext = { - fromSlice(s: c.Slice): OnRamp_MessageValidationFailed_GetValidatedFeeContext { +export const TokenPool_ReleaseOrMintTransfer = { + fromSlice(s: c.Slice): TokenPool_ReleaseOrMintTransfer { return (() => { - loadAndCheckPrefix32(s, 0xac1dd12e, 'OnRamp_MessageValidationFailed'); return { - $: 'OnRamp_MessageValidationFailed', - error: s.loadUintBig(256), - msg: loadCellRef(s, Router_CCIPSend.fromSlice), - context: Router_GetValidatedFeeContext.fromSlice(s), + $: 'TokenPool_Transfer', + id: s.loadUintBig(256), + details: loadCellRef>(s, + (s) => (() => { + return { + $: 'TokenPool_TransferDetails', + receiver: s.loadAddress(), + remoteChainSelector: s.loadUintBig(64), + originalSender: loadCellRef(s, CrossChainAddress.fromSlice), + amount: s.loadUintBig(256), + localToken: s.loadAddress(), + } + })() + ), } })(); }, - store(self: OnRamp_MessageValidationFailed_GetValidatedFeeContext, b: c.Builder): void { - b.storeUint(0xac1dd12e, 32); - b.storeUint(self.error, 256); - storeCellRef(self.msg, b, Router_CCIPSend.store); - Router_GetValidatedFeeContext.store(self.context, b); + store(self: TokenPool_ReleaseOrMintTransfer, b: c.Builder): void { + b.storeUint(self.id, 256); + storeCellRef>(self.details, b, + (v,b) => { b.storeAddress(v.receiver); + b.storeUint(v.remoteChainSelector, 64); + storeCellRef(v.originalSender, b, CrossChainAddress.store); + b.storeUint(v.amount, 256); + b.storeAddress(v.localToken); } + ); }, - toCell(self: OnRamp_MessageValidationFailed_GetValidatedFeeContext): c.Cell { - return makeCellFrom(self, OnRamp_MessageValidationFailed_GetValidatedFeeContext.store); + toCell(self: TokenPool_ReleaseOrMintTransfer): c.Cell { + return makeCellFrom(self, TokenPool_ReleaseOrMintTransfer.store); } } /** - > struct (0x7db6745d) Router_ApplyRampUpdates { - > queryId: uint64 - > onRampUpdates: OnRamps? - > offRampAdds: OffRamps? - > offRampRemoves: OffRamps? + > struct TokenPool_LockOrBurnInV1 { + > transfer: TokenPool_LockOrBurnTransfer > } */ -export interface Router_ApplyRampUpdates { - readonly $: 'Router_ApplyRampUpdates' - queryId: uint64 - onRampUpdates: OnRamps | null /* = null */ - offRampAdds: OffRamps | null /* = null */ - offRampRemoves: OffRamps | null /* = null */ +export interface TokenPool_LockOrBurnInV1 { + readonly $: 'TokenPool_LockOrBurnInV1' + transfer: TokenPool_LockOrBurnTransfer } -export const Router_ApplyRampUpdates = { - PREFIX: 0x7db6745d, - +export const TokenPool_LockOrBurnInV1 = { create(args: { - queryId?: uint64 - onRampUpdates?: OnRamps | null /* = null */ - offRampAdds?: OffRamps | null /* = null */ - offRampRemoves?: OffRamps | null /* = null */ - }): Router_ApplyRampUpdates { + transfer: TokenPool_LockOrBurnTransfer + }): TokenPool_LockOrBurnInV1 { return { - $: 'Router_ApplyRampUpdates', - onRampUpdates: null, - offRampAdds: null, - offRampRemoves: null, - ...args, - queryId: args.queryId ?? 0n + $: 'TokenPool_LockOrBurnInV1', + ...args } }, - fromSlice(s: c.Slice): Router_ApplyRampUpdates { - loadAndCheckPrefix32(s, 0x7db6745d, 'Router_ApplyRampUpdates'); + fromSlice(s: c.Slice): TokenPool_LockOrBurnInV1 { return { - $: 'Router_ApplyRampUpdates', - queryId: s.loadUintBig(64), - onRampUpdates: s.loadBoolean() ? OnRamps.fromSlice(s) : null, - offRampAdds: s.loadBoolean() ? OffRamps.fromSlice(s) : null, - offRampRemoves: s.loadBoolean() ? OffRamps.fromSlice(s) : null, + $: 'TokenPool_LockOrBurnInV1', + transfer: TokenPool_LockOrBurnTransfer.fromSlice(s), } }, - store(self: Router_ApplyRampUpdates, b: c.Builder): void { - b.storeUint(0x7db6745d, 32); - b.storeUint(self.queryId, 64); - storeTolkNullable(self.onRampUpdates, b, OnRamps.store); - storeTolkNullable(self.offRampAdds, b, OffRamps.store); - storeTolkNullable(self.offRampRemoves, b, OffRamps.store); + store(self: TokenPool_LockOrBurnInV1, b: c.Builder): void { + TokenPool_LockOrBurnTransfer.store(self.transfer, b); }, - toCell(self: Router_ApplyRampUpdates): c.Cell { - return makeCellFrom(self, Router_ApplyRampUpdates.store); + toCell(self: TokenPool_LockOrBurnInV1): c.Cell { + return makeCellFrom(self, TokenPool_LockOrBurnInV1.store); } } /** - > struct (0x31768d95) Router_CCIPSend { - > queryID: uint64 - > destChainSelector: uint64 - > receiver: CrossChainAddress - > data: cell - > tokenAmounts: SnakedCell - > feeToken: address? - > extraArgs: Cell + > struct TokenPool_LockOrBurnOutV1 { + > destTokenAddress: Cell + > destPoolData: cell > } */ -export interface Router_CCIPSend { - readonly $: 'Router_CCIPSend' - queryID: uint64 - destChainSelector: uint64 - receiver: CrossChainAddress - data: c.Cell - tokenAmounts: SnakedCell - feeToken: c.Address | null - extraArgs: ExtraArgs +export interface TokenPool_LockOrBurnOutV1 { + readonly $: 'TokenPool_LockOrBurnOutV1' + destTokenAddress: CrossChainAddress + destPoolData: c.Cell } -export const Router_CCIPSend = { - PREFIX: 0x31768d95, - +export const TokenPool_LockOrBurnOutV1 = { create(args: { - queryID?: uint64 - destChainSelector: uint64 - receiver: CrossChainAddress - data: c.Cell - tokenAmounts: SnakedCell - feeToken: c.Address | null - extraArgs: ExtraArgs - }): Router_CCIPSend { + destTokenAddress: CrossChainAddress + destPoolData: c.Cell + }): TokenPool_LockOrBurnOutV1 { return { - $: 'Router_CCIPSend', - ...args, - queryID: args.queryID ?? 0n + $: 'TokenPool_LockOrBurnOutV1', + ...args } }, - fromSlice(s: c.Slice): Router_CCIPSend { - loadAndCheckPrefix32(s, 0x31768d95, 'Router_CCIPSend'); + fromSlice(s: c.Slice): TokenPool_LockOrBurnOutV1 { return { - $: 'Router_CCIPSend', - queryID: s.loadUintBig(64), - destChainSelector: s.loadUintBig(64), - receiver: CrossChainAddress.fromSlice(s), - data: s.loadRef(), - tokenAmounts: loadSnakedCellOf(s, TokenAmount.fromSlice), - feeToken: s.loadMaybeAddress(), - extraArgs: loadCellRef(s, ExtraArgs.fromSlice), + $: 'TokenPool_LockOrBurnOutV1', + destTokenAddress: loadCellRef(s, CrossChainAddress.fromSlice), + destPoolData: s.loadRef(), } }, - store(self: Router_CCIPSend, b: c.Builder): void { - b.storeUint(0x31768d95, 32); - b.storeUint(self.queryID, 64); - b.storeUint(self.destChainSelector, 64); - CrossChainAddress.store(self.receiver, b); - b.storeRef(self.data); - storeSnakedCellOf(self.tokenAmounts, b, TokenAmount.store); - b.storeAddress(self.feeToken); - storeCellRef(self.extraArgs, b, ExtraArgs.store); + store(self: TokenPool_LockOrBurnOutV1, b: c.Builder): void { + storeCellRef(self.destTokenAddress, b, CrossChainAddress.store); + b.storeRef(self.destPoolData); }, - toCell(self: Router_CCIPSend): c.Cell { - return makeCellFrom(self, Router_CCIPSend.store); + toCell(self: TokenPool_LockOrBurnOutV1): c.Cell { + return makeCellFrom(self, TokenPool_LockOrBurnOutV1.store); } } /** - > struct (0xfc69c50b) Router_RouteMessage { - > message: Cell - > execId: ReceiveExecutorId - > receiver: address - > gasLimit: coins + > struct TokenPool_ReleaseOrMintInV1 { + > transfer: TokenPool_ReleaseOrMintTransfer + > sourcePoolAddress: Cell + > sourcePoolData: cell? + > offchainTokenData: cell? > } */ -export interface Router_RouteMessage { - readonly $: 'Router_RouteMessage' - message: Any2TVMMessage - execId: ReceiveExecutorId - receiver: c.Address - gasLimit: coins +export interface TokenPool_ReleaseOrMintInV1 { + readonly $: 'TokenPool_ReleaseOrMintInV1' + transfer: TokenPool_ReleaseOrMintTransfer + sourcePoolAddress: CrossChainAddress + sourcePoolData: c.Cell | null + offchainTokenData: c.Cell | null } -export const Router_RouteMessage = { - PREFIX: 0xfc69c50b, - +export const TokenPool_ReleaseOrMintInV1 = { create(args: { - message: Any2TVMMessage - execId: ReceiveExecutorId - receiver: c.Address - gasLimit: coins - }): Router_RouteMessage { + transfer: TokenPool_ReleaseOrMintTransfer + sourcePoolAddress: CrossChainAddress + sourcePoolData: c.Cell | null + offchainTokenData: c.Cell | null + }): TokenPool_ReleaseOrMintInV1 { return { - $: 'Router_RouteMessage', + $: 'TokenPool_ReleaseOrMintInV1', ...args } }, - fromSlice(s: c.Slice): Router_RouteMessage { - loadAndCheckPrefix32(s, 0xfc69c50b, 'Router_RouteMessage'); + fromSlice(s: c.Slice): TokenPool_ReleaseOrMintInV1 { return { - $: 'Router_RouteMessage', - message: loadCellRef(s, Any2TVMMessage.fromSlice), - execId: ReceiveExecutorId.fromSlice(s), - receiver: s.loadAddress(), - gasLimit: s.loadCoins(), + $: 'TokenPool_ReleaseOrMintInV1', + transfer: TokenPool_ReleaseOrMintTransfer.fromSlice(s), + sourcePoolAddress: loadCellRef(s, CrossChainAddress.fromSlice), + sourcePoolData: s.loadBoolean() ? s.loadRef() : null, + offchainTokenData: s.loadBoolean() ? s.loadRef() : null, } }, - store(self: Router_RouteMessage, b: c.Builder): void { - b.storeUint(0xfc69c50b, 32); - storeCellRef(self.message, b, Any2TVMMessage.store); - ReceiveExecutorId.store(self.execId, b); - b.storeAddress(self.receiver); - b.storeCoins(self.gasLimit); + store(self: TokenPool_ReleaseOrMintInV1, b: c.Builder): void { + TokenPool_ReleaseOrMintTransfer.store(self.transfer, b); + storeCellRef(self.sourcePoolAddress, b, CrossChainAddress.store); + storeTolkNullable(self.sourcePoolData, b, + (v,b) => b.storeRef(v) + ); + storeTolkNullable(self.offchainTokenData, b, + (v,b) => b.storeRef(v) + ); }, - toCell(self: Router_RouteMessage): c.Cell { - return makeCellFrom(self, Router_RouteMessage.store); + toCell(self: TokenPool_ReleaseOrMintInV1): c.Cell { + return makeCellFrom(self, TokenPool_ReleaseOrMintInV1.store); } } /** - > struct (0x19f0098f) Router_WithdrawToTokenPool { - > queryID: uint64 - > destChainSelector: uint64 - > withdrawRequest: Cell + > struct OnRamps { + > destChainSelectors: SnakedCell + > onRamp: address? > } */ -export interface Router_WithdrawToTokenPool { - readonly $: 'Router_WithdrawToTokenPool' - queryID: uint64 - destChainSelector: uint64 - withdrawRequest: Router_WithdrawRequest +export interface OnRamps { + readonly $: 'OnRamps' + destChainSelectors: SnakedCell + onRamp: c.Address | null } -export const Router_WithdrawToTokenPool = { - PREFIX: 0x19f0098f, - +export const OnRamps = { create(args: { - queryID?: uint64 - destChainSelector: uint64 - withdrawRequest: Router_WithdrawRequest - }): Router_WithdrawToTokenPool { + destChainSelectors: SnakedCell + onRamp: c.Address | null + }): OnRamps { return { - $: 'Router_WithdrawToTokenPool', - ...args, - queryID: args.queryID ?? 0n + $: 'OnRamps', + ...args } }, - fromSlice(s: c.Slice): Router_WithdrawToTokenPool { - loadAndCheckPrefix32(s, 0x19f0098f, 'Router_WithdrawToTokenPool'); + fromSlice(s: c.Slice): OnRamps { return { - $: 'Router_WithdrawToTokenPool', - queryID: s.loadUintBig(64), - destChainSelector: s.loadUintBig(64), - withdrawRequest: loadCellRef(s, Router_WithdrawRequest.fromSlice), + $: 'OnRamps', + destChainSelectors: loadSnakedCellOf(s, (s) => s.loadUintBig(64)), + onRamp: s.loadMaybeAddress(), } }, - store(self: Router_WithdrawToTokenPool, b: c.Builder): void { - b.storeUint(0x19f0098f, 32); - b.storeUint(self.queryID, 64); - b.storeUint(self.destChainSelector, 64); - storeCellRef(self.withdrawRequest, b, Router_WithdrawRequest.store); + store(self: OnRamps, b: c.Builder): void { + storeSnakedCellOf(self.destChainSelectors, b, (v, b) => b.storeUint(v, 64)); + b.storeAddress(self.onRamp); }, - toCell(self: Router_WithdrawToTokenPool): c.Cell { - return makeCellFrom(self, Router_WithdrawToTokenPool.store); + toCell(self: OnRamps): c.Cell { + return makeCellFrom(self, OnRamps.store); } } /** - > struct Router_WithdrawRequest { - > routerWalletAddress: address - > amount: coins - > tokenPool: address - > forwardPayload: Cell + > struct OffRamps { + > sourceChainSelectors: SnakedCell + > offRamp: address > } */ -export interface Router_WithdrawRequest { - readonly $: 'Router_WithdrawRequest' - routerWalletAddress: c.Address - amount: coins - tokenPool: c.Address - forwardPayload: TokenPool_LockOrBurnForwardPayload +export interface OffRamps { + readonly $: 'OffRamps' + sourceChainSelectors: SnakedCell + offRamp: c.Address } -export const Router_WithdrawRequest = { +export const OffRamps = { create(args: { - routerWalletAddress: c.Address - amount: coins - tokenPool: c.Address - forwardPayload: TokenPool_LockOrBurnForwardPayload - }): Router_WithdrawRequest { + sourceChainSelectors: SnakedCell + offRamp: c.Address + }): OffRamps { return { - $: 'Router_WithdrawRequest', + $: 'OffRamps', ...args } }, - fromSlice(s: c.Slice): Router_WithdrawRequest { + fromSlice(s: c.Slice): OffRamps { return { - $: 'Router_WithdrawRequest', - routerWalletAddress: s.loadAddress(), - amount: s.loadCoins(), - tokenPool: s.loadAddress(), - forwardPayload: loadCellRef(s, TokenPool_LockOrBurnForwardPayload.fromSlice), + $: 'OffRamps', + sourceChainSelectors: loadSnakedCellOf(s, (s) => s.loadUintBig(64)), + offRamp: s.loadAddress(), } }, - store(self: Router_WithdrawRequest, b: c.Builder): void { - b.storeAddress(self.routerWalletAddress); - b.storeCoins(self.amount); - b.storeAddress(self.tokenPool); - storeCellRef(self.forwardPayload, b, TokenPool_LockOrBurnForwardPayload.store); + store(self: OffRamps, b: c.Builder): void { + storeSnakedCellOf(self.sourceChainSelectors, b, (v, b) => b.storeUint(v, 64)); + b.storeAddress(self.offRamp); }, - toCell(self: Router_WithdrawRequest): c.Cell { - return makeCellFrom(self, Router_WithdrawRequest.store); + toCell(self: OffRamps): c.Cell { + return makeCellFrom(self, OffRamps.store); } } /** - > struct (0x1e55bbf6) Router_CCIPReceiveConfirm { - > execId: ReceiveExecutorId - > } + > type Router_GetValidatedFee_Any = Router_GetValidatedFee */ -export interface Router_CCIPReceiveConfirm { - readonly $: 'Router_CCIPReceiveConfirm' - execId: ReceiveExecutorId -} - -export const Router_CCIPReceiveConfirm = { - PREFIX: 0x1e55bbf6, +export type Router_GetValidatedFee_Any = Router_GetValidatedFee - create(args: { - execId: ReceiveExecutorId - }): Router_CCIPReceiveConfirm { - return { - $: 'Router_CCIPReceiveConfirm', - ...args - } - }, - fromSlice(s: c.Slice): Router_CCIPReceiveConfirm { - loadAndCheckPrefix32(s, 0x1e55bbf6, 'Router_CCIPReceiveConfirm'); - return { - $: 'Router_CCIPReceiveConfirm', - execId: ReceiveExecutorId.fromSlice(s), - } +export const Router_GetValidatedFee_Any = { + fromSlice(s: c.Slice): Router_GetValidatedFee_Any { + return (() => { + loadAndCheckPrefix32(s, 0x4dd6aa82, 'Router_GetValidatedFee'); + return { + $: 'Router_GetValidatedFee', + ccipSend: loadCellRef(s, Router_CCIPSend.fromSlice), + context: loadTolkRemaining(s), + } + })(); }, - store(self: Router_CCIPReceiveConfirm, b: c.Builder): void { - b.storeUint(0x1e55bbf6, 32); - ReceiveExecutorId.store(self.execId, b); + store(self: Router_GetValidatedFee_Any, b: c.Builder): void { + b.storeUint(0x4dd6aa82, 32); + storeCellRef(self.ccipSend, b, Router_CCIPSend.store); + storeTolkRemaining(self.context, b); }, - toCell(self: Router_CCIPReceiveConfirm): c.Cell { - return makeCellFrom(self, Router_CCIPReceiveConfirm.store); + toCell(self: Router_GetValidatedFee_Any): c.Cell { + return makeCellFrom(self, Router_GetValidatedFee_Any.store); } } /** - > struct (0xf3388046) Router_RMNRemoteCurse { - > queryId: uint64 - > subjects: SnakedCell - > } + > type OnRamp_MessageValidated_GetValidatedFeeContext = OnRamp_MessageValidated */ -export interface Router_RMNRemoteCurse { - readonly $: 'Router_RMNRemoteCurse' - queryId: uint64 - subjects: SnakedCell +export type OnRamp_MessageValidated_GetValidatedFeeContext = OnRamp_MessageValidated + +export const OnRamp_MessageValidated_GetValidatedFeeContext = { + fromSlice(s: c.Slice): OnRamp_MessageValidated_GetValidatedFeeContext { + return (() => { + loadAndCheckPrefix32(s, 0x2afb11bd, 'OnRamp_MessageValidated'); + return { + $: 'OnRamp_MessageValidated', + fee: s.loadCoins(), + msg: loadCellRef(s, Router_CCIPSend.fromSlice), + context: Router_GetValidatedFeeContext.fromSlice(s), + } + })(); + }, + store(self: OnRamp_MessageValidated_GetValidatedFeeContext, b: c.Builder): void { + b.storeUint(0x2afb11bd, 32); + b.storeCoins(self.fee); + storeCellRef(self.msg, b, Router_CCIPSend.store); + Router_GetValidatedFeeContext.store(self.context, b); + }, + toCell(self: OnRamp_MessageValidated_GetValidatedFeeContext): c.Cell { + return makeCellFrom(self, OnRamp_MessageValidated_GetValidatedFeeContext.store); + } } -export const Router_RMNRemoteCurse = { - PREFIX: 0xf3388046, +/** + > type OnRamp_MessageValidationFailed_GetValidatedFeeContext = OnRamp_MessageValidationFailed + */ +export type OnRamp_MessageValidationFailed_GetValidatedFeeContext = OnRamp_MessageValidationFailed - create(args: { - queryId?: uint64 - subjects: SnakedCell - }): Router_RMNRemoteCurse { - return { - $: 'Router_RMNRemoteCurse', - ...args, - queryId: args.queryId ?? 0n - } - }, - fromSlice(s: c.Slice): Router_RMNRemoteCurse { - loadAndCheckPrefix32(s, 0xf3388046, 'Router_RMNRemoteCurse'); - return { - $: 'Router_RMNRemoteCurse', - queryId: s.loadUintBig(64), - subjects: loadSnakedCellOf(s, (s) => s.loadUintBig(128)), - } +export const OnRamp_MessageValidationFailed_GetValidatedFeeContext = { + fromSlice(s: c.Slice): OnRamp_MessageValidationFailed_GetValidatedFeeContext { + return (() => { + loadAndCheckPrefix32(s, 0xac1dd12e, 'OnRamp_MessageValidationFailed'); + return { + $: 'OnRamp_MessageValidationFailed', + error: s.loadUintBig(256), + msg: loadCellRef(s, Router_CCIPSend.fromSlice), + context: Router_GetValidatedFeeContext.fromSlice(s), + } + })(); }, - store(self: Router_RMNRemoteCurse, b: c.Builder): void { - b.storeUint(0xf3388046, 32); - b.storeUint(self.queryId, 64); - storeSnakedCellOf(self.subjects, b, (v, b) => b.storeUint(v, 128)); + store(self: OnRamp_MessageValidationFailed_GetValidatedFeeContext, b: c.Builder): void { + b.storeUint(0xac1dd12e, 32); + b.storeUint(self.error, 256); + storeCellRef(self.msg, b, Router_CCIPSend.store); + Router_GetValidatedFeeContext.store(self.context, b); }, - toCell(self: Router_RMNRemoteCurse): c.Cell { - return makeCellFrom(self, Router_RMNRemoteCurse.store); + toCell(self: OnRamp_MessageValidationFailed_GetValidatedFeeContext): c.Cell { + return makeCellFrom(self, OnRamp_MessageValidationFailed_GetValidatedFeeContext.store); } } /** - > struct (0x3f153a31) Router_RMNRemoteUncurse { + > struct (0x7db6745d) Router_ApplyRampUpdates { > queryId: uint64 - > subjects: SnakedCell + > onRampUpdates: OnRamps? + > offRampAdds: OffRamps? + > offRampRemoves: OffRamps? > } */ -export interface Router_RMNRemoteUncurse { - readonly $: 'Router_RMNRemoteUncurse' +export interface Router_ApplyRampUpdates { + readonly $: 'Router_ApplyRampUpdates' queryId: uint64 - subjects: SnakedCell + onRampUpdates: OnRamps | null /* = null */ + offRampAdds: OffRamps | null /* = null */ + offRampRemoves: OffRamps | null /* = null */ } -export const Router_RMNRemoteUncurse = { - PREFIX: 0x3f153a31, +export const Router_ApplyRampUpdates = { + PREFIX: 0x7db6745d, create(args: { queryId?: uint64 - subjects: SnakedCell - }): Router_RMNRemoteUncurse { + onRampUpdates?: OnRamps | null /* = null */ + offRampAdds?: OffRamps | null /* = null */ + offRampRemoves?: OffRamps | null /* = null */ + }): Router_ApplyRampUpdates { return { - $: 'Router_RMNRemoteUncurse', + $: 'Router_ApplyRampUpdates', + onRampUpdates: null, + offRampAdds: null, + offRampRemoves: null, ...args, queryId: args.queryId ?? 0n } }, - fromSlice(s: c.Slice): Router_RMNRemoteUncurse { - loadAndCheckPrefix32(s, 0x3f153a31, 'Router_RMNRemoteUncurse'); + fromSlice(s: c.Slice): Router_ApplyRampUpdates { + loadAndCheckPrefix32(s, 0x7db6745d, 'Router_ApplyRampUpdates'); return { - $: 'Router_RMNRemoteUncurse', + $: 'Router_ApplyRampUpdates', queryId: s.loadUintBig(64), - subjects: loadSnakedCellOf(s, (s) => s.loadUintBig(128)), + onRampUpdates: s.loadBoolean() ? OnRamps.fromSlice(s) : null, + offRampAdds: s.loadBoolean() ? OffRamps.fromSlice(s) : null, + offRampRemoves: s.loadBoolean() ? OffRamps.fromSlice(s) : null, } }, - store(self: Router_RMNRemoteUncurse, b: c.Builder): void { - b.storeUint(0x3f153a31, 32); + store(self: Router_ApplyRampUpdates, b: c.Builder): void { + b.storeUint(0x7db6745d, 32); b.storeUint(self.queryId, 64); - storeSnakedCellOf(self.subjects, b, (v, b) => b.storeUint(v, 128)); + storeTolkNullable(self.onRampUpdates, b, OnRamps.store); + storeTolkNullable(self.offRampAdds, b, OffRamps.store); + storeTolkNullable(self.offRampRemoves, b, OffRamps.store); }, - toCell(self: Router_RMNRemoteUncurse): c.Cell { - return makeCellFrom(self, Router_RMNRemoteUncurse.store); + toCell(self: Router_ApplyRampUpdates): c.Cell { + return makeCellFrom(self, Router_ApplyRampUpdates.store); } } /** - > struct (0x0b95aa4e) Router_RMNRemoteVerifyNotCursed { - > queryId: uint64 - > subject: uint128 + > struct (0x31768d95) Router_CCIPSend { + > queryID: uint64 + > destChainSelector: uint64 + > receiver: CrossChainAddress + > data: cell + > tokenAmounts: SnakedCell + > feeToken: address? + > extraArgs: Cell > } */ -export interface Router_RMNRemoteVerifyNotCursed { - readonly $: 'Router_RMNRemoteVerifyNotCursed' - queryId: uint64 - subject: uint128 +export interface Router_CCIPSend { + readonly $: 'Router_CCIPSend' + queryID: uint64 + destChainSelector: uint64 + receiver: CrossChainAddress + data: c.Cell + tokenAmounts: SnakedCell + feeToken: c.Address | null + extraArgs: ExtraArgs } -export const Router_RMNRemoteVerifyNotCursed = { - PREFIX: 0x0b95aa4e, +export const Router_CCIPSend = { + PREFIX: 0x31768d95, create(args: { - queryId?: uint64 - subject: uint128 - }): Router_RMNRemoteVerifyNotCursed { + queryID?: uint64 + destChainSelector: uint64 + receiver: CrossChainAddress + data: c.Cell + tokenAmounts: SnakedCell + feeToken: c.Address | null + extraArgs: ExtraArgs + }): Router_CCIPSend { return { - $: 'Router_RMNRemoteVerifyNotCursed', + $: 'Router_CCIPSend', ...args, - queryId: args.queryId ?? 0n + queryID: args.queryID ?? 0n } }, - fromSlice(s: c.Slice): Router_RMNRemoteVerifyNotCursed { - loadAndCheckPrefix32(s, 0x0b95aa4e, 'Router_RMNRemoteVerifyNotCursed'); + fromSlice(s: c.Slice): Router_CCIPSend { + loadAndCheckPrefix32(s, 0x31768d95, 'Router_CCIPSend'); return { - $: 'Router_RMNRemoteVerifyNotCursed', - queryId: s.loadUintBig(64), - subject: s.loadUintBig(128), + $: 'Router_CCIPSend', + queryID: s.loadUintBig(64), + destChainSelector: s.loadUintBig(64), + receiver: CrossChainAddress.fromSlice(s), + data: s.loadRef(), + tokenAmounts: loadSnakedCellOf(s, TokenAmount.fromSlice), + feeToken: s.loadMaybeAddress(), + extraArgs: loadCellRef(s, ExtraArgs.fromSlice), } }, - store(self: Router_RMNRemoteVerifyNotCursed, b: c.Builder): void { - b.storeUint(0x0b95aa4e, 32); - b.storeUint(self.queryId, 64); - b.storeUint(self.subject, 128); + store(self: Router_CCIPSend, b: c.Builder): void { + b.storeUint(0x31768d95, 32); + b.storeUint(self.queryID, 64); + b.storeUint(self.destChainSelector, 64); + CrossChainAddress.store(self.receiver, b); + b.storeRef(self.data); + storeSnakedCellOf(self.tokenAmounts, b, TokenAmount.store); + b.storeAddress(self.feeToken); + storeCellRef(self.extraArgs, b, ExtraArgs.store); }, - toCell(self: Router_RMNRemoteVerifyNotCursed): c.Cell { - return makeCellFrom(self, Router_RMNRemoteVerifyNotCursed.store); + toCell(self: Router_CCIPSend): c.Cell { + return makeCellFrom(self, Router_CCIPSend.store); } } /** - > struct (0x22ba83b3) Router_RMNRemoteVerifyNotCursedResponse { - > queryId: uint64 - > result: bool + > struct (0xfc69c50b) Router_RouteMessage { + > message: Cell + > execId: ReceiveExecutorId + > receiver: address + > gasLimit: coins > } */ -export interface Router_RMNRemoteVerifyNotCursedResponse { - readonly $: 'Router_RMNRemoteVerifyNotCursedResponse' - queryId: uint64 - result: boolean +export interface Router_RouteMessage { + readonly $: 'Router_RouteMessage' + message: Any2TVMMessage + execId: ReceiveExecutorId + receiver: c.Address + gasLimit: coins } -export const Router_RMNRemoteVerifyNotCursedResponse = { - PREFIX: 0x22ba83b3, +export const Router_RouteMessage = { + PREFIX: 0xfc69c50b, create(args: { - queryId?: uint64 - result: boolean - }): Router_RMNRemoteVerifyNotCursedResponse { + message: Any2TVMMessage + execId: ReceiveExecutorId + receiver: c.Address + gasLimit: coins + }): Router_RouteMessage { return { - $: 'Router_RMNRemoteVerifyNotCursedResponse', - ...args, - queryId: args.queryId ?? 0n + $: 'Router_RouteMessage', + ...args } }, - fromSlice(s: c.Slice): Router_RMNRemoteVerifyNotCursedResponse { - loadAndCheckPrefix32(s, 0x22ba83b3, 'Router_RMNRemoteVerifyNotCursedResponse'); + fromSlice(s: c.Slice): Router_RouteMessage { + loadAndCheckPrefix32(s, 0xfc69c50b, 'Router_RouteMessage'); return { - $: 'Router_RMNRemoteVerifyNotCursedResponse', - queryId: s.loadUintBig(64), - result: s.loadBoolean(), + $: 'Router_RouteMessage', + message: loadCellRef(s, Any2TVMMessage.fromSlice), + execId: ReceiveExecutorId.fromSlice(s), + receiver: s.loadAddress(), + gasLimit: s.loadCoins(), } }, - store(self: Router_RMNRemoteVerifyNotCursedResponse, b: c.Builder): void { - b.storeUint(0x22ba83b3, 32); - b.storeUint(self.queryId, 64); - b.storeBit(self.result); + store(self: Router_RouteMessage, b: c.Builder): void { + b.storeUint(0xfc69c50b, 32); + storeCellRef(self.message, b, Any2TVMMessage.store); + ReceiveExecutorId.store(self.execId, b); + b.storeAddress(self.receiver); + b.storeCoins(self.gasLimit); }, - toCell(self: Router_RMNRemoteVerifyNotCursedResponse): c.Cell { - return makeCellFrom(self, Router_RMNRemoteVerifyNotCursedResponse.store); + toCell(self: Router_RouteMessage): c.Cell { + return makeCellFrom(self, Router_RouteMessage.store); } } /** - > struct (0x6513f8e1) Router_MessageSent { + > struct (0x19f0098f) Router_WithdrawToTokenPool { > queryID: uint64 - > messageId: uint256 > destChainSelector: uint64 - > sender: address + > withdrawRequest: Cell > } */ -export interface Router_MessageSent { - readonly $: 'Router_MessageSent' +export interface Router_WithdrawToTokenPool { + readonly $: 'Router_WithdrawToTokenPool' queryID: uint64 - messageId: uint256 destChainSelector: uint64 - sender: c.Address + withdrawRequest: Router_WithdrawRequest } -export const Router_MessageSent = { - PREFIX: 0x6513f8e1, +export const Router_WithdrawToTokenPool = { + PREFIX: 0x19f0098f, create(args: { queryID?: uint64 - messageId: uint256 destChainSelector: uint64 - sender: c.Address - }): Router_MessageSent { + withdrawRequest: Router_WithdrawRequest + }): Router_WithdrawToTokenPool { return { - $: 'Router_MessageSent', + $: 'Router_WithdrawToTokenPool', ...args, queryID: args.queryID ?? 0n } }, - fromSlice(s: c.Slice): Router_MessageSent { - loadAndCheckPrefix32(s, 0x6513f8e1, 'Router_MessageSent'); + fromSlice(s: c.Slice): Router_WithdrawToTokenPool { + loadAndCheckPrefix32(s, 0x19f0098f, 'Router_WithdrawToTokenPool'); return { - $: 'Router_MessageSent', + $: 'Router_WithdrawToTokenPool', queryID: s.loadUintBig(64), - messageId: s.loadUintBig(256), destChainSelector: s.loadUintBig(64), - sender: s.loadAddress(), + withdrawRequest: loadCellRef(s, Router_WithdrawRequest.fromSlice), } }, - store(self: Router_MessageSent, b: c.Builder): void { - b.storeUint(0x6513f8e1, 32); + store(self: Router_WithdrawToTokenPool, b: c.Builder): void { + b.storeUint(0x19f0098f, 32); b.storeUint(self.queryID, 64); - b.storeUint(self.messageId, 256); b.storeUint(self.destChainSelector, 64); - b.storeAddress(self.sender); + storeCellRef(self.withdrawRequest, b, Router_WithdrawRequest.store); }, - toCell(self: Router_MessageSent): c.Cell { - return makeCellFrom(self, Router_MessageSent.store); + toCell(self: Router_WithdrawToTokenPool): c.Cell { + return makeCellFrom(self, Router_WithdrawToTokenPool.store); } } /** - > struct (0x8ae25114) Router_MessageRejected { - > queryID: uint64 - > destChainSelector: uint64 - > sender: address - > error: uint256 + > struct Router_WithdrawRequest { + > routerWalletAddress: address + > amount: coins + > tokenPool: address + > forwardPayload: Cell > } */ -export interface Router_MessageRejected { - readonly $: 'Router_MessageRejected' - queryID: uint64 - destChainSelector: uint64 - sender: c.Address - error: uint256 +export interface Router_WithdrawRequest { + readonly $: 'Router_WithdrawRequest' + routerWalletAddress: c.Address + amount: coins + tokenPool: c.Address + forwardPayload: TokenPool_LockOrBurnForwardPayload } -export const Router_MessageRejected = { - PREFIX: 0x8ae25114, - +export const Router_WithdrawRequest = { create(args: { - queryID?: uint64 - destChainSelector: uint64 - sender: c.Address - error: uint256 - }): Router_MessageRejected { + routerWalletAddress: c.Address + amount: coins + tokenPool: c.Address + forwardPayload: TokenPool_LockOrBurnForwardPayload + }): Router_WithdrawRequest { return { - $: 'Router_MessageRejected', - ...args, - queryID: args.queryID ?? 0n + $: 'Router_WithdrawRequest', + ...args } }, - fromSlice(s: c.Slice): Router_MessageRejected { - loadAndCheckPrefix32(s, 0x8ae25114, 'Router_MessageRejected'); + fromSlice(s: c.Slice): Router_WithdrawRequest { return { - $: 'Router_MessageRejected', - queryID: s.loadUintBig(64), - destChainSelector: s.loadUintBig(64), - sender: s.loadAddress(), - error: s.loadUintBig(256), + $: 'Router_WithdrawRequest', + routerWalletAddress: s.loadAddress(), + amount: s.loadCoins(), + tokenPool: s.loadAddress(), + forwardPayload: loadCellRef(s, TokenPool_LockOrBurnForwardPayload.fromSlice), } }, - store(self: Router_MessageRejected, b: c.Builder): void { - b.storeUint(0x8ae25114, 32); - b.storeUint(self.queryID, 64); - b.storeUint(self.destChainSelector, 64); - b.storeAddress(self.sender); - b.storeUint(self.error, 256); + store(self: Router_WithdrawRequest, b: c.Builder): void { + b.storeAddress(self.routerWalletAddress); + b.storeCoins(self.amount); + b.storeAddress(self.tokenPool); + storeCellRef(self.forwardPayload, b, TokenPool_LockOrBurnForwardPayload.store); }, - toCell(self: Router_MessageRejected): c.Cell { - return makeCellFrom(self, Router_MessageRejected.store); + toCell(self: Router_WithdrawRequest): c.Cell { + return makeCellFrom(self, Router_WithdrawRequest.store); } } /** - > struct (0xaf7a9ac6) Router_RMNOwnableMessage { - > content: RemainingBitsAndRefs + > struct (0x1e55bbf6) Router_CCIPReceiveConfirm { + > execId: ReceiveExecutorId > } */ -export interface Router_RMNOwnableMessage { - readonly $: 'Router_RMNOwnableMessage' - content: RemainingBitsAndRefs +export interface Router_CCIPReceiveConfirm { + readonly $: 'Router_CCIPReceiveConfirm' + execId: ReceiveExecutorId } -export const Router_RMNOwnableMessage = { - PREFIX: 0xaf7a9ac6, +export const Router_CCIPReceiveConfirm = { + PREFIX: 0x1e55bbf6, create(args: { - content: RemainingBitsAndRefs - }): Router_RMNOwnableMessage { + execId: ReceiveExecutorId + }): Router_CCIPReceiveConfirm { return { - $: 'Router_RMNOwnableMessage', + $: 'Router_CCIPReceiveConfirm', ...args } }, - fromSlice(s: c.Slice): Router_RMNOwnableMessage { - loadAndCheckPrefix32(s, 0xaf7a9ac6, 'Router_RMNOwnableMessage'); + fromSlice(s: c.Slice): Router_CCIPReceiveConfirm { + loadAndCheckPrefix32(s, 0x1e55bbf6, 'Router_CCIPReceiveConfirm'); return { - $: 'Router_RMNOwnableMessage', - content: loadTolkRemaining(s), + $: 'Router_CCIPReceiveConfirm', + execId: ReceiveExecutorId.fromSlice(s), } }, - store(self: Router_RMNOwnableMessage, b: c.Builder): void { - b.storeUint(0xaf7a9ac6, 32); - storeTolkRemaining(self.content, b); + store(self: Router_CCIPReceiveConfirm, b: c.Builder): void { + b.storeUint(0x1e55bbf6, 32); + ReceiveExecutorId.store(self.execId, b); }, - toCell(self: Router_RMNOwnableMessage): c.Cell { - return makeCellFrom(self, Router_RMNOwnableMessage.store); + toCell(self: Router_CCIPReceiveConfirm): c.Cell { + return makeCellFrom(self, Router_CCIPReceiveConfirm.store); } } /** - > struct (0x78d0f21e) Router_CCIPSendACK { - > queryID: uint64 - > messageId: uint256 + > struct (0xf3388046) Router_RMNRemoteCurse { + > queryId: uint64 + > subjects: SnakedCell > } */ -export interface Router_CCIPSendACK { - readonly $: 'Router_CCIPSendACK' - queryID: uint64 - messageId: uint256 +export interface Router_RMNRemoteCurse { + readonly $: 'Router_RMNRemoteCurse' + queryId: uint64 + subjects: SnakedCell } -export const Router_CCIPSendACK = { - PREFIX: 0x78d0f21e, +export const Router_RMNRemoteCurse = { + PREFIX: 0xf3388046, create(args: { - queryID?: uint64 - messageId: uint256 - }): Router_CCIPSendACK { + queryId?: uint64 + subjects: SnakedCell + }): Router_RMNRemoteCurse { return { - $: 'Router_CCIPSendACK', + $: 'Router_RMNRemoteCurse', ...args, - queryID: args.queryID ?? 0n + queryId: args.queryId ?? 0n } }, - fromSlice(s: c.Slice): Router_CCIPSendACK { - loadAndCheckPrefix32(s, 0x78d0f21e, 'Router_CCIPSendACK'); + fromSlice(s: c.Slice): Router_RMNRemoteCurse { + loadAndCheckPrefix32(s, 0xf3388046, 'Router_RMNRemoteCurse'); return { - $: 'Router_CCIPSendACK', - queryID: s.loadUintBig(64), - messageId: s.loadUintBig(256), + $: 'Router_RMNRemoteCurse', + queryId: s.loadUintBig(64), + subjects: loadSnakedCellOf(s, (s) => s.loadUintBig(128)), } }, - store(self: Router_CCIPSendACK, b: c.Builder): void { - b.storeUint(0x78d0f21e, 32); - b.storeUint(self.queryID, 64); - b.storeUint(self.messageId, 256); + store(self: Router_RMNRemoteCurse, b: c.Builder): void { + b.storeUint(0xf3388046, 32); + b.storeUint(self.queryId, 64); + storeSnakedCellOf(self.subjects, b, (v, b) => b.storeUint(v, 128)); }, - toCell(self: Router_CCIPSendACK): c.Cell { - return makeCellFrom(self, Router_CCIPSendACK.store); + toCell(self: Router_RMNRemoteCurse): c.Cell { + return makeCellFrom(self, Router_RMNRemoteCurse.store); } } /** - > struct (0x5a45d434) Router_CCIPSendNACK { - > queryID: uint64 - > error: uint256 + > struct (0x3f153a31) Router_RMNRemoteUncurse { + > queryId: uint64 + > subjects: SnakedCell > } */ -export interface Router_CCIPSendNACK { - readonly $: 'Router_CCIPSendNACK' - queryID: uint64 - error: uint256 +export interface Router_RMNRemoteUncurse { + readonly $: 'Router_RMNRemoteUncurse' + queryId: uint64 + subjects: SnakedCell } -export const Router_CCIPSendNACK = { - PREFIX: 0x5a45d434, +export const Router_RMNRemoteUncurse = { + PREFIX: 0x3f153a31, create(args: { - queryID?: uint64 - error: uint256 - }): Router_CCIPSendNACK { + queryId?: uint64 + subjects: SnakedCell + }): Router_RMNRemoteUncurse { return { - $: 'Router_CCIPSendNACK', + $: 'Router_RMNRemoteUncurse', ...args, - queryID: args.queryID ?? 0n + queryId: args.queryId ?? 0n } }, - fromSlice(s: c.Slice): Router_CCIPSendNACK { - loadAndCheckPrefix32(s, 0x5a45d434, 'Router_CCIPSendNACK'); + fromSlice(s: c.Slice): Router_RMNRemoteUncurse { + loadAndCheckPrefix32(s, 0x3f153a31, 'Router_RMNRemoteUncurse'); return { - $: 'Router_CCIPSendNACK', - queryID: s.loadUintBig(64), - error: s.loadUintBig(256), + $: 'Router_RMNRemoteUncurse', + queryId: s.loadUintBig(64), + subjects: loadSnakedCellOf(s, (s) => s.loadUintBig(128)), } }, - store(self: Router_CCIPSendNACK, b: c.Builder): void { - b.storeUint(0x5a45d434, 32); - b.storeUint(self.queryID, 64); - b.storeUint(self.error, 256); + store(self: Router_RMNRemoteUncurse, b: c.Builder): void { + b.storeUint(0x3f153a31, 32); + b.storeUint(self.queryId, 64); + storeSnakedCellOf(self.subjects, b, (v, b) => b.storeUint(v, 128)); }, - toCell(self: Router_CCIPSendNACK): c.Cell { - return makeCellFrom(self, Router_CCIPSendNACK.store); + toCell(self: Router_RMNRemoteUncurse): c.Cell { + return makeCellFrom(self, Router_RMNRemoteUncurse.store); } } /** - > struct (0x4dd6aa82) Router_GetValidatedFee { - > ccipSend: Cell - > context: T + > struct (0x0b95aa4e) Router_RMNRemoteVerifyNotCursed { + > queryId: uint64 + > subject: uint128 > } */ -export interface Router_GetValidatedFee { - readonly $: 'Router_GetValidatedFee' - ccipSend: Router_CCIPSend - context: T +export interface Router_RMNRemoteVerifyNotCursed { + readonly $: 'Router_RMNRemoteVerifyNotCursed' + queryId: uint64 + subject: uint128 } -export const Router_GetValidatedFee = { - PREFIX: 0x4dd6aa82, +export const Router_RMNRemoteVerifyNotCursed = { + PREFIX: 0x0b95aa4e, - create(args: { - ccipSend: Router_CCIPSend - context: T - }): Router_GetValidatedFee { + create(args: { + queryId?: uint64 + subject: uint128 + }): Router_RMNRemoteVerifyNotCursed { return { - $: 'Router_GetValidatedFee', - ...args + $: 'Router_RMNRemoteVerifyNotCursed', + ...args, + queryId: args.queryId ?? 0n + } + }, + fromSlice(s: c.Slice): Router_RMNRemoteVerifyNotCursed { + loadAndCheckPrefix32(s, 0x0b95aa4e, 'Router_RMNRemoteVerifyNotCursed'); + return { + $: 'Router_RMNRemoteVerifyNotCursed', + queryId: s.loadUintBig(64), + subject: s.loadUintBig(128), } }, + store(self: Router_RMNRemoteVerifyNotCursed, b: c.Builder): void { + b.storeUint(0x0b95aa4e, 32); + b.storeUint(self.queryId, 64); + b.storeUint(self.subject, 128); + }, + toCell(self: Router_RMNRemoteVerifyNotCursed): c.Cell { + return makeCellFrom(self, Router_RMNRemoteVerifyNotCursed.store); + } } /** - > struct (0x6f2d00df) Router_LockOrBurn { + > struct (0x22ba83b3) Router_RMNRemoteVerifyNotCursedResponse { + > queryId: uint64 + > result: bool + > } + */ +export interface Router_RMNRemoteVerifyNotCursedResponse { + readonly $: 'Router_RMNRemoteVerifyNotCursedResponse' + queryId: uint64 + result: boolean +} + +export const Router_RMNRemoteVerifyNotCursedResponse = { + PREFIX: 0x22ba83b3, + + create(args: { + queryId?: uint64 + result: boolean + }): Router_RMNRemoteVerifyNotCursedResponse { + return { + $: 'Router_RMNRemoteVerifyNotCursedResponse', + ...args, + queryId: args.queryId ?? 0n + } + }, + fromSlice(s: c.Slice): Router_RMNRemoteVerifyNotCursedResponse { + loadAndCheckPrefix32(s, 0x22ba83b3, 'Router_RMNRemoteVerifyNotCursedResponse'); + return { + $: 'Router_RMNRemoteVerifyNotCursedResponse', + queryId: s.loadUintBig(64), + result: s.loadBoolean(), + } + }, + store(self: Router_RMNRemoteVerifyNotCursedResponse, b: c.Builder): void { + b.storeUint(0x22ba83b3, 32); + b.storeUint(self.queryId, 64); + b.storeBit(self.result); + }, + toCell(self: Router_RMNRemoteVerifyNotCursedResponse): c.Cell { + return makeCellFrom(self, Router_RMNRemoteVerifyNotCursedResponse.store); + } +} + +/** + > struct (0x6513f8e1) Router_MessageSent { > queryID: uint64 - > tokenPool: address - > request: Cell - > executorAddress: address + > messageId: uint256 + > destChainSelector: uint64 + > sender: address > } */ -export interface Router_LockOrBurn { - readonly $: 'Router_LockOrBurn' +export interface Router_MessageSent { + readonly $: 'Router_MessageSent' queryID: uint64 - tokenPool: c.Address - request: TokenPool_LockOrBurnInV1 - executorAddress: c.Address + messageId: uint256 + destChainSelector: uint64 + sender: c.Address } -export const Router_LockOrBurn = { - PREFIX: 0x6f2d00df, +export const Router_MessageSent = { + PREFIX: 0x6513f8e1, create(args: { queryID?: uint64 - tokenPool: c.Address - request: TokenPool_LockOrBurnInV1 - executorAddress: c.Address - }): Router_LockOrBurn { + messageId: uint256 + destChainSelector: uint64 + sender: c.Address + }): Router_MessageSent { return { - $: 'Router_LockOrBurn', + $: 'Router_MessageSent', ...args, queryID: args.queryID ?? 0n } }, - fromSlice(s: c.Slice): Router_LockOrBurn { - loadAndCheckPrefix32(s, 0x6f2d00df, 'Router_LockOrBurn'); + fromSlice(s: c.Slice): Router_MessageSent { + loadAndCheckPrefix32(s, 0x6513f8e1, 'Router_MessageSent'); return { - $: 'Router_LockOrBurn', + $: 'Router_MessageSent', queryID: s.loadUintBig(64), - tokenPool: s.loadAddress(), - request: loadCellRef(s, TokenPool_LockOrBurnInV1.fromSlice), - executorAddress: s.loadAddress(), + messageId: s.loadUintBig(256), + destChainSelector: s.loadUintBig(64), + sender: s.loadAddress(), } }, - store(self: Router_LockOrBurn, b: c.Builder): void { - b.storeUint(0x6f2d00df, 32); + store(self: Router_MessageSent, b: c.Builder): void { + b.storeUint(0x6513f8e1, 32); b.storeUint(self.queryID, 64); - b.storeAddress(self.tokenPool); - storeCellRef(self.request, b, TokenPool_LockOrBurnInV1.store); - b.storeAddress(self.executorAddress); + b.storeUint(self.messageId, 256); + b.storeUint(self.destChainSelector, 64); + b.storeAddress(self.sender); }, - toCell(self: Router_LockOrBurn): c.Cell { - return makeCellFrom(self, Router_LockOrBurn.store); + toCell(self: Router_MessageSent): c.Cell { + return makeCellFrom(self, Router_MessageSent.store); } } /** - > struct Router_GetValidatedFeeContext { - > routerContext: address - > userContext: RemainingBitsOrRef + > struct (0x8ae25114) Router_MessageRejected { + > queryID: uint64 + > destChainSelector: uint64 + > sender: address + > error: uint256 > } */ -export interface Router_GetValidatedFeeContext { - readonly $: 'Router_GetValidatedFeeContext' - routerContext: c.Address - userContext: RemainingBitsOrRef +export interface Router_MessageRejected { + readonly $: 'Router_MessageRejected' + queryID: uint64 + destChainSelector: uint64 + sender: c.Address + error: uint256 } -export const Router_GetValidatedFeeContext = { +export const Router_MessageRejected = { + PREFIX: 0x8ae25114, + create(args: { - routerContext: c.Address - userContext: RemainingBitsOrRef - }): Router_GetValidatedFeeContext { + queryID?: uint64 + destChainSelector: uint64 + sender: c.Address + error: uint256 + }): Router_MessageRejected { return { - $: 'Router_GetValidatedFeeContext', - ...args + $: 'Router_MessageRejected', + ...args, + queryID: args.queryID ?? 0n } }, - fromSlice(s: c.Slice): Router_GetValidatedFeeContext { + fromSlice(s: c.Slice): Router_MessageRejected { + loadAndCheckPrefix32(s, 0x8ae25114, 'Router_MessageRejected'); return { - $: 'Router_GetValidatedFeeContext', - routerContext: s.loadAddress(), - userContext: loadTolkRemaining(s), + $: 'Router_MessageRejected', + queryID: s.loadUintBig(64), + destChainSelector: s.loadUintBig(64), + sender: s.loadAddress(), + error: s.loadUintBig(256), } }, - store(self: Router_GetValidatedFeeContext, b: c.Builder): void { - b.storeAddress(self.routerContext); - storeTolkRemaining(self.userContext, b); + store(self: Router_MessageRejected, b: c.Builder): void { + b.storeUint(0x8ae25114, 32); + b.storeUint(self.queryID, 64); + b.storeUint(self.destChainSelector, 64); + b.storeAddress(self.sender); + b.storeUint(self.error, 256); }, - toCell(self: Router_GetValidatedFeeContext): c.Cell { - return makeCellFrom(self, Router_GetValidatedFeeContext.store); + toCell(self: Router_MessageRejected): c.Cell { + return makeCellFrom(self, Router_MessageRejected.store); } } /** - > type Router_MessageValidated_Any = Router_MessageValidated + > struct (0xaf7a9ac6) Router_RMNOwnableMessage { + > content: RemainingBitsAndRefs + > } */ -export type Router_MessageValidated_Any = Router_MessageValidated +export interface Router_RMNOwnableMessage { + readonly $: 'Router_RMNOwnableMessage' + content: RemainingBitsAndRefs +} -export const Router_MessageValidated_Any = { - fromSlice(s: c.Slice): Router_MessageValidated_Any { - return (() => { - loadAndCheckPrefix32(s, 0x9e2155ec, 'Router_MessageValidated'); - return { - $: 'Router_MessageValidated', - fee: s.loadCoins(), - msg: loadCellRef(s, Router_CCIPSend.fromSlice), - context: loadTolkRemaining(s), - } - })(); - }, - store(self: Router_MessageValidated_Any, b: c.Builder): void { - b.storeUint(0x9e2155ec, 32); - b.storeCoins(self.fee); - storeCellRef(self.msg, b, Router_CCIPSend.store); - storeTolkRemaining(self.context, b); - }, - toCell(self: Router_MessageValidated_Any): c.Cell { - return makeCellFrom(self, Router_MessageValidated_Any.store); - } -} - -/** - > struct (0x9e2155ec) Router_MessageValidated { - > fee: coins - > msg: Cell - > context: RemainingBitsOrRef - > } - */ -export interface Router_MessageValidated { - readonly $: 'Router_MessageValidated' - fee: coins - msg: Router_CCIPSend - context: RemainingBitsOrRef -} - -export const Router_MessageValidated = { - PREFIX: 0x9e2155ec, - - create(args: { - fee: coins - msg: Router_CCIPSend - context: RemainingBitsOrRef - }): Router_MessageValidated { - return { - $: 'Router_MessageValidated', - ...args - } - }, -} - -/** - > type Router_MessageValidationFailed_Any = Router_MessageValidationFailed - */ -export type Router_MessageValidationFailed_Any = Router_MessageValidationFailed - -export const Router_MessageValidationFailed_Any = { - fromSlice(s: c.Slice): Router_MessageValidationFailed_Any { - return (() => { - loadAndCheckPrefix32(s, 0xec23c562, 'Router_MessageValidationFailed'); - return { - $: 'Router_MessageValidationFailed', - error: s.loadUintBig(256), - msg: loadCellRef(s, Router_CCIPSend.fromSlice), - context: loadTolkRemaining(s), - } - })(); - }, - store(self: Router_MessageValidationFailed_Any, b: c.Builder): void { - b.storeUint(0xec23c562, 32); - b.storeUint(self.error, 256); - storeCellRef(self.msg, b, Router_CCIPSend.store); - storeTolkRemaining(self.context, b); - }, - toCell(self: Router_MessageValidationFailed_Any): c.Cell { - return makeCellFrom(self, Router_MessageValidationFailed_Any.store); - } -} - -/** - > struct (0xec23c562) Router_MessageValidationFailed { - > error: uint256 - > msg: Cell - > context: RemainingBitsOrRef - > } - */ -export interface Router_MessageValidationFailed { - readonly $: 'Router_MessageValidationFailed' - error: uint256 - msg: Router_CCIPSend - context: RemainingBitsOrRef -} - -export const Router_MessageValidationFailed = { - PREFIX: 0xec23c562, - - create(args: { - error: uint256 - msg: Router_CCIPSend - context: RemainingBitsOrRef - }): Router_MessageValidationFailed { - return { - $: 'Router_MessageValidationFailed', - ...args - } - }, -} - -/** - > struct RMNRemote { - > admin: Ownable2Step - > cursedSubjects: CursedSubjects - > forwardUpdates: map - > } - */ -export interface RMNRemote { - readonly $: 'RMNRemote' - admin: Ownable2Step - cursedSubjects: CursedSubjects - forwardUpdates: Set /* = [] as map */ -} +export const Router_RMNOwnableMessage = { + PREFIX: 0xaf7a9ac6, -export const RMNRemote = { create(args: { - admin: Ownable2Step - cursedSubjects: CursedSubjects - forwardUpdates: Set /* = [] as map */ - }): RMNRemote { + content: RemainingBitsAndRefs + }): Router_RMNOwnableMessage { return { - $: 'RMNRemote', + $: 'Router_RMNOwnableMessage', ...args } }, - fromSlice(s: c.Slice): RMNRemote { + fromSlice(s: c.Slice): Router_RMNOwnableMessage { + loadAndCheckPrefix32(s, 0xaf7a9ac6, 'Router_RMNOwnableMessage'); return { - $: 'RMNRemote', - admin: Ownable2Step.fromSlice(s), - cursedSubjects: CursedSubjects.fromSlice(s), - forwardUpdates: dictToSet(c.Dictionary.load(c.Dictionary.Keys.Address(), createDictionaryValue<[]>( - (s) => [], - (v,b) => { {} } - ), s)), + $: 'Router_RMNOwnableMessage', + content: loadTolkRemaining(s), } }, - store(self: RMNRemote, b: c.Builder): void { - Ownable2Step.store(self.admin, b); - CursedSubjects.store(self.cursedSubjects, b); - b.storeDict(setToDict(self.forwardUpdates, c.Dictionary.Keys.Address(), createDictionaryValue<[]>( - (s) => [], - (v,b) => { {} } - )), c.Dictionary.Keys.Address(), createDictionaryValue<[]>( - (s) => [], - (v,b) => { {} } - )); + store(self: Router_RMNOwnableMessage, b: c.Builder): void { + b.storeUint(0xaf7a9ac6, 32); + storeTolkRemaining(self.content, b); }, - toCell(self: RMNRemote): c.Cell { - return makeCellFrom(self, RMNRemote.store); + toCell(self: Router_RMNOwnableMessage): c.Cell { + return makeCellFrom(self, Router_RMNOwnableMessage.store); } } /** - > struct Storage { - > id: uint32 - > ownable: Ownable2Step - > wrappedNative: address - > onRamps: map - > offRamps: map - > rmnRemote: Cell + > struct (0x78d0f21e) Router_CCIPSendACK { + > queryID: uint64 + > messageId: uint256 > } */ -export interface Storage { - readonly $: 'Storage' - id: uint32 - ownable: Ownable2Step - wrappedNative: c.Address - onRamps: Map /* = [] as map */ - offRamps: Map /* = [] as map */ - rmnRemote: RMNRemote +export interface Router_CCIPSendACK { + readonly $: 'Router_CCIPSendACK' + queryID: uint64 + messageId: uint256 } -export const Storage = { +export const Router_CCIPSendACK = { + PREFIX: 0x78d0f21e, + create(args: { - id: uint32 - ownable: Ownable2Step - wrappedNative: c.Address - onRamps: Map /* = [] as map */ - offRamps: Map /* = [] as map */ - rmnRemote: RMNRemote - }): Storage { + queryID?: uint64 + messageId: uint256 + }): Router_CCIPSendACK { return { - $: 'Storage', - ...args + $: 'Router_CCIPSendACK', + ...args, + queryID: args.queryID ?? 0n } }, - fromSlice(s: c.Slice): Storage { + fromSlice(s: c.Slice): Router_CCIPSendACK { + loadAndCheckPrefix32(s, 0x78d0f21e, 'Router_CCIPSendACK'); return { - $: 'Storage', - id: s.loadUintBig(32), - ownable: Ownable2Step.fromSlice(s), - wrappedNative: s.loadAddress(), - onRamps: dictToMap(c.Dictionary.load(c.Dictionary.Keys.BigUint(64), createDictionaryValue( - (s) => s.loadAddress(), - (v,b) => b.storeAddress(v) - ), s)), - offRamps: dictToMap(c.Dictionary.load(c.Dictionary.Keys.BigUint(64), createDictionaryValue( - (s) => s.loadAddress(), - (v,b) => b.storeAddress(v) - ), s)), - rmnRemote: loadCellRef(s, RMNRemote.fromSlice), + $: 'Router_CCIPSendACK', + queryID: s.loadUintBig(64), + messageId: s.loadUintBig(256), } }, - store(self: Storage, b: c.Builder): void { - b.storeUint(self.id, 32); - Ownable2Step.store(self.ownable, b); - b.storeAddress(self.wrappedNative); - b.storeDict(mapToDict(self.onRamps, c.Dictionary.Keys.BigUint(64), createDictionaryValue( - (s) => s.loadAddress(), - (v,b) => b.storeAddress(v) - )), c.Dictionary.Keys.BigUint(64), createDictionaryValue( - (s) => s.loadAddress(), - (v,b) => b.storeAddress(v) - )); - b.storeDict(mapToDict(self.offRamps, c.Dictionary.Keys.BigUint(64), createDictionaryValue( - (s) => s.loadAddress(), - (v,b) => b.storeAddress(v) - )), c.Dictionary.Keys.BigUint(64), createDictionaryValue( - (s) => s.loadAddress(), - (v,b) => b.storeAddress(v) - )); - storeCellRef(self.rmnRemote, b, RMNRemote.store); + store(self: Router_CCIPSendACK, b: c.Builder): void { + b.storeUint(0x78d0f21e, 32); + b.storeUint(self.queryID, 64); + b.storeUint(self.messageId, 256); }, - toCell(self: Storage): c.Cell { - return makeCellFrom(self, Storage.store); + toCell(self: Router_CCIPSendACK): c.Cell { + return makeCellFrom(self, Router_CCIPSendACK.store); } } /** - > struct OnRampSet { - > destChainSelectors: SnakedCell - > onRamp: address? + > struct (0x5a45d434) Router_CCIPSendNACK { + > queryID: uint64 + > error: uint256 > } */ -export interface OnRampSet { - readonly $: 'OnRampSet' - destChainSelectors: SnakedCell - onRamp: c.Address | null +export interface Router_CCIPSendNACK { + readonly $: 'Router_CCIPSendNACK' + queryID: uint64 + error: uint256 } -export const OnRampSet = { +export const Router_CCIPSendNACK = { + PREFIX: 0x5a45d434, + create(args: { - destChainSelectors: SnakedCell - onRamp: c.Address | null - }): OnRampSet { + queryID?: uint64 + error: uint256 + }): Router_CCIPSendNACK { return { - $: 'OnRampSet', - ...args + $: 'Router_CCIPSendNACK', + ...args, + queryID: args.queryID ?? 0n } }, - fromSlice(s: c.Slice): OnRampSet { + fromSlice(s: c.Slice): Router_CCIPSendNACK { + loadAndCheckPrefix32(s, 0x5a45d434, 'Router_CCIPSendNACK'); return { - $: 'OnRampSet', - destChainSelectors: loadSnakedCellOf(s, (s) => s.loadUintBig(64)), - onRamp: s.loadMaybeAddress(), + $: 'Router_CCIPSendNACK', + queryID: s.loadUintBig(64), + error: s.loadUintBig(256), } }, - store(self: OnRampSet, b: c.Builder): void { - storeSnakedCellOf(self.destChainSelectors, b, (v, b) => b.storeUint(v, 64)); - b.storeAddress(self.onRamp); + store(self: Router_CCIPSendNACK, b: c.Builder): void { + b.storeUint(0x5a45d434, 32); + b.storeUint(self.queryID, 64); + b.storeUint(self.error, 256); }, - toCell(self: OnRampSet): c.Cell { - return makeCellFrom(self, OnRampSet.store); + toCell(self: Router_CCIPSendNACK): c.Cell { + return makeCellFrom(self, Router_CCIPSendNACK.store); } } /** - > struct OffRampAdded { - > sourceChainSelectors: SnakedCell - > offRampAdded: address + > struct (0x4dd6aa82) Router_GetValidatedFee { + > ccipSend: Cell + > context: T > } */ -export interface OffRampAdded { - readonly $: 'OffRampAdded' - sourceChainSelectors: SnakedCell - offRampAdded: c.Address +export interface Router_GetValidatedFee { + readonly $: 'Router_GetValidatedFee' + ccipSend: Router_CCIPSend + context: T } -export const OffRampAdded = { - create(args: { - sourceChainSelectors: SnakedCell - offRampAdded: c.Address - }): OffRampAdded { +export const Router_GetValidatedFee = { + PREFIX: 0x4dd6aa82, + + create(args: { + ccipSend: Router_CCIPSend + context: T + }): Router_GetValidatedFee { return { - $: 'OffRampAdded', + $: 'Router_GetValidatedFee', ...args } }, - fromSlice(s: c.Slice): OffRampAdded { - return { - $: 'OffRampAdded', - sourceChainSelectors: loadSnakedCellOf(s, (s) => s.loadUintBig(64)), - offRampAdded: s.loadAddress(), - } - }, - store(self: OffRampAdded, b: c.Builder): void { - storeSnakedCellOf(self.sourceChainSelectors, b, (v, b) => b.storeUint(v, 64)); - b.storeAddress(self.offRampAdded); - }, - toCell(self: OffRampAdded): c.Cell { - return makeCellFrom(self, OffRampAdded.store); - } } /** - > struct OffRampRemoved { - > sourceChainSelectors: SnakedCell - > offRampRemoved: address + > struct (0x6f2d00df) Router_LockOrBurn { + > queryID: uint64 + > tokenPool: address + > request: Cell + > executorAddress: address > } */ -export interface OffRampRemoved { - readonly $: 'OffRampRemoved' - sourceChainSelectors: SnakedCell - offRampRemoved: c.Address +export interface Router_LockOrBurn { + readonly $: 'Router_LockOrBurn' + queryID: uint64 + tokenPool: c.Address + request: TokenPool_LockOrBurnInV1 + executorAddress: c.Address } -export const OffRampRemoved = { +export const Router_LockOrBurn = { + PREFIX: 0x6f2d00df, + create(args: { - sourceChainSelectors: SnakedCell - offRampRemoved: c.Address - }): OffRampRemoved { + queryID?: uint64 + tokenPool: c.Address + request: TokenPool_LockOrBurnInV1 + executorAddress: c.Address + }): Router_LockOrBurn { return { - $: 'OffRampRemoved', - ...args + $: 'Router_LockOrBurn', + ...args, + queryID: args.queryID ?? 0n } }, - fromSlice(s: c.Slice): OffRampRemoved { + fromSlice(s: c.Slice): Router_LockOrBurn { + loadAndCheckPrefix32(s, 0x6f2d00df, 'Router_LockOrBurn'); return { - $: 'OffRampRemoved', - sourceChainSelectors: loadSnakedCellOf(s, (s) => s.loadUintBig(64)), - offRampRemoved: s.loadAddress(), + $: 'Router_LockOrBurn', + queryID: s.loadUintBig(64), + tokenPool: s.loadAddress(), + request: loadCellRef(s, TokenPool_LockOrBurnInV1.fromSlice), + executorAddress: s.loadAddress(), } }, - store(self: OffRampRemoved, b: c.Builder): void { - storeSnakedCellOf(self.sourceChainSelectors, b, (v, b) => b.storeUint(v, 64)); - b.storeAddress(self.offRampRemoved); + store(self: Router_LockOrBurn, b: c.Builder): void { + b.storeUint(0x6f2d00df, 32); + b.storeUint(self.queryID, 64); + b.storeAddress(self.tokenPool); + storeCellRef(self.request, b, TokenPool_LockOrBurnInV1.store); + b.storeAddress(self.executorAddress); }, - toCell(self: OffRampRemoved): c.Cell { - return makeCellFrom(self, OffRampRemoved.store); + toCell(self: Router_LockOrBurn): c.Cell { + return makeCellFrom(self, Router_LockOrBurn.store); } } -/** - > struct Cursed { - > subject: uint128 +/** + > struct (0xb19862a3) Router_RelayReleaseOrMint { + > queryID: uint64 + > sourceChainSelector: uint64 + > tokenPool: address + > request: Cell + > requestedFinalityConfig: uint32 + > replyTo: address > } */ -export interface Cursed { - readonly $: 'Cursed' - subject: uint128 +export interface Router_RelayReleaseOrMint { + readonly $: 'Router_RelayReleaseOrMint' + queryID: uint64 + sourceChainSelector: uint64 + tokenPool: c.Address + request: TokenPool_ReleaseOrMintInV1 + requestedFinalityConfig: uint32 + replyTo: c.Address } -export const Cursed = { +export const Router_RelayReleaseOrMint = { + PREFIX: 0xb19862a3, + create(args: { - subject: uint128 - }): Cursed { + queryID?: uint64 + sourceChainSelector: uint64 + tokenPool: c.Address + request: TokenPool_ReleaseOrMintInV1 + requestedFinalityConfig: uint32 + replyTo: c.Address + }): Router_RelayReleaseOrMint { return { - $: 'Cursed', - ...args + $: 'Router_RelayReleaseOrMint', + ...args, + queryID: args.queryID ?? 0n } }, - fromSlice(s: c.Slice): Cursed { + fromSlice(s: c.Slice): Router_RelayReleaseOrMint { + loadAndCheckPrefix32(s, 0xb19862a3, 'Router_RelayReleaseOrMint'); return { - $: 'Cursed', - subject: s.loadUintBig(128), + $: 'Router_RelayReleaseOrMint', + queryID: s.loadUintBig(64), + sourceChainSelector: s.loadUintBig(64), + tokenPool: s.loadAddress(), + request: loadCellRef(s, TokenPool_ReleaseOrMintInV1.fromSlice), + requestedFinalityConfig: s.loadUintBig(32), + replyTo: s.loadAddress(), } }, - store(self: Cursed, b: c.Builder): void { - b.storeUint(self.subject, 128); + store(self: Router_RelayReleaseOrMint, b: c.Builder): void { + b.storeUint(0xb19862a3, 32); + b.storeUint(self.queryID, 64); + b.storeUint(self.sourceChainSelector, 64); + b.storeAddress(self.tokenPool); + storeCellRef(self.request, b, TokenPool_ReleaseOrMintInV1.store); + b.storeUint(self.requestedFinalityConfig, 32); + b.storeAddress(self.replyTo); }, - toCell(self: Cursed): c.Cell { - return makeCellFrom(self, Cursed.store); + toCell(self: Router_RelayReleaseOrMint): c.Cell { + return makeCellFrom(self, Router_RelayReleaseOrMint.store); } } /** - > struct Uncursed { - > subject: uint128 + > struct Router_GetValidatedFeeContext { + > routerContext: address + > userContext: RemainingBitsOrRef > } */ -export interface Uncursed { - readonly $: 'Uncursed' - subject: uint128 +export interface Router_GetValidatedFeeContext { + readonly $: 'Router_GetValidatedFeeContext' + routerContext: c.Address + userContext: RemainingBitsOrRef } -export const Uncursed = { +export const Router_GetValidatedFeeContext = { create(args: { - subject: uint128 - }): Uncursed { + routerContext: c.Address + userContext: RemainingBitsOrRef + }): Router_GetValidatedFeeContext { return { - $: 'Uncursed', + $: 'Router_GetValidatedFeeContext', ...args } }, - fromSlice(s: c.Slice): Uncursed { + fromSlice(s: c.Slice): Router_GetValidatedFeeContext { return { - $: 'Uncursed', - subject: s.loadUintBig(128), + $: 'Router_GetValidatedFeeContext', + routerContext: s.loadAddress(), + userContext: loadTolkRemaining(s), } }, - store(self: Uncursed, b: c.Builder): void { - b.storeUint(self.subject, 128); + store(self: Router_GetValidatedFeeContext, b: c.Builder): void { + b.storeAddress(self.routerContext); + storeTolkRemaining(self.userContext, b); }, - toCell(self: Uncursed): c.Cell { - return makeCellFrom(self, Uncursed.store); + toCell(self: Router_GetValidatedFeeContext): c.Cell { + return makeCellFrom(self, Router_GetValidatedFeeContext.store); } } /** - > struct MessageToOffRampBounced { - > offRamp: address - > execId: uint192 - > } + > type Router_MessageValidated_Any = Router_MessageValidated */ -export interface MessageToOffRampBounced { - readonly $: 'MessageToOffRampBounced' - offRamp: c.Address - execId: uint192 -} +export type Router_MessageValidated_Any = Router_MessageValidated -export const MessageToOffRampBounced = { - create(args: { - offRamp: c.Address - execId: uint192 - }): MessageToOffRampBounced { - return { - $: 'MessageToOffRampBounced', - ...args - } - }, - fromSlice(s: c.Slice): MessageToOffRampBounced { - return { - $: 'MessageToOffRampBounced', - offRamp: s.loadAddress(), - execId: s.loadUintBig(192), - } +export const Router_MessageValidated_Any = { + fromSlice(s: c.Slice): Router_MessageValidated_Any { + return (() => { + loadAndCheckPrefix32(s, 0x9e2155ec, 'Router_MessageValidated'); + return { + $: 'Router_MessageValidated', + fee: s.loadCoins(), + msg: loadCellRef(s, Router_CCIPSend.fromSlice), + context: loadTolkRemaining(s), + } + })(); }, - store(self: MessageToOffRampBounced, b: c.Builder): void { - b.storeAddress(self.offRamp); - b.storeUint(self.execId, 192); + store(self: Router_MessageValidated_Any, b: c.Builder): void { + b.storeUint(0x9e2155ec, 32); + b.storeCoins(self.fee); + storeCellRef(self.msg, b, Router_CCIPSend.store); + storeTolkRemaining(self.context, b); }, - toCell(self: MessageToOffRampBounced): c.Cell { - return makeCellFrom(self, MessageToOffRampBounced.store); + toCell(self: Router_MessageValidated_Any): c.Cell { + return makeCellFrom(self, Router_MessageValidated_Any.store); } } /** - > struct TokenPool_LockOrBurnPrepared { - > feeAmount: coins - > destTokenAmount: coins - > out: TokenPool_LockOrBurnOutV1 + > struct (0x9e2155ec) Router_MessageValidated { + > fee: coins + > msg: Cell + > context: RemainingBitsOrRef > } */ -export interface TokenPool_LockOrBurnPrepared { - readonly $: 'TokenPool_LockOrBurnPrepared' - feeAmount: coins - destTokenAmount: coins - out: TokenPool_LockOrBurnOutV1 +export interface Router_MessageValidated { + readonly $: 'Router_MessageValidated' + fee: coins + msg: Router_CCIPSend + context: RemainingBitsOrRef } -export const TokenPool_LockOrBurnPrepared = { - create(args: { - feeAmount: coins - destTokenAmount: coins - out: TokenPool_LockOrBurnOutV1 - }): TokenPool_LockOrBurnPrepared { +export const Router_MessageValidated = { + PREFIX: 0x9e2155ec, + + create(args: { + fee: coins + msg: Router_CCIPSend + context: RemainingBitsOrRef + }): Router_MessageValidated { return { - $: 'TokenPool_LockOrBurnPrepared', + $: 'Router_MessageValidated', ...args } }, - fromSlice(s: c.Slice): TokenPool_LockOrBurnPrepared { - return { - $: 'TokenPool_LockOrBurnPrepared', - feeAmount: s.loadCoins(), - destTokenAmount: s.loadCoins(), - out: TokenPool_LockOrBurnOutV1.fromSlice(s), - } +} + +/** + > type Router_MessageValidationFailed_Any = Router_MessageValidationFailed + */ +export type Router_MessageValidationFailed_Any = Router_MessageValidationFailed + +export const Router_MessageValidationFailed_Any = { + fromSlice(s: c.Slice): Router_MessageValidationFailed_Any { + return (() => { + loadAndCheckPrefix32(s, 0xec23c562, 'Router_MessageValidationFailed'); + return { + $: 'Router_MessageValidationFailed', + error: s.loadUintBig(256), + msg: loadCellRef(s, Router_CCIPSend.fromSlice), + context: loadTolkRemaining(s), + } + })(); }, - store(self: TokenPool_LockOrBurnPrepared, b: c.Builder): void { - b.storeCoins(self.feeAmount); - b.storeCoins(self.destTokenAmount); - TokenPool_LockOrBurnOutV1.store(self.out, b); + store(self: Router_MessageValidationFailed_Any, b: c.Builder): void { + b.storeUint(0xec23c562, 32); + b.storeUint(self.error, 256); + storeCellRef(self.msg, b, Router_CCIPSend.store); + storeTolkRemaining(self.context, b); }, - toCell(self: TokenPool_LockOrBurnPrepared): c.Cell { - return makeCellFrom(self, TokenPool_LockOrBurnPrepared.store); + toCell(self: Router_MessageValidationFailed_Any): c.Cell { + return makeCellFrom(self, Router_MessageValidationFailed_Any.store); } } /** - > struct TokenPool_Transfer { - > id: uint256 - > details: Cell> + > struct (0xec23c562) Router_MessageValidationFailed { + > error: uint256 + > msg: Cell + > context: RemainingBitsOrRef > } */ -export interface TokenPool_Transfer { - readonly $: 'TokenPool_Transfer' - id: uint256 - details: TokenPool_TransferDetails +export interface Router_MessageValidationFailed { + readonly $: 'Router_MessageValidationFailed' + error: uint256 + msg: Router_CCIPSend + context: RemainingBitsOrRef } -export const TokenPool_Transfer = { - create(args: { - id: uint256 - details: TokenPool_TransferDetails - }): TokenPool_Transfer { +export const Router_MessageValidationFailed = { + PREFIX: 0xec23c562, + + create(args: { + error: uint256 + msg: Router_CCIPSend + context: RemainingBitsOrRef + }): Router_MessageValidationFailed { return { - $: 'TokenPool_Transfer', + $: 'Router_MessageValidationFailed', ...args } }, } /** - > struct TokenPool_TransferDetails { - > receiver: R - > remoteChainSelector: uint64 - > originalSender: S - > amount: C - > localToken: address + > struct (0xb76e3a84) Router_TokenPoolLockOrBurnFailed { + > queryID: uint64 + > tokenPool: address + > exitCode: int32 > } */ -export interface TokenPool_TransferDetails { - readonly $: 'TokenPool_TransferDetails' - receiver: R - remoteChainSelector: uint64 - originalSender: S - amount: C - localToken: c.Address -} - -export const TokenPool_TransferDetails = { - create(args: { - receiver: R - remoteChainSelector: uint64 - originalSender: S - amount: C - localToken: c.Address - }): TokenPool_TransferDetails { +export interface Router_TokenPoolLockOrBurnFailed { + readonly $: 'Router_TokenPoolLockOrBurnFailed' + queryID: uint64 + tokenPool: c.Address + exitCode: int32 +} + +export const Router_TokenPoolLockOrBurnFailed = { + PREFIX: 0xb76e3a84, + + create(args: { + queryID?: uint64 + tokenPool: c.Address + exitCode: int32 + }): Router_TokenPoolLockOrBurnFailed { return { - $: 'TokenPool_TransferDetails', - ...args + $: 'Router_TokenPoolLockOrBurnFailed', + ...args, + queryID: args.queryID ?? 0n + } + }, + fromSlice(s: c.Slice): Router_TokenPoolLockOrBurnFailed { + loadAndCheckPrefix32(s, 0xb76e3a84, 'Router_TokenPoolLockOrBurnFailed'); + return { + $: 'Router_TokenPoolLockOrBurnFailed', + queryID: s.loadUintBig(64), + tokenPool: s.loadAddress(), + exitCode: s.loadIntBig(32), } }, + store(self: Router_TokenPoolLockOrBurnFailed, b: c.Builder): void { + b.storeUint(0xb76e3a84, 32); + b.storeUint(self.queryID, 64); + b.storeAddress(self.tokenPool); + b.storeInt(self.exitCode, 32); + }, + toCell(self: Router_TokenPoolLockOrBurnFailed): c.Cell { + return makeCellFrom(self, Router_TokenPoolLockOrBurnFailed.store); + } } /** - > type TokenPool_LockOrBurnTransfer = TokenPool_Transfer, coins> + > struct (0xb980cb4e) Router_TokenPoolReleaseOrMintFailed { + > queryID: uint64 + > tokenPool: address + > exitCode: int32 + > } */ -export type TokenPool_LockOrBurnTransfer = TokenPool_Transfer +export interface Router_TokenPoolReleaseOrMintFailed { + readonly $: 'Router_TokenPoolReleaseOrMintFailed' + queryID: uint64 + tokenPool: c.Address + exitCode: int32 +} -export const TokenPool_LockOrBurnTransfer = { - fromSlice(s: c.Slice): TokenPool_LockOrBurnTransfer { - return (() => { - return { - $: 'TokenPool_Transfer', - id: s.loadUintBig(256), - details: loadCellRef>(s, - (s) => (() => { - return { - $: 'TokenPool_TransferDetails', - receiver: loadCellRef(s, CrossChainAddress.fromSlice), - remoteChainSelector: s.loadUintBig(64), - originalSender: s.loadAddress(), - amount: s.loadCoins(), - localToken: s.loadAddress(), - } - })() - ), - } - })(); +export const Router_TokenPoolReleaseOrMintFailed = { + PREFIX: 0xb980cb4e, + + create(args: { + queryID?: uint64 + tokenPool: c.Address + exitCode: int32 + }): Router_TokenPoolReleaseOrMintFailed { + return { + $: 'Router_TokenPoolReleaseOrMintFailed', + ...args, + queryID: args.queryID ?? 0n + } }, - store(self: TokenPool_LockOrBurnTransfer, b: c.Builder): void { - b.storeUint(self.id, 256); - storeCellRef>(self.details, b, - (v,b) => { storeCellRef(v.receiver, b, CrossChainAddress.store); - b.storeUint(v.remoteChainSelector, 64); - b.storeAddress(v.originalSender); - b.storeCoins(v.amount); - b.storeAddress(v.localToken); } - ); + fromSlice(s: c.Slice): Router_TokenPoolReleaseOrMintFailed { + loadAndCheckPrefix32(s, 0xb980cb4e, 'Router_TokenPoolReleaseOrMintFailed'); + return { + $: 'Router_TokenPoolReleaseOrMintFailed', + queryID: s.loadUintBig(64), + tokenPool: s.loadAddress(), + exitCode: s.loadIntBig(32), + } }, - toCell(self: TokenPool_LockOrBurnTransfer): c.Cell { - return makeCellFrom(self, TokenPool_LockOrBurnTransfer.store); + store(self: Router_TokenPoolReleaseOrMintFailed, b: c.Builder): void { + b.storeUint(0xb980cb4e, 32); + b.storeUint(self.queryID, 64); + b.storeAddress(self.tokenPool); + b.storeInt(self.exitCode, 32); + }, + toCell(self: Router_TokenPoolReleaseOrMintFailed): c.Cell { + return makeCellFrom(self, Router_TokenPoolReleaseOrMintFailed.store); } } /** - > struct TokenPool_LockOrBurnInV1 { - > transfer: TokenPool_LockOrBurnTransfer + > struct RMNRemote { + > admin: Ownable2Step + > cursedSubjects: CursedSubjects + > forwardUpdates: map > } */ -export interface TokenPool_LockOrBurnInV1 { - readonly $: 'TokenPool_LockOrBurnInV1' - transfer: TokenPool_LockOrBurnTransfer +export interface RMNRemote { + readonly $: 'RMNRemote' + admin: Ownable2Step + cursedSubjects: CursedSubjects + forwardUpdates: Set /* = [] as map */ } -export const TokenPool_LockOrBurnInV1 = { +export const RMNRemote = { create(args: { - transfer: TokenPool_LockOrBurnTransfer - }): TokenPool_LockOrBurnInV1 { + admin: Ownable2Step + cursedSubjects: CursedSubjects + forwardUpdates: Set /* = [] as map */ + }): RMNRemote { return { - $: 'TokenPool_LockOrBurnInV1', + $: 'RMNRemote', ...args } }, - fromSlice(s: c.Slice): TokenPool_LockOrBurnInV1 { + fromSlice(s: c.Slice): RMNRemote { return { - $: 'TokenPool_LockOrBurnInV1', - transfer: TokenPool_LockOrBurnTransfer.fromSlice(s), + $: 'RMNRemote', + admin: Ownable2Step.fromSlice(s), + cursedSubjects: CursedSubjects.fromSlice(s), + forwardUpdates: dictToSet(c.Dictionary.load(c.Dictionary.Keys.Address(), createDictionaryValue<[]>( + (s) => [], + (v,b) => { {} } + ), s)), } }, - store(self: TokenPool_LockOrBurnInV1, b: c.Builder): void { - TokenPool_LockOrBurnTransfer.store(self.transfer, b); + store(self: RMNRemote, b: c.Builder): void { + Ownable2Step.store(self.admin, b); + CursedSubjects.store(self.cursedSubjects, b); + b.storeDict(setToDict(self.forwardUpdates, c.Dictionary.Keys.Address(), createDictionaryValue<[]>( + (s) => [], + (v,b) => { {} } + )), c.Dictionary.Keys.Address(), createDictionaryValue<[]>( + (s) => [], + (v,b) => { {} } + )); }, - toCell(self: TokenPool_LockOrBurnInV1): c.Cell { - return makeCellFrom(self, TokenPool_LockOrBurnInV1.store); + toCell(self: RMNRemote): c.Cell { + return makeCellFrom(self, RMNRemote.store); } } /** - > struct TokenPool_LockOrBurnOutV1 { - > destTokenAddress: Cell - > destPoolData: cell + > struct Storage { + > id: uint32 + > ownable: Ownable2Step + > wrappedNative: address + > onRamps: map + > offRamps: map + > rmnRemote: Cell > } */ -export interface TokenPool_LockOrBurnOutV1 { - readonly $: 'TokenPool_LockOrBurnOutV1' - destTokenAddress: CrossChainAddress - destPoolData: c.Cell +export interface Storage { + readonly $: 'Storage' + id: uint32 + ownable: Ownable2Step + wrappedNative: c.Address + onRamps: Map /* = [] as map */ + offRamps: Map /* = [] as map */ + rmnRemote: RMNRemote } -export const TokenPool_LockOrBurnOutV1 = { +export const Storage = { create(args: { - destTokenAddress: CrossChainAddress - destPoolData: c.Cell - }): TokenPool_LockOrBurnOutV1 { + id: uint32 + ownable: Ownable2Step + wrappedNative: c.Address + onRamps: Map /* = [] as map */ + offRamps: Map /* = [] as map */ + rmnRemote: RMNRemote + }): Storage { return { - $: 'TokenPool_LockOrBurnOutV1', + $: 'Storage', ...args } }, - fromSlice(s: c.Slice): TokenPool_LockOrBurnOutV1 { + fromSlice(s: c.Slice): Storage { return { - $: 'TokenPool_LockOrBurnOutV1', - destTokenAddress: loadCellRef(s, CrossChainAddress.fromSlice), - destPoolData: s.loadRef(), + $: 'Storage', + id: s.loadUintBig(32), + ownable: Ownable2Step.fromSlice(s), + wrappedNative: s.loadAddress(), + onRamps: dictToMap(c.Dictionary.load(c.Dictionary.Keys.BigUint(64), createDictionaryValue( + (s) => s.loadAddress(), + (v,b) => b.storeAddress(v) + ), s)), + offRamps: dictToMap(c.Dictionary.load(c.Dictionary.Keys.BigUint(64), createDictionaryValue( + (s) => s.loadAddress(), + (v,b) => b.storeAddress(v) + ), s)), + rmnRemote: loadCellRef(s, RMNRemote.fromSlice), } }, - store(self: TokenPool_LockOrBurnOutV1, b: c.Builder): void { - storeCellRef(self.destTokenAddress, b, CrossChainAddress.store); - b.storeRef(self.destPoolData); + store(self: Storage, b: c.Builder): void { + b.storeUint(self.id, 32); + Ownable2Step.store(self.ownable, b); + b.storeAddress(self.wrappedNative); + b.storeDict(mapToDict(self.onRamps, c.Dictionary.Keys.BigUint(64), createDictionaryValue( + (s) => s.loadAddress(), + (v,b) => b.storeAddress(v) + )), c.Dictionary.Keys.BigUint(64), createDictionaryValue( + (s) => s.loadAddress(), + (v,b) => b.storeAddress(v) + )); + b.storeDict(mapToDict(self.offRamps, c.Dictionary.Keys.BigUint(64), createDictionaryValue( + (s) => s.loadAddress(), + (v,b) => b.storeAddress(v) + )), c.Dictionary.Keys.BigUint(64), createDictionaryValue( + (s) => s.loadAddress(), + (v,b) => b.storeAddress(v) + )); + storeCellRef(self.rmnRemote, b, RMNRemote.store); }, - toCell(self: TokenPool_LockOrBurnOutV1): c.Cell { - return makeCellFrom(self, TokenPool_LockOrBurnOutV1.store); + toCell(self: Storage): c.Cell { + return makeCellFrom(self, Storage.store); } } /** - > type CrossChainAddress = slice + > struct OnRampSet { + > destChainSelectors: SnakedCell + > onRamp: address? + > } */ -export type CrossChainAddress = c.Slice +export interface OnRampSet { + readonly $: 'OnRampSet' + destChainSelectors: SnakedCell + onRamp: c.Address | null +} -export const CrossChainAddress = { - fromSlice(s: c.Slice): CrossChainAddress { - return invokeCustomUnpackFromSlice('CrossChainAddress', s); +export const OnRampSet = { + create(args: { + destChainSelectors: SnakedCell + onRamp: c.Address | null + }): OnRampSet { + return { + $: 'OnRampSet', + ...args + } }, - store(self: CrossChainAddress, b: c.Builder): void { - invokeCustomPackToBuilder('CrossChainAddress', self, b); + fromSlice(s: c.Slice): OnRampSet { + return { + $: 'OnRampSet', + destChainSelectors: loadSnakedCellOf(s, (s) => s.loadUintBig(64)), + onRamp: s.loadMaybeAddress(), + } }, - toCell(self: CrossChainAddress): c.Cell { - return makeCellFrom(self, CrossChainAddress.store); + store(self: OnRampSet, b: c.Builder): void { + storeSnakedCellOf(self.destChainSelectors, b, (v, b) => b.storeUint(v, 64)); + b.storeAddress(self.onRamp); + }, + toCell(self: OnRampSet): c.Cell { + return makeCellFrom(self, OnRampSet.store); } } /** - > type ExtraArgs = GenericExtraArgsV2 | SVMExtraArgsV1 | SuiExtraArgsV1 + > struct OffRampAdded { + > sourceChainSelectors: SnakedCell + > offRampAdded: address + > } */ -export type ExtraArgs = - | GenericExtraArgsV2 - | SVMExtraArgsV1 - | SuiExtraArgsV1 +export interface OffRampAdded { + readonly $: 'OffRampAdded' + sourceChainSelectors: SnakedCell + offRampAdded: c.Address +} -export const ExtraArgs = { - fromSlice(s: c.Slice): ExtraArgs { - return lookupPrefix(s, 0x181dcf10, 32) ? GenericExtraArgsV2.fromSlice(s) : - lookupPrefix(s, 0x1f3b3aba, 32) ? SVMExtraArgsV1.fromSlice(s) : - lookupPrefix(s, 0x21ea4ca9, 32) ? SuiExtraArgsV1.fromSlice(s) : - throwNonePrefixMatch('ExtraArgs'); +export const OffRampAdded = { + create(args: { + sourceChainSelectors: SnakedCell + offRampAdded: c.Address + }): OffRampAdded { + return { + $: 'OffRampAdded', + ...args + } }, - store(self: ExtraArgs, b: c.Builder): void { - switch (self.$) { - case 'GenericExtraArgsV2': - GenericExtraArgsV2.store(self, b); - break; - case 'SVMExtraArgsV1': - SVMExtraArgsV1.store(self, b); - break; - case 'SuiExtraArgsV1': - SuiExtraArgsV1.store(self, b); - break; + fromSlice(s: c.Slice): OffRampAdded { + return { + $: 'OffRampAdded', + sourceChainSelectors: loadSnakedCellOf(s, (s) => s.loadUintBig(64)), + offRampAdded: s.loadAddress(), } }, - toCell(self: ExtraArgs): c.Cell { - return makeCellFrom(self, ExtraArgs.store); + store(self: OffRampAdded, b: c.Builder): void { + storeSnakedCellOf(self.sourceChainSelectors, b, (v, b) => b.storeUint(v, 64)); + b.storeAddress(self.offRampAdded); + }, + toCell(self: OffRampAdded): c.Cell { + return makeCellFrom(self, OffRampAdded.store); } } /** - > struct (0x181dcf10) GenericExtraArgsV2 { - > gasLimit: uint256? - > allowOutOfOrderExecution: bool + > struct OffRampRemoved { + > sourceChainSelectors: SnakedCell + > offRampRemoved: address > } */ -export interface GenericExtraArgsV2 { - readonly $: 'GenericExtraArgsV2' - gasLimit: uint256 | null - allowOutOfOrderExecution: boolean +export interface OffRampRemoved { + readonly $: 'OffRampRemoved' + sourceChainSelectors: SnakedCell + offRampRemoved: c.Address } -export const GenericExtraArgsV2 = { - PREFIX: 0x181dcf10, - +export const OffRampRemoved = { create(args: { - gasLimit: uint256 | null - allowOutOfOrderExecution: boolean - }): GenericExtraArgsV2 { + sourceChainSelectors: SnakedCell + offRampRemoved: c.Address + }): OffRampRemoved { return { - $: 'GenericExtraArgsV2', + $: 'OffRampRemoved', ...args } }, - fromSlice(s: c.Slice): GenericExtraArgsV2 { - loadAndCheckPrefix32(s, 0x181dcf10, 'GenericExtraArgsV2'); + fromSlice(s: c.Slice): OffRampRemoved { return { - $: 'GenericExtraArgsV2', - gasLimit: s.loadBoolean() ? s.loadUintBig(256) : null, - allowOutOfOrderExecution: s.loadBoolean(), + $: 'OffRampRemoved', + sourceChainSelectors: loadSnakedCellOf(s, (s) => s.loadUintBig(64)), + offRampRemoved: s.loadAddress(), } }, - store(self: GenericExtraArgsV2, b: c.Builder): void { - b.storeUint(0x181dcf10, 32); - storeTolkNullable(self.gasLimit, b, - (v,b) => b.storeUint(v, 256) - ); - b.storeBit(self.allowOutOfOrderExecution); + store(self: OffRampRemoved, b: c.Builder): void { + storeSnakedCellOf(self.sourceChainSelectors, b, (v, b) => b.storeUint(v, 64)); + b.storeAddress(self.offRampRemoved); }, - toCell(self: GenericExtraArgsV2): c.Cell { - return makeCellFrom(self, GenericExtraArgsV2.store); + toCell(self: OffRampRemoved): c.Cell { + return makeCellFrom(self, OffRampRemoved.store); } } /** - > struct (0x1f3b3aba) SVMExtraArgsV1 { - > computeUnits: uint32 - > accountIsWritableBitmap: uint64 - > allowOutOfOrderExecution: bool - > tokenReceiver: uint256 - > accounts: SnakedCell + > struct Cursed { + > subject: uint128 > } */ -export interface SVMExtraArgsV1 { - readonly $: 'SVMExtraArgsV1' - computeUnits: uint32 - accountIsWritableBitmap: uint64 - allowOutOfOrderExecution: boolean - tokenReceiver: uint256 - accounts: SnakedCell +export interface Cursed { + readonly $: 'Cursed' + subject: uint128 } -export const SVMExtraArgsV1 = { - PREFIX: 0x1f3b3aba, - +export const Cursed = { create(args: { - computeUnits: uint32 - accountIsWritableBitmap: uint64 - allowOutOfOrderExecution: boolean - tokenReceiver: uint256 - accounts: SnakedCell - }): SVMExtraArgsV1 { + subject: uint128 + }): Cursed { return { - $: 'SVMExtraArgsV1', + $: 'Cursed', ...args } }, - fromSlice(s: c.Slice): SVMExtraArgsV1 { - loadAndCheckPrefix32(s, 0x1f3b3aba, 'SVMExtraArgsV1'); + fromSlice(s: c.Slice): Cursed { return { - $: 'SVMExtraArgsV1', - computeUnits: s.loadUintBig(32), - accountIsWritableBitmap: s.loadUintBig(64), - allowOutOfOrderExecution: s.loadBoolean(), - tokenReceiver: s.loadUintBig(256), - accounts: loadSnakedCellOf(s, (s) => s.loadUintBig(256)), + $: 'Cursed', + subject: s.loadUintBig(128), } }, - store(self: SVMExtraArgsV1, b: c.Builder): void { - b.storeUint(0x1f3b3aba, 32); - b.storeUint(self.computeUnits, 32); - b.storeUint(self.accountIsWritableBitmap, 64); - b.storeBit(self.allowOutOfOrderExecution); - b.storeUint(self.tokenReceiver, 256); - storeSnakedCellOf(self.accounts, b, (v, b) => b.storeUint(v, 256)); + store(self: Cursed, b: c.Builder): void { + b.storeUint(self.subject, 128); }, - toCell(self: SVMExtraArgsV1): c.Cell { - return makeCellFrom(self, SVMExtraArgsV1.store); + toCell(self: Cursed): c.Cell { + return makeCellFrom(self, Cursed.store); } } /** - > struct (0x21ea4ca9) SuiExtraArgsV1 { - > gasLimit: uint256 - > allowOutOfOrderExecution: bool - > tokenReceiver: uint256 - > receiverObjectIds: SnakedCell + > struct Uncursed { + > subject: uint128 > } */ -export interface SuiExtraArgsV1 { - readonly $: 'SuiExtraArgsV1' - gasLimit: uint256 - allowOutOfOrderExecution: boolean - tokenReceiver: uint256 - receiverObjectIds: SnakedCell +export interface Uncursed { + readonly $: 'Uncursed' + subject: uint128 } -export const SuiExtraArgsV1 = { - PREFIX: 0x21ea4ca9, - +export const Uncursed = { create(args: { - gasLimit: uint256 - allowOutOfOrderExecution: boolean - tokenReceiver: uint256 - receiverObjectIds: SnakedCell - }): SuiExtraArgsV1 { + subject: uint128 + }): Uncursed { return { - $: 'SuiExtraArgsV1', + $: 'Uncursed', ...args } }, - fromSlice(s: c.Slice): SuiExtraArgsV1 { - loadAndCheckPrefix32(s, 0x21ea4ca9, 'SuiExtraArgsV1'); + fromSlice(s: c.Slice): Uncursed { return { - $: 'SuiExtraArgsV1', - gasLimit: s.loadUintBig(256), - allowOutOfOrderExecution: s.loadBoolean(), - tokenReceiver: s.loadUintBig(256), - receiverObjectIds: loadSnakedCellOf(s, (s) => s.loadUintBig(256)), + $: 'Uncursed', + subject: s.loadUintBig(128), } }, - store(self: SuiExtraArgsV1, b: c.Builder): void { - b.storeUint(0x21ea4ca9, 32); - b.storeUint(self.gasLimit, 256); - b.storeBit(self.allowOutOfOrderExecution); - b.storeUint(self.tokenReceiver, 256); - storeSnakedCellOf(self.receiverObjectIds, b, (v, b) => b.storeUint(v, 256)); + store(self: Uncursed, b: c.Builder): void { + b.storeUint(self.subject, 128); }, - toCell(self: SuiExtraArgsV1): c.Cell { - return makeCellFrom(self, SuiExtraArgsV1.store); + toCell(self: Uncursed): c.Cell { + return makeCellFrom(self, Uncursed.store); } } /** - > struct TokenAmount { - > amount: coins - > token: address + > struct MessageToOffRampBounced { + > offRamp: address + > execId: uint192 > } */ -export interface TokenAmount { - readonly $: 'TokenAmount' - amount: coins - token: c.Address +export interface MessageToOffRampBounced { + readonly $: 'MessageToOffRampBounced' + offRamp: c.Address + execId: uint192 } -export const TokenAmount = { +export const MessageToOffRampBounced = { create(args: { - amount: coins - token: c.Address - }): TokenAmount { + offRamp: c.Address + execId: uint192 + }): MessageToOffRampBounced { return { - $: 'TokenAmount', + $: 'MessageToOffRampBounced', ...args } }, - fromSlice(s: c.Slice): TokenAmount { + fromSlice(s: c.Slice): MessageToOffRampBounced { return { - $: 'TokenAmount', - amount: s.loadCoins(), - token: s.loadAddress(), + $: 'MessageToOffRampBounced', + offRamp: s.loadAddress(), + execId: s.loadUintBig(192), } }, - store(self: TokenAmount, b: c.Builder): void { - b.storeCoins(self.amount); - b.storeAddress(self.token); + store(self: MessageToOffRampBounced, b: c.Builder): void { + b.storeAddress(self.offRamp); + b.storeUint(self.execId, 192); }, - toCell(self: TokenAmount): c.Cell { - return makeCellFrom(self, TokenAmount.store); + toCell(self: MessageToOffRampBounced): c.Cell { + return makeCellFrom(self, MessageToOffRampBounced.store); } } @@ -3347,7 +3655,7 @@ function calculateDeployedAddress(code: c.Cell, data: c.Cell, options: DeployedA } export class Router implements c.Contract { - static CodeCell = c.Cell.fromBase64('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'); + static CodeCell = c.Cell.fromBase64('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'); static Errors = { 'Common_Error.CrossChainAddressOutOfRange': 5, @@ -3371,6 +3679,7 @@ export class Router implements c.Contract { 'Router_Error.InsufficientFee': 57109, 'Router_Error.TokenTransferNotThroughNotification': 57110, 'Router_Error.TokenAmountMismatch': 57112, + 'Router_Error.SourceChainSelectorMismatch': 57114, } readonly address: c.Address @@ -3533,6 +3842,17 @@ export class Router implements c.Contract { return Router_LockOrBurn.toCell(Router_LockOrBurn.create(body)); } + static createCellOfRouterRelayReleaseOrMint(body: { + queryID?: uint64 + sourceChainSelector: uint64 + tokenPool: c.Address + request: TokenPool_ReleaseOrMintInV1 + requestedFinalityConfig: uint32 + replyTo: c.Address + }) { + return Router_RelayReleaseOrMint.toCell(Router_RelayReleaseOrMint.create(body)); + } + static createCellOfRouterRMNOwnableMessage(body: { content: RemainingBitsAndRefs }) { @@ -3762,6 +4082,21 @@ export class Router implements c.Contract { }); } + async sendRouterRelayReleaseOrMint(provider: ContractProvider, via: Sender, msgValue: coins, body: { + queryID?: uint64 + sourceChainSelector: uint64 + tokenPool: c.Address + request: TokenPool_ReleaseOrMintInV1 + requestedFinalityConfig: uint32 + replyTo: c.Address + }, extraOptions?: ExtraSendOptions) { + return provider.internal(via, { + value: msgValue, + body: Router_RelayReleaseOrMint.toCell(Router_RelayReleaseOrMint.create(body)), + ...extraOptions + }); + } + async sendRouterRMNOwnableMessage(provider: ContractProvider, via: Sender, msgValue: coins, body: { content: RemainingBitsAndRefs }, extraOptions?: ExtraSendOptions) { diff --git a/contracts/wrappers/gen/ccip/pools/BurnMintTokenPool.ts b/contracts/wrappers/gen/ccip/pools/BurnMintTokenPool.ts index 5d7d64e2c..ac7907841 100644 --- a/contracts/wrappers/gen/ccip/pools/BurnMintTokenPool.ts +++ b/contracts/wrappers/gen/ccip/pools/BurnMintTokenPool.ts @@ -1383,7 +1383,7 @@ export const CursedSubjects = { /** > struct TokenPool_AdminConfig { > ownable: Cell - > rmnProxy: address + > rmnProxy: address? > dynamicConfig: Cell > jettonClient: JettonClient > allowedFinalityConfig: uint32 @@ -1394,7 +1394,7 @@ export const CursedSubjects = { export interface TokenPool_AdminConfig { readonly $: 'TokenPool_AdminConfig' ownable: Ownable2Step - rmnProxy: c.Address + rmnProxy: c.Address | null dynamicConfig: TokenPool_DynamicConfig jettonClient: JettonClient allowedFinalityConfig: uint32 /* = 0 as uint32 */ @@ -1405,7 +1405,7 @@ export interface TokenPool_AdminConfig { export const TokenPool_AdminConfig = { create(args: { ownable: Ownable2Step - rmnProxy: c.Address + rmnProxy: c.Address | null dynamicConfig: TokenPool_DynamicConfig jettonClient: JettonClient allowedFinalityConfig?: uint32 /* = 0 as uint32 */ @@ -1424,7 +1424,7 @@ export const TokenPool_AdminConfig = { return { $: 'TokenPool_AdminConfig', ownable: loadCellRef(s, Ownable2Step.fromSlice), - rmnProxy: s.loadAddress(), + rmnProxy: s.loadMaybeAddress(), dynamicConfig: loadCellRef(s, TokenPool_DynamicConfig.fromSlice), jettonClient: JettonClient.fromSlice(s), allowedFinalityConfig: s.loadUintBig(32), @@ -1451,7 +1451,7 @@ export const TokenPool_AdminConfig = { /** > struct TokenPool_Data { > adminConfig: Cell - > mirroredPolicy: Cell + > localPolicy: Cell > tokenDecimals: uint8 > remoteChainConfigs: map > tokenTransferFeeConfigs: map @@ -1460,7 +1460,7 @@ export const TokenPool_AdminConfig = { export interface TokenPool_Data { readonly $: 'TokenPool_Data' adminConfig: TokenPool_AdminConfig - mirroredPolicy: TokenPool_MirroredPolicy + localPolicy: TokenPool_LocalPolicy tokenDecimals: uint8 remoteChainConfigs: Map /* = [] as map */ tokenTransferFeeConfigs: Map /* = [] as map */ @@ -1469,7 +1469,7 @@ export interface TokenPool_Data { export const TokenPool_Data = { create(args: { adminConfig: TokenPool_AdminConfig - mirroredPolicy: TokenPool_MirroredPolicy + localPolicy: TokenPool_LocalPolicy tokenDecimals: uint8 remoteChainConfigs: Map /* = [] as map */ tokenTransferFeeConfigs: Map /* = [] as map */ @@ -1483,7 +1483,7 @@ export const TokenPool_Data = { return { $: 'TokenPool_Data', adminConfig: loadCellRef(s, TokenPool_AdminConfig.fromSlice), - mirroredPolicy: loadCellRef(s, TokenPool_MirroredPolicy.fromSlice), + localPolicy: loadCellRef(s, TokenPool_LocalPolicy.fromSlice), tokenDecimals: s.loadUintBig(8), remoteChainConfigs: dictToMap(c.Dictionary.load(c.Dictionary.Keys.BigUint(64), createDictionaryValue(TokenPool_RemoteChainConfig.fromSlice, TokenPool_RemoteChainConfig.store), s)), tokenTransferFeeConfigs: dictToMap(c.Dictionary.load(c.Dictionary.Keys.BigUint(64), createDictionaryValue(TokenPool_TokenTransferFeeConfig.fromSlice, TokenPool_TokenTransferFeeConfig.store), s)), @@ -1491,7 +1491,7 @@ export const TokenPool_Data = { }, store(self: TokenPool_Data, b: c.Builder): void { storeCellRef(self.adminConfig, b, TokenPool_AdminConfig.store); - storeCellRef(self.mirroredPolicy, b, TokenPool_MirroredPolicy.store); + storeCellRef(self.localPolicy, b, TokenPool_LocalPolicy.store); b.storeUint(self.tokenDecimals, 8); b.storeDict(mapToDict(self.remoteChainConfigs, c.Dictionary.Keys.BigUint(64), createDictionaryValue(TokenPool_RemoteChainConfig.fromSlice, TokenPool_RemoteChainConfig.store)), c.Dictionary.Keys.BigUint(64), createDictionaryValue(TokenPool_RemoteChainConfig.fromSlice, TokenPool_RemoteChainConfig.store)); b.storeDict(mapToDict(self.tokenTransferFeeConfigs, c.Dictionary.Keys.BigUint(64), createDictionaryValue(TokenPool_TokenTransferFeeConfig.fromSlice, TokenPool_TokenTransferFeeConfig.store)), c.Dictionary.Keys.BigUint(64), createDictionaryValue(TokenPool_TokenTransferFeeConfig.fromSlice, TokenPool_TokenTransferFeeConfig.store)); @@ -1551,108 +1551,35 @@ export const TokenPool_DynamicConfig = { } /** - > struct TokenPool_MirroredPolicy { - > onRamps: map - > offRamps: map + > struct TokenPool_LocalPolicy { > cursedSubjects: CursedSubjects > } */ -export interface TokenPool_MirroredPolicy { - readonly $: 'TokenPool_MirroredPolicy' - onRamps: Map /* = [] as map */ - offRamps: Map /* = [] as map */ +export interface TokenPool_LocalPolicy { + readonly $: 'TokenPool_LocalPolicy' cursedSubjects: CursedSubjects } -export const TokenPool_MirroredPolicy = { +export const TokenPool_LocalPolicy = { create(args: { - onRamps: Map /* = [] as map */ - offRamps: Map /* = [] as map */ cursedSubjects: CursedSubjects - }): TokenPool_MirroredPolicy { + }): TokenPool_LocalPolicy { return { - $: 'TokenPool_MirroredPolicy', + $: 'TokenPool_LocalPolicy', ...args } }, - fromSlice(s: c.Slice): TokenPool_MirroredPolicy { + fromSlice(s: c.Slice): TokenPool_LocalPolicy { return { - $: 'TokenPool_MirroredPolicy', - onRamps: dictToMap(c.Dictionary.load(c.Dictionary.Keys.BigUint(64), createDictionaryValue( - (s) => s.loadAddress(), - (v,b) => b.storeAddress(v) - ), s)), - offRamps: dictToMap(c.Dictionary.load(c.Dictionary.Keys.BigUint(64), createDictionaryValue( - (s) => s.loadAddress(), - (v,b) => b.storeAddress(v) - ), s)), + $: 'TokenPool_LocalPolicy', cursedSubjects: CursedSubjects.fromSlice(s), } }, - store(self: TokenPool_MirroredPolicy, b: c.Builder): void { - b.storeDict(mapToDict(self.onRamps, c.Dictionary.Keys.BigUint(64), createDictionaryValue( - (s) => s.loadAddress(), - (v,b) => b.storeAddress(v) - )), c.Dictionary.Keys.BigUint(64), createDictionaryValue( - (s) => s.loadAddress(), - (v,b) => b.storeAddress(v) - )); - b.storeDict(mapToDict(self.offRamps, c.Dictionary.Keys.BigUint(64), createDictionaryValue( - (s) => s.loadAddress(), - (v,b) => b.storeAddress(v) - )), c.Dictionary.Keys.BigUint(64), createDictionaryValue( - (s) => s.loadAddress(), - (v,b) => b.storeAddress(v) - )); + store(self: TokenPool_LocalPolicy, b: c.Builder): void { CursedSubjects.store(self.cursedSubjects, b); }, - toCell(self: TokenPool_MirroredPolicy): c.Cell { - return makeCellFrom(self, TokenPool_MirroredPolicy.store); - } -} - -/** - > struct TokenPool_RampUpdate { - > remoteChainSelector: uint64 - > onRamp: address? - > offRamp: address? - > } - */ -export interface TokenPool_RampUpdate { - readonly $: 'TokenPool_RampUpdate' - remoteChainSelector: uint64 - onRamp: c.Address | null /* = null */ - offRamp: c.Address | null /* = null */ -} - -export const TokenPool_RampUpdate = { - create(args: { - remoteChainSelector: uint64 - onRamp?: c.Address | null /* = null */ - offRamp?: c.Address | null /* = null */ - }): TokenPool_RampUpdate { - return { - $: 'TokenPool_RampUpdate', - onRamp: null, - offRamp: null, - ...args - } - }, - fromSlice(s: c.Slice): TokenPool_RampUpdate { - return { - $: 'TokenPool_RampUpdate', - remoteChainSelector: s.loadUintBig(64), - onRamp: s.loadMaybeAddress(), - offRamp: s.loadMaybeAddress(), - } - }, - store(self: TokenPool_RampUpdate, b: c.Builder): void { - b.storeUint(self.remoteChainSelector, 64); - b.storeAddress(self.onRamp); - b.storeAddress(self.offRamp); - }, - toCell(self: TokenPool_RampUpdate): c.Cell { - return makeCellFrom(self, TokenPool_RampUpdate.store); + toCell(self: TokenPool_LocalPolicy): c.Cell { + return makeCellFrom(self, TokenPool_LocalPolicy.store); } } @@ -2934,59 +2861,16 @@ export const TokenPool_ApplyTokenTransferFeeConfigUpdates = { } } -/** - > struct (0xe30764be) TokenPool_UpdateRampAccess { - > queryId: uint64 - > updates: SnakedCell - > } - */ -export interface TokenPool_UpdateRampAccess { - readonly $: 'TokenPool_UpdateRampAccess' - queryId: uint64 - updates: SnakedCell -} - -export const TokenPool_UpdateRampAccess = { - PREFIX: 0xe30764be, - - create(args: { - queryId?: uint64 - updates: SnakedCell - }): TokenPool_UpdateRampAccess { - return { - $: 'TokenPool_UpdateRampAccess', - ...args, - queryId: args.queryId ?? 0n - } - }, - fromSlice(s: c.Slice): TokenPool_UpdateRampAccess { - loadAndCheckPrefix32(s, 0xe30764be, 'TokenPool_UpdateRampAccess'); - return { - $: 'TokenPool_UpdateRampAccess', - queryId: s.loadUintBig(64), - updates: loadSnakedCellOf(s, TokenPool_RampUpdate.fromSlice), - } - }, - store(self: TokenPool_UpdateRampAccess, b: c.Builder): void { - b.storeUint(0xe30764be, 32); - b.storeUint(self.queryId, 64); - storeSnakedCellOf(self.updates, b, TokenPool_RampUpdate.store); - }, - toCell(self: TokenPool_UpdateRampAccess): c.Cell { - return makeCellFrom(self, TokenPool_UpdateRampAccess.store); - } -} - /** > struct (0x9929b642) TokenPool_SetRMNProxy { > queryId: uint64 - > rmnProxy: address + > rmnProxy: address? > } */ export interface TokenPool_SetRMNProxy { readonly $: 'TokenPool_SetRMNProxy' queryId: uint64 - rmnProxy: c.Address + rmnProxy: c.Address | null } export const TokenPool_SetRMNProxy = { @@ -2994,7 +2878,7 @@ export const TokenPool_SetRMNProxy = { create(args: { queryId?: uint64 - rmnProxy: c.Address + rmnProxy: c.Address | null }): TokenPool_SetRMNProxy { return { $: 'TokenPool_SetRMNProxy', @@ -3007,7 +2891,7 @@ export const TokenPool_SetRMNProxy = { return { $: 'TokenPool_SetRMNProxy', queryId: s.loadUintBig(64), - rmnProxy: s.loadAddress(), + rmnProxy: s.loadMaybeAddress(), } }, store(self: TokenPool_SetRMNProxy, b: c.Builder): void { @@ -4288,13 +4172,13 @@ export const TokenPool_RateLimitConfiguredNotification = { /** > struct (0xe5d08b2e) TokenPool_RMNProxySet { > queryId: uint64 - > rmnProxy: address + > rmnProxy: address? > } */ export interface TokenPool_RMNProxySet { readonly $: 'TokenPool_RMNProxySet' queryId: uint64 - rmnProxy: c.Address + rmnProxy: c.Address | null } export const TokenPool_RMNProxySet = { @@ -4302,7 +4186,7 @@ export const TokenPool_RMNProxySet = { create(args: { queryId?: uint64 - rmnProxy: c.Address + rmnProxy: c.Address | null }): TokenPool_RMNProxySet { return { $: 'TokenPool_RMNProxySet', @@ -4315,7 +4199,7 @@ export const TokenPool_RMNProxySet = { return { $: 'TokenPool_RMNProxySet', queryId: s.loadUintBig(64), - rmnProxy: s.loadAddress(), + rmnProxy: s.loadMaybeAddress(), } }, store(self: TokenPool_RMNProxySet, b: c.Builder): void { @@ -4409,44 +4293,6 @@ export const TokenPool_ChainUpdatesApplied = { } } -/** - > struct (0xd7f5c563) TokenPool_RampAccessUpdatesApplied { - > queryId: uint64 - > } - */ -export interface TokenPool_RampAccessUpdatesApplied { - readonly $: 'TokenPool_RampAccessUpdatesApplied' - queryId: uint64 -} - -export const TokenPool_RampAccessUpdatesApplied = { - PREFIX: 0xd7f5c563, - - create(args: { - queryId?: uint64 - }): TokenPool_RampAccessUpdatesApplied { - return { - $: 'TokenPool_RampAccessUpdatesApplied', - ...args, - queryId: args.queryId ?? 0n - } - }, - fromSlice(s: c.Slice): TokenPool_RampAccessUpdatesApplied { - loadAndCheckPrefix32(s, 0xd7f5c563, 'TokenPool_RampAccessUpdatesApplied'); - return { - $: 'TokenPool_RampAccessUpdatesApplied', - queryId: s.loadUintBig(64), - } - }, - store(self: TokenPool_RampAccessUpdatesApplied, b: c.Builder): void { - b.storeUint(0xd7f5c563, 32); - b.storeUint(self.queryId, 64); - }, - toCell(self: TokenPool_RampAccessUpdatesApplied): c.Cell { - return makeCellFrom(self, TokenPool_RampAccessUpdatesApplied.store); - } -} - /** > struct (0x28cbcc64) TokenPool_FeeConfigApplied { > queryId: uint64 @@ -5370,51 +5216,6 @@ export const TokenPool_RateLimitConfigured = { } } -/** - > struct TokenPool_RampAccessUpdated { - > remoteChainSelector: uint64 - > onRamp: address? - > offRamp: address? - > } - */ -export interface TokenPool_RampAccessUpdated { - readonly $: 'TokenPool_RampAccessUpdated' - remoteChainSelector: uint64 - onRamp: c.Address | null /* = null */ - offRamp: c.Address | null /* = null */ -} - -export const TokenPool_RampAccessUpdated = { - create(args: { - remoteChainSelector: uint64 - onRamp?: c.Address | null /* = null */ - offRamp?: c.Address | null /* = null */ - }): TokenPool_RampAccessUpdated { - return { - $: 'TokenPool_RampAccessUpdated', - onRamp: null, - offRamp: null, - ...args - } - }, - fromSlice(s: c.Slice): TokenPool_RampAccessUpdated { - return { - $: 'TokenPool_RampAccessUpdated', - remoteChainSelector: s.loadUintBig(64), - onRamp: s.loadMaybeAddress(), - offRamp: s.loadMaybeAddress(), - } - }, - store(self: TokenPool_RampAccessUpdated, b: c.Builder): void { - b.storeUint(self.remoteChainSelector, 64); - b.storeAddress(self.onRamp); - b.storeAddress(self.offRamp); - }, - toCell(self: TokenPool_RampAccessUpdated): c.Cell { - return makeCellFrom(self, TokenPool_RampAccessUpdated.store); - } -} - /** > struct RateLimiter_Config { > isEnabled: bool @@ -5550,7 +5351,7 @@ function calculateDeployedAddress(code: c.Cell, data: c.Cell, options: DeployedA } export class BurnMintTokenPool implements c.Contract { - static CodeCell = c.Cell.fromBase64('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'); + static CodeCell = c.Cell.fromBase64('te6ccgICAQEAAQAAP0oAAAEU/wD0pBP0vPLICwABAgFiAAIAAwICygAEAAUCASAA1wDYAgEgAAYABwIBSAC3ALgCASAACAAJAgEgAH0AfgIBIAAbABwCASAACgALAgEgAAwADQIBIAASABMCASAADgAPAgEgABAAEQBpCDCTZMwcHHgcXqTIsIAjiAicbDAAZyE/yKpBCG+8oRmqAHeAqsAIMIAlFEgqALeAugwMXCAAjwwI7ORf5UgwADDAOKRMOBTUvgjJ6EQaF40EDdIgFKA8As1UWW5lYE/rfLw4FM0uY4QXwUglYE/rvLw4TCBP67y8OBQNKFQNIABZDAjs5F/lSDAAMMA4pEw4FNS+CMnoRBoXjQQN0iAUoDwCzVQRaBQBbYIREQDgADUII4VNly8lYE/rPLw4FFSqKAUtgj4I1BE4FuACASAAFAAVAgEgABcAGAD1GwzMyDQAsj6UswSzMkB1ywn0+0iJPK/1ws/IdDUMddM0PoAMfoAMIIK+vCA+CjIz5LowKkeUmD6UiXPFMnIz5LowKkeUnD6UhbMycjPkWV8HvIVyz9QA/oCEvpUE/QA9ADJyM+FiBP6UgH6As+Bc/oCcc8LZczJcfsAgAfUggDKBQnDABny9CTQ0/8x10zQyM+Q1H3fjifPCz8WzBTLHxL6VMkByMsfWPoCUAX6AskDyPpSFMwSzMkC+kgw+ChtyEAzgQEL9EEhyPpSEvpS9ADJI8jPks9UjYYUzMnIz4mIAVMkyM+E0MzM+RbPC//PhBBz+gKBAIyAAFgAwzwtrFMzMz5GiQogWyz/0AMmAQPsAgQCHAfcMiFukl8D4CTQNQTU1NMH9AT0BNGCAMn+JdDUMfpQMdQx+kgwGMcFF/L0ggDJ/vgoGccFGPL0A9DXLCXRgVI88r/6SNdM0IIAr8gk0NQx+lAx1DH6SNdM+CjIz4QC+lIS+lLJAcjPhNDMzPkWyM+KAEDL/89QE8cFEvL0gABkDpTtou37INcsJ9PtIiSebCHTP9TTH/QE+lAw8BCPs9csIEeX/byPKNcsJTb9MRyOndcsI5sWhOSOEjHTP/oA+lBVA/GAF4AbgBTbOOMO4w3jDeJ/gAEAAQQBCAfD6SNTXTAHQAdAB1ywn0+0iJPK/0z/U0x8x9AH6UDAB0NP/MdTR0NQx0z/6SDH6ADH6SNEE+gAx+gDU10wGyPpSF/pSIfoCycjPjxgABIIQN91vbs8L93DPC2ETyz8SzMlw+wAhbpJfBeMOAcjMzMsHE/QAEvQAyQEAGgBCBMjME8zJyM+FiBP6UoIQ9DKk488Ljss/zAH6AsmAQPsAAgFIAB0AHgIBWAA9AD4C9z4keMC7UTQ1NTRIdDU1NMH9AT0BNGBAIdtbW1tkvANAG1tbW2S8AwAbYEAiFYTVhP4kviXAxEQAxAvED4QLRA8ECsQOhApEDgQJxA2XiIQI1YY8A8/XwwCjh44OAfDAJE0kzUQNOICyMzMywf0ABL0AMnIzMzJ7VTgXweAAHwAgAak7aLt+9csJ5Db7QyORNcsJ88U8lSUW3DbMeGCAMKKI26z8vQhggDCigTHBRPy9CBtA9cLP4sCAcjLPxX6UhL6UsnIz4cgFM5xzwthE8zJcPsA4w1/gADwEdu1E0NTU0QLXLCf////08r/U0wcx1wofAdDXLCB8U/Us4wLXLCLK+D3k4wLXLCAAAACs4wLXLCNEhRAsACEAIgAjACQDjCLXLCHMTHJs4wLXLCapk7bcjhczAtM/+kj0BfiSEEVVIPAOAcjMzMntVODXLCbQIxhk4wLXLCWn8uBk4wJfA4QPAccA8vQANQA2ADcA+jEh0NTUMdMHMfQEMfQEMdHQ1DH6UDHUMfpI10yCAK/I+JL4KCTIz4QCEvpS+lLJI8jPhNDMzPkWyM+KAEDL/89QxwXy9ALTP/oA+kj6UPQE+gD4KMjPhAL6Uhj6UslQCMjPhNDMzPkWyM+KAEDL/89QB1UF8AYwyMzMye1UAf4x0z8x+gAx+lAx9AWCAK/IIW6z8vTQ1ywl0YFSPPK/+kjXTIIAr8j4klADxwUS8vTQIdBsEtTU0wf0BPQE0QX6SDHU10wh0NcsJ9PtIiTyv9M/10zQ0/8x10zQ0z8x+kj6ADCCEAX14QAp0NQx+lAx1DH6SNdM+CjIz4QC+lISACUB/jGCAK/J+JIj0NTUMdMHMfQEMfQEMdHQ1DH6UDHUMfpIMMcF8vTXTNDXLCC8aijM8r/TPzH6ADH6UDH6UDH6ADH0BCFumDEgxwCSMG3gktHQ4iBus5PIzsmSMG3iggCvySFus/L00NcsJZ6pGwzyv9dM0CHQbBLU1NMH9AT0BNEAKwIa4wLXLCYqO2lc4wLyPwAsAC0D/vpSyQHIz4TQzMz5FsjPigBAy//PUG2LBMjPkD4p+pYXyz9QBPoCUkD6UhT6VBL0AM+EIBPOycjPhQgS+lJY+gJxzwtqzMlz+wAh0NcsJ9PtIiTyv9M/MdTXCx8B0NP/MddM0ALQAtcLPwL6ADH6ADAB4w/Q1ywn0+0iJPK/0z8AJgAnACgC/oIAyfhTJIBA9A5voRLy9NT0BNTU0SDQ1NTRAdDTd9M/0gDTd9N30SKON18GAdDU1NEB0NN30z/SANN303fRL9DUMfpQMdQx+kgwUqDwCgTIy3cTyz/KAMt3y3fJyMzMyQHjDQPIzBL0AMzMVCAlgED0QybQ1DH6UDHUMfpIMAIAKQAqAfqCAMn4UySAQPQOb6ES8vTU9ATU1NEB0NTU0QHQ03fTP9IA03fTd9Ev0NQx+lAx1DH6SDBSoPAKBMjLdxPLP8oAy3fLd8nIzMzJA8jMEvQAEszMVCAlgED0QybQ1DH6UDHUMfpIMALIyz8S+lJQA/oCycjPjxgABIIQMOur2wAzAHrUMdMfMfQB+lAwIG6RW44ayM+FCPpSghA0dupyzwuOyz/Pir8iyYBA+wDiA8jMEszLB/QA9ADJyMzMye1UAFQ2L9DUMfpQMdQx+kgwEEUQNEEwVCag8AoEyMt3E8s/ygDLd8t3ycjMzMkARsjLPxL6UlAD+gLJyM+PGAAEghAUH34szwv3cc8LYczJcPsAAvYF+kgx1NdMIdDXLCGo+78c8r/TPzHU1wsfAdDT/zHXTNAC0AL6SDHXCz8C0x8x+gAwAeMPBMjME8zLB/QAEvQAyQHQ1ywhqPu/HPK/0z/THzH6UDAgbpFbjhrIz4UI+lKCEO8Ms27PC47LP8+KvybJgED7AOLIzMzJ7VQALgAvA/4x0z8x9AWCAK/MIW6z8vTQ1ywlnqkbDPK/1NHQIdBsEtTU0wf0BPQE0QX6SDHU10wh0NcsIaj7vxzyv9M/MdTXCx8B0NP/MddM0ALQAvpIMdcLPwLTHzH6ADAB4w8EyMwTzMsH9AAS9ADJAdDXLCGo+78c8r/TP9MfMfpQMCBuAC4ALwAwAfwi0NTU0wf0BPQE0YEAh21tbW2S8A0AbW1tbZLwDABtgQCIVhURE9M/+kjTP/oA0x/TByHCAfJF9AT6SPQFVhoRGVYaERkhERkhERkhERkRGBEiERgRFxEgERcBERYBERURFBEiERQRExEgERMBERIBEREREBEiERAPESAPUO0ANAL+ggDJ+FMkgED0Dm+hEvL01PQE1NTRINDU1NHQ03fTP9IA03fTd9EijjdfBgHQ1NTR0NN30z/SANN303fRL9DUMfpQMdQx+kgwUqDwCgTIy3cTyz/KAMt3y3fJAcjMzMkB4w0DyMwS9ADMzFQgJYBA9EMm0NQx+lAx1DH6SDACyAAxADIB+oIAyfhTJIBA9A5voRLy9NT0BNTU0QHQ1NTR0NN30z/SANN303fRL9DUMfpQMdQx+kgwUqDwCgTIy3cTyz/KAMt3y3fJAcjMzMkDyMwS9AASzMxUICWAQPRDJtDUMfpQMdQx+kgwAsjLPxL6UlAD+gLJyM+PGAAEghB0Ca2PADMASpFbjhrIz4UI+lKCEO8Ms27PC47LP8+KvzLJgED7AOLIzMzJ7VQAVjYv0NQx+lAx1DH6SDAQRRA0QTBUJqDwCgTIy3cTyz/KAMt3y3fJAcjMzMkARMs/EvpSUAP6AsnIz48YAASCEDR//HzPC/dxzwthzMlw+wAAGM8L93HPC2HMyXD7AABoDBEiDAsRIAtQqQgRIggHESAHUGUEESIEAxEgA1gRIfAoAcjMzBPLBxL0APQAycjMzMntVAD2MwLXCz/4kiLQ1NQx0wcx9AQx9AQx0dDU+lAx1DH6SDHUMdMfMfpQMfQEMdHQ+kj6UDHRAYIAwogCxwXy9IIK+vCAItDU1DHTBzH0BDH0BDHR0NQx+lAx1DH6SDDIz4WI+lIB+gKCEPuI4RnPC4rLP8mAQPsAyMzMye1UAfgzAtM/9AX4koIAr8oibrPy9CHQ1ywlnqkbDPK/1NHQ1DHXTNAi0NcsJZ6pGwzyv9TR0NdM0NcsIaj7vxzyv9dM0NP/MddM0PpIMCXQ1NQx0wcx9AQx9AQx0dDUMfpQMdQx+kgw+ChtyEBEgQEL9EEiyPpSUjD6UvQAyVKAADgC/jMC10z4kgHQ+kj6ADH0BDH6ADHTPzHTHzHU0dDXLCObFoTk8r/TPzH6ADH6UIIAr8sCbhLy9PQEIW6YMSDHAJIwbeCS0dDiIG6zk8jOyZIwbeKCAK/LIW6z8vQg0NcsJZ6pGwzyv9dM0AHQ1ywlnqkbDPK/1NHQ10zQidcn8r8AsAA5AO6CAK/KAsjPhNDMzPkWyM+KAEDL/89QJccF8vQC0x8x+gAwghAF9eEAIG2CCJiWgAjI9ADPUMjPkF41FGYqzws/UAX6AvpUFPpUUAb6As7JyM+FiBP6UlAE+gLPgXP6AoAVzwuFFMs/+lIB+gLMyXH7AMjMzMntVAH+10zQ0/8x10zQ+kgwJNDU1DHTBzH0BDH0BDHR0NQx+lAx1DH6SNdM+ChtyEBVgQEL9EEjyPpSFPpSE/QAySeCAK/LUyHIz4TQzMz5FsjPigBAy//PUBjHBRfy9FAFyM+E0MzM+RbIz4oAQMv/z1DIz4QC+lIU+lLJUAPIz4TQzAA6AfrM+RbIz4oAQMv/z1ABggCvywLHBfL0IdBsEtTU0wf0BPQE0QX6SDHU10wB0NcsIaj7vxzyv9M/1NMfMfpQMAHQ0/8x10zQA9AD+kjTP9P/MfpIMAXTHzH6ADH6ADD4KAPI+lLJBsj6UhP6UiL6AhXMycjPjxgABIIQ6cAMlwA7AJDPC/dwzwthFcs/FMzJcPsAIG6SXwOOHshQA/oCycjPhQgT+lKCEODogvXPC47LP8zJgED7AOIDyMwSzMsH9AD0AMnIzMzJ7VQAZmwS0z/6SDCCAMKIUTTHBRPy9IIAwolTI8cFs/L0IYsCyM+HIM5wzwthEss/EvpSyXD7AAH1FR2VFR2VCZsYfQEIW6YMSDHAJIwbeCS0dDiIG6VMG1tbXCOFdcsIWsLAGSX+kj0BIEAheAwbW1tcOKUIW7DAJF/4pZfA21tbXCOFSHQ1ywgDLUDvDGTgQCF4F8DbW1tcOJsIZNfCXDhCMj6Us+QPin6lhfLP1AF+gITgAD8AVwhbpJbcOCCaQAAAAAAAAAAAAAAAAAAASKDBvQOb6Exklt/4AGDBvQOb6ExgADr6UvpU9AAB+gLOycjPhQgS+lJxzwtuzMmAQPsAfwLs1ywhqPu/HI7r1ywk8VNbNI5gbCHTPzHXTFYV0NQx+lAx1DH6SDHUMdMfMfpQ9AQx0YIAyf4hbrOVA8cFwwCTMTJw4hLy9ND6SNTU0QHQAdAB1ywhqPu/HPK/0z/U0x/6UDAE0x/6APoAMBBWEEUQNPAh4w7jDQBDAEQD+mwh0z8x10xWFdDUMfpQMdQx+kgx1DHTHzH6UPQEMdGCAMn+IW6zlQPHBcMAkzEycOIS8vTQ+kgx1NTRIdDXLCfT7SIk8r/TPzHU1wsfAdDT/zHXTNAC0ALXCz8C+gAx+gAwAeMP0NcsJ9PtIiTyv9M/1DHTHzH0AfpQMCBuAHUAdgB3Af5sIdM/MddMVhXQ1DH6UDHUMfpIMdQx0x8x+lD0BDHRggDJ/iFus5UDxwXDAJMxMnDiEvL00PpI1NTRAdAB0AHXLCfT7SIk8r/TP9TTH/QE+lAwBfoA+gDU10zIz5Pp9pESKM8LPxfMFcsfE/QAUmD6VMnIWPoCWPoCEswSzMnIAHsDeNcsIQ847DyPMdcsJio7aVyOHGwh0z/6SNM/+gDTH9MHIcIB8kX0BPpI9AVt8CKPCdcsJpFKJqzjD+LjDQBFAEYARwAYbCHTP9TTH/pQMPAbAf5sIdM/+kjTP/oA0x/TByHCAfJF9AT0BVYc0NQx+lAx1DH6SDHUMdMf+lAx9AQx0VJA8BWCAMn9Vh3Q1DH6UDHUMfpIMCjHBfL0ggDJ+SZWG4BA9A5voTHy9FYcVhxWHFYcVhxWHFYcVhxWHFYcVhxWHFYcVhxWHFYcVhxWHFYcAEgDKNcsIYMJWLyPCdcsIre56bzjD+MNAEkASgBLA/hsIdM/MddMVhXQ1DH6UDHUMfpIMdQx0x8x+lD0BDHRggDJ/iFus5UDxwXDAJMxMnDiEvL00PpIMdTU0SHQ1ywhqPu/HPK/0z8x1NcLHwHQ0/8x10zQAtAC+kgx1ws/AtMfMfoAMAHjD9DXLCGo+78c8r/TP9MfMfpQMCBuAG8AcABxAFhWHFYZVhlWGVYZ8CQIyMsfF8sfUAX6AlAD+gLLD8sPygAB+gLKAMn4KFnwIgP+bCHTP9TXTFYX0NT6UDHUMfpIMdQx0x8x+lAx9AQx0dD6SPpQMdEkggDCiALHBfL0AdCUIMcAs45AINdLAZEwm4E0vAHAAfL010zQ4tM/UhARFoBA9FuCAMn4AfL0yM+PGAAEghAnkIKLzwv3cM8LYRLLP8lw+wARFOgw0IqK6ABMAE0ATgMo1ywgvhIW5I8J1ywiE1xmJOMP4w0AUgBTAFQD/mwh0z9vAAHTB/QEkyFus44SAdD0BJr6SFBVb4wkxwAV5jAB6DEib4hYuvKJ9AVWF9DUMfpQMdQx+kgx1DHTHzH6UPQEMdGCAMn+IW6zlQXHBcMAkzE0cOIU8vSCAMoGI26z8vQC0PpI9AT0BSBu4w/Iz4UIEvpScc8LbszJgEAAbABtAG4ACCDHALMB/iDXSwGRMJuBNLwBwAHy9NdM0OLTP9TU1IIAyfcj0NMHIcFB8oUBqgLXGNHXScMA8vSCAMn7JVYZgED0Dm+hMbPy9AHQ1NTRbQLQ0gDTd9N30fgjIsjLd8s/E8oAy3fLd8kB0NIA03fTd9H4IyLIy3fLPxPKAMt3y3fJAcjMzMkATwAwMMjPhQgS+lKCEK14M9fPC47LP8mAQPsAAbj4I3DIy3fLP3DPC/DJ+CNwyMt3yz9wzwvwyQHIzMzJJAbQlCDHALOK6DAFyMwS9ADME8xSMhEXgED0Q8jPjxgABIIQ7TfEvM8L93DPC2ETyz8BERUBzMlw+wAREwBQAfog10sBkTCbgTS8AcAB8vTXTNDi0wchwUHyhQGqAtcYyCLXSSCpOALyRasCIMFB8oXPCwcSzsmCAMn3IdDTByHBQfKFAaoC1xjR10nDAPL0IPkAggDJ/1MWgwf0Dm+hMbPy9FRBFoMH9BfIz48YAASCEL8NGrbPC/dwzwthKQBRABLPCz8VzMlw+wAB/Gwh0z/TP9dMVhfQ1PpQMdQx+kgx1DHTHzH6UDH0BDHR0PpI+lAx0SSCAMKIAscF8vSCAMn4IlYWgED0Dm+hMfL0ggDJ+CJWFoBA9A5voRLy9NT0BNTU0ST5AFADgwf0W4IAygAB8vQDyMwT9AASzMxSIhEWgED0Q8jPjxgABABVAurXLCa7iUCEjurXLCHihRzcjl9sIdM/1wsfERbQ1PpQ1PpI1NMfMfpQ9ATRJtD6SPpQMdEpggDCiALHBfL0VhwHyMwW+lQUzBL6UswTyx8S+lT0AMnIz4UIE/pSghBCanE7zwuOyz8BERUByx/JgED7AOMO4w0AVgBXAf5sIdM/0z/XTFYX0NT6UDHUMfpIMdQx0x8x+lAx9AQx0dD6SPpQMdEkggDCiALHBfL0ggDJ+CJWFoBA9A5voTHy9IIAyfgiVhaAQPQOb6ES8vTU9ATU1NGCAMn3JdDTByHBQfKFAaoC1xjR10nDAPL0JPkAggDJ/1MUgwf0Dm+hAGsAcIIQvBTH6M8L93DPC2Eizws/VhXPFMlw+wDIz4UIFPpSghDhe/PMzwuOEss/yz8BERIBzMmAQPsAA/jXLCH65Pq8j3HXLCHDRxhMjlxsIdM/9AURFtDU+lDU+kjU0x/6UPQEMdEm0PpI+lAx0SmCAMKIAscF8vRWHAfIzBb6VBTMEvpSzMsf+lT0AMnIz4UIE/pSghCJ1gLlzwuOyz8BERUB9ADJgED7AI8J1ywkIcIKFOMP4uMNAFgAWQBaAv5sIdM/+kj6UPpQMBEY0NT6UNQx+kjU0x/6UPQE0SbQ+kj6UDHRK4IAwogCxwXy9IIAyfcpjQhgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAExwWz8vSCAMn3Vh9ukX/jDvL0bSnI+lJSkPpUViAB+lT0AMkHyMwWAGkAagD0bCHTP/QFERbQ1PpQ1PpI1NMf+lD0BNEn0PpI+lAx0SqCAMKIAscF8vQF0PpI+lD6UPQEMdECyPpS+lT6VAERHQH0AMkGyMwV+lQVzPpSE8zLHwERFwH6VAERFgH0AMnIz4UIEvpSghDB/+OmzwuOAREVAcs/yYBA+wAC7NcsIn8Wk2SO62wh0z/XTFYW0NT6UDHU+kgx1DHTHzH6UDH0BDHR0PpI+lD6UPQE0QTQ+kj6UDHRkvAlAFQlgOxfJIIAyf4DxwWSMH+U2gHDAOLy9NCUIMcAs4roMMjPhQgS+lKCEN17DHHPC47LP8mAQPsA4w4AWwBcALxsIdM/+lAwERbQ1PpQ1PpI1NMf+lAx9ATRJtD6SPpQMdEpggDCiALHBfL0VhwHyMwW+lQUzBL6UszLHxL6VPQAycjPhQgT+lKCEDyGnYDPC47LPwERFQH6VMmAQPsAAv4g10sBkTCbgTS8AcAB8vTXTNDi0z/SANTUggDJ+CVWGYBA9A5voRLy9NT0BNTU0SeOPwHQ1DHUMdEl0NIA03fTd9H4IyLIy3fLPxPKAMt3y3fJJdDSANN303fR+CMiyMt3yz8TygDLd8t3yQHIzMzJAeMNA8jMEvQAzMxSUhEZAF0AXgMo1ywhhQ6PvI8J1ywkyU2yFOMP4w0AXwBgAGEAetDUMdQx0SXQ0gDTd9N30fgjIsjLd8s/E8oAy3fLd8kl0NIA03fTd9H4IyLIy3fLPxPKAMt3y3fJAcjMzMkASoBA9EPIz48YAASCEP+dv3bPC/dwzwthFcs/E8oAzMzJcPsAERMB/Gwh0z/6UDARFtDU+lAx1PpI1NMf+lD0BNEm0PpI+lAx0SmCAMKIAscF8vSCAMn3Vh1ukX+OK1YdjQhgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAExwWzwwDi8vRWHAfIzBf6VBXME/pSzMsf+lT0AMnIz4UIEwBiAfTXLCTtJtBMjm9sIdM/9AVWFtDU+lDUMfpIMdQx0x8x+lAx9AQx0QHQ+kj6UDHRJIIAyf4CxwWSMX+OECFus5ZSQscFwwCSMXDiwwDi8vQRFdD0BDHRVhTI9ADJyM+FCBP6UoIQFYABYc8Ljss/AREUAfQAyYBA+wDjDgBjAv5sIdM/1NdMVhfQ1PpQMdQx+kgx1DHTHzH6UDH0BDHR0PpI+lAx0SSCAMKIAscF8vQB0JQgxwCziugw0JQgxwCzjjog10sBkTCbgTS8AcAB8vTXTNDi0z9SEBEUgED0WzDIz48YAASCENZGx9HPC/dwzwthEss/yXD7ABES6DDIAGUAZgAw+lKCEOXQiy7PC47LPwERFQH6VMmAQPsAAe7XLCBoBMrkjlQwMVYV0NT6UNT6SNTTH/pQ9ATRB9D6SPpQ0UEKKfABjio4VxwRG8j6Uhb6VMnIzBP6VMz6UhLMAREWAcsf+lQBERQB9ADJERN/2zHgEIlfCccA2zHhMdM/bwAB0wf0BZMgbrOK6DAhb4i68onwJgBkAFrQ9ASOJvpI+gDXLCB8U/Us8r/TP/oA+kj6UPQE+gCLCAxVgG8Jb4wjxwAU5jAB/iDXSwGRMJuBNLwBwAHy9NdM0OLTP9Mf0x/6APoA0w/TD9IAggDJ+ClWHoBA9A5voTHy9IIAyfUi8vSCAMn0JIEnELny9IIAyfQjgScQufL0ggDJ9SjCAPL0J8jLHyfPCx8m+gIl+gIkzwsPI88LDyLPCgBSkhEdgED0QwfIyx8AZwEsic8WEvpSghAoy8xkzwuOyz/JgED7AABoAF4Wyx9QBPoCWPoCyw/LD8oAycjPjxgABIIQ++YfFc8L93DPC2ETyz8SzMlw+wAREwABQgBWVh+NCGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATHBbPDAABu+lQWzBP6UszLHxL6VPQAycjPktzXjDIUyz8S+lL6VAERFgH6VMnIz4UIEvpScc8LbszJgED7AACyMbPy9FRFFIMH9BfIz48YAASCEL8NGrbPC/dwzwthJs8LPyXPFMlw+wADyMwT9AASzMxSIhEWgED0Q8jPhQgU+lKCEBLMSYXPC44Syz/LPwEREgHMyYBA+wAAfjDIz5Gxwst2E8s/I2+Ic21UciGpBo4bAcj0AFMhtghRIqEimVOAb4FY+lIBpOQByQKh5DAxNc8LBxP0APQAyQCCyM+QVjdfVhTLPyRviHNtVHIhqQaOGwHI9ABTIbYIUSKhIplTkG+BWPpSAaTkAckCoeQwMTbPCwcU9AASzBL0AMkABPsAAvyCAMn4IlYVgED0Dm+hEvL01PQE1NTRINDU1NHQ03fTP9IA03fTd9EijjhfBgHQ1NTR0NN30z/SANN303fRVh/Q1DH6UDHUMfpIMFKg8AoEyMt3E8s/ygDLd8t3yQHIzMzJAeMNA8jMEvQAzMxSIhEVgED0Q1YW0NQx+lAx1DEAcgBzAfiCAMn4IlYVgED0Dm+hEvL01PQE1NTRAdDU1NHQ03fTP9IA03fTd9FWH9DUMfpQMdQx+kgwUqDwCgTIy3cTyz/KAMt3y3fJAcjMzMkDyMwS9AASzMxSIhEVgED0Q1YW0NQx+lAx1DH6SDACyMs/EvpSARET+gLJyM+PGAAEAHQAPpFbjhrIz4UI+lKCEO8Ms27PC47LP8+LKBbJgED7AOIAWDZWH9DUMfpQMdQx+kgwEEUQNEEwVCag8AoEyMt3E8s/ygDLd8t3yQHIzMzJAFD6SDACyMs/EvpSARET+gLJyM+PGAAEghA0f/x8zwv3cc8LYczJcPsAACSCEHQJrY/PC/dxzwthzMlw+wAC/oIAyfgiVhWAQPQOb6ES8vTU9ATU1NEg0NTU0QHQ03fTP9IA03fTd9EijjhfBgHQ1NTRAdDTd9M/0gDTd9N30VYf0NQx+lAx1DH6SDBSoPAKBMjLdxPLP8oAy3fLd8nIzMzJAeMNA8jMEvQAzMxSIhEVgED0Q1YW0NQx+lAx1DEAeAB5AfiCAMn4IlYVgED0Dm+hEvL01PQE1NTRAdDU1NEB0NN30z/SANN303fRVh/Q1DH6UDHUMfpIMFKg8AoEyMt3E8s/ygDLd8t3ycjMzMkDyMwS9AASzMxSIhEVgED0Q1YW0NQx+lAx1DH6SDACyMs/EvpSARET+gLJyM+PGAAEAHoAPpFbjhrIz4UI+lKCEDR26nLPC47LP8+LKBbJgED7AOIAVjZWH9DUMfpQMdQx+kgwEEUQNEEwVCag8AoEyMt3E8s/ygDLd8t3ycjMzMkAUPpIMALIyz8S+lIBERP6AsnIz48YAASCEBQffizPC/dxzwthzMlw+wAAJIIQMOur288L93HPC2HMyXD7AAE+ic8WE8s/FPpSE8wSzMnIz4WIEvpScc8LbszJgED7AAB8AAjno1BBAgEgAH8AgAIBIACcAJ0CASAAgQCCAgEgAJEAkgIBIACDAIQCASAAjwCQAfMVhnQ1DH6UDHU+kgx1DHTHzH6UDH0BDHR0PpI+lAx+lAx9AQx0SaCAMn+AscF8vQmwwCVLG6zwwCRcOKOF1cSBxETBwYREgZVBBERK9qCUNyBAIcM4BETERkRExESERgREhERERcREREQERYREA8RFQ8OERQODREZDYACFAfcJsMAlStus8MAkXDijiBXEgcREwcGERIGVQQRESrahwYREgYFEREFgQCHERFVQOAj0NP/1NEg0NM/+kgx+gD6SDCCAMn9Vh/Q1DH6UDHUMfpIMFjHBfL0ggDJ+SJWHIBA9A5voTHy9FYdVh1WHVYdVh1WHVYdVh1WHVYdgAIcB/gwRGAwLERcLChEWCgkRFQkIERQIBxEZBwYRGAYFERcFBBEWBAMRFQMCERQCAREZAREYVhdWF1YXVhdWHVYd8BEEjiRfBFcUVxRXFFcUVxRXFA0REw0MERIMCxERCwoREAoQnxCOVVfgyM+T6faRElYbzws/AREaAcwBERgByx8AhgD4AREcAfQAVhoB+lTJyAERHPoCAREW+gIBERYBzAERFAHMycjPk56NQQYBERYByz8BERYB+lIBERcBzAEREwHMycjPhYgBERUB+lJxzwtuAREUAczJgED7AA0REw0MERIMCxERCwoREAoQnxCOEH0QbBBbEEoQOUgWRVUHAwP+Vh1WHVYdVh1WHVYdVh1WHVYdVh1WFfASVh0CVh0CVh0CVh0CVh0CVh0CVh0CVh0CVh0CVh0CVh0CVh0CVh0CVh0CVh0CVh0CVh0CVh0CVh0CVh0CAREXAREWVhrwE2ahJeMPggDJ+FExgED0Dm+hFPL0AtT0BDHUMdQx0VYayACIAIkAigL+VhzQ1DH6UDHUMfpIMdQx0x/6UDH0BDHRUmDwFYIAyfgjVhuAQPQOb6ES8vTU9ATU1NHQ1NTRAdDTd9M/0gDTd9N30SKOM1Yl0NQx+lAx1DH6SDBSoPAJBMjLdxPLP8oAy3fLd8nIzMzJA8jMEvQAzMxSMhEbgED0Q+MOVhzQ1ACLAIwB9IIAyfgjVhuAQPQOb6ES8vTU9ATU1NEB0NTU0QHQ03fTP9IA03fTd9FWJdDUMfpQMdQx+kgwUqDwCQTIy3cTyz/KAMt3y3fJyMzMyQPIzBL0ABLMzFIyERuAQPRDVhzQ1DH6UDHUMfpIMCPIyz/6UlYa+gLJyM+PGAAEAI0B/Mv/ycjPk+n2kRIpzws/KM8UJ88LH1Jg9ABSUPpUycgk+gJWHPoCI88UIs8UyStWIAlWIAlWIFGQCVYgCVYgCVYgCVYgCVYgCVYgCVYgCVYgCVYgCVYgCVYgCVYgCVYgCVYgCVYgCVYgCQgRIAgHER8HBhEeBgURHQVQQ/AWBACOAfhfCYIAyfgjVhuAQPQOb6ES8vTU9ATU1NEB0NTU0QHQ03fTP9IA03fTd9FWJdDUMfpQMdQx+kgwUqDwCQTIy3cTyz/KAMt3y3fJyMzMyQPIzBL0ABLMzFIyERuAQPRDVhzQ1DH6UDHUMfpIMCPIyz/6UlYa+gLJyM+PGAAEAI0AWDH6UDHUMfpIMCPIyz/6UlYa+gLJyM+PGAAEghDrpIwLzwv3cc8LYczJcPsAACSCEM9QWfzPC/dxzwthzMlw+wAABhEVWQBZFcQVxBfCjY3ggDJ+gbQ9ATRI/AHsxby9ALDAJUibrPDAJFw4pREBNpA4F8FgAHcVxNXEF8PbDPQ0z/6SDH6ADACgED0Dm+h8BQxbDMzApNfBHDhA5EykTDiggDJ9CKBJxC58vSogScQqQSACASAAkwCUAgEgAJUAlgBXJkwbW1tbW1tbXDh0x/TH/oA+gDTD9MP0gDRIJOBAIqaXwdtbW1tbW1tcOKAAKwhkVvhggDKCSGUArrDAJNsIXDi8vSABow4OTk5Ojo6Ojo6Oj09PT0EwwCVKm6zwwCRcOKOEDwQaxBaEEkIEGdGFBAj2rHgNTU1NjYH0NQx+lAx1DH6SDHUMdMfMfpQ9AQx0SBu4wNfCHCAAlwH1CbDAJUpbrPDAJFw4o4YMFcRBhESBgUREQVVAxEQJ9pyUNyBAIcM4IIAyf5WGtDUMfpQMdQx+kjXTPgoyM+EAvpSEvpSyQHIz4TQzMz5FsjPigBAy//PUCfHBfL0VhlWGVYZVhlWGVYZVhlWGVYZVhlWGVYZVhlWGVYZgAJgAliLQ+gAx+gDUMdQx0fgoBcj6UhfME8zJyM+RBKdEJhLLPxfME8sfFPQAWPoCEvpSEvQAycjPhYgS+lLPhBBz+gJxzwtlzMmAQPsAfwFQVhlWGVYZVhlWGVYZVhlWGVYZVhmTW/Aa7eO6gBl/7RGK7UHt8QHy/wCZAu4h9AQhbpgxIMcAkjBt4JLR0OL6SNTU0VYcAVYcAVYcAVYcAVYcAVYcAVYcAVYcAVYcAVYcAVYcAVYcAVYcAVYcAVYcAVYcAVYcAVYcAVYcAVYcAVYcAVYcAVYcAVYcAVYcAREcVhqK7eO6gBt/7RGK7UHt8QHy/wCaAJsAqDEQRxA2RXbwGvgnbxBTAbyRopJbcOL4L6By+wIB0NcsJ9PtIiTyv9M/1DHTHzH0AfpQMCBukl8DjhnIz4UI+lKCEDR26nLPC47LP8sPyYEAgvsA4gDkINDXLCfT7SIk8r/XTNDT/zHXTNDTPzH6SPoAMIIAyghRGLry9IIAygcmbrPy9FYcAVYcAVYcAVYcAVYcAVYcAVYcAVYcAVYcAVYcAVYcAVYcAVYcAVYcAVYcAVYcAVYcAVYcAVYcAVYcAVYZAfAYWPAZAgEgAJ4AnwIBIACoAKkCASAAoAChAgEgAKQApQGTO2i7ftXElcQXw9sIiLQ1DH6UDHU+kgx1DHTHzH6UDH0BDHR0PpI+lAx+lAx9ATRUyHHBZJfBeAggCD0hm+lMpEBiuiCAMn+8vCAAogHzCjDAJUqbrPDAJFw4o4YVxQJERUJCBEUCFUGERNWFdqiUNyBAIcM4GwzMzMC0AHQAdcsJ9PtIiTyv9M/1NMfMfQB+lAwAdDT/zHU0dDUMdM/+kgx+gAx+kjRBPoAMfoA1NdMBsj6Uhf6UiH6AsnIz48YAASCEDfdb26AAowCgUwXQ1DH6UDHUMfpIMdQx0x8x+lAx9ATRggDJ/iFus/L0JMj6UhLLH1Jg+lLJAcjPhNDMzPkWyM+KAEDL/89QJMcFlF8G2zHgIYAg9HxvpTIAcs8L93DPC2ETyz8SzMlw+wAhbpJfBY4hBMjME8zJyM+FiBP6UoIQ9DKk488Ljss/zAH6AsmAQPsA4gCDDAgbpJfBOCCEAX14QBtiwTIz5A+KfqWFss/UAT6AlIg+lIS+lQS9ADPhCASzsnIz4UIE/pSAfoCcc8LaszJc/sAgAfMVhjQ1DH6UDHU+kgx1DHTHzH6UDH0BDHR0PpI+lAx+lAx9AQx0SWCAMn+AscF8vQlwwCVL26zwwCRcOKOFzRXEAUREQUEERAEWlQfDdpiUNyBAIcM4BETERgRExESERcREhERERYREREQERUREA8RFA8OERgODREXDYACmAfQMERYMCxEVCwoRFAoJERgJCBEXCAcRFgcGERUGBREUBQQRGAQDERcDAhEWAgERFQERFFYYVhhWGFYYVhjwHAOOIF8DVxRXFFcUVxRXFA4REw4NERINDBERDAsREAsQr1VJ4BEWERsRFhEVERoRFREUERkRFBETERgREwCnAHIREhEXERIREREWEREREBEVERAPERQPDhETDg0REg0MEREMCxEQCxCvEJ4QjRB8EGsQWhBJEDhY8CECASAAqgCrAgEgALUAtgH1CXDAJUubrPDAJFw4o4gVxEGERIGBRERBVUDERAt2nYFEREFBBEQBIEAhxEQVTDgItDT/zHU1PQE9AQx0QLQ+kgx0z/UMdP/+kjRggDJ/VYe0NQx+lAx1DH6SDBYxwXy9IIAyfkiVhuAQPQOb6Ex8vRWHFYcVhxWHFYcgAKwATxXE1cQXw8zMwKAQPQOb6GSW3Dh1DH0BNQx1DHRAfkAAYMH9A5voTGAB/FYcVhxWHFYcVhxWHFYcVhxWHFYcVhxWHFYcVhxWHFYV8BJWHFYcVhxWHFYcVhxWHFYcVhxWHFYcVhxWHFYcVhxWHFYcVhxWHFYcVhWCAMoAERjwHRPy9FYbAVYbAVYbAVYbAVYbAVYbAVYbAVYbAVYbAVYbAVYbAVYbAVYbAQCtBPxWGwFWGwFWGwFWGwFWGwFWGwFWGwERFvAekvAfABJWHAJWHAJWHAJWHAJWHAJWHAJWHAJWHAJWHAJWHAJWHAJWHAJWHAJWHAJWHAJWHAJWHAJWHAJWHAJWHAKAFn/tEdoBIMEAkX+WIIR3vMMA4paCAMoC8vDgI+MPIlYXyIkArgCvALAAsQL+VhrQ1DH6UDHUMfpIMdQx0x/6UDH0BDHRUkDwFYIAyfgiVhmAQPQOb6ES8vTU9ATU1NHQ1NTR0NN30z/SANN303fRIo40ViPQ1DH6UDHUMfpIMFKg8AkEyMt3E8s/ygDLd8t3yQHIzMzJA8jMEvQAzMxSIhEZgED0Q+MOVhrQ1ACyALMB9oIAyfgiVhmAQPQOb6ES8vTU9ATU1NEB0NTU0dDTd9M/0gDTd9N30VYj0NQx+lAx1DH6SDBSoPAJBMjLdxPLP8oAy3fLd8kByMzMyQPIzBL0ABLMzFIiERmAQPRDVhrQ1DH6UDHUMfpIMALIyz8S+lJWF/oCycjPjxgABAC0AAg1H3fjAPDPFifPCz8mzxQlzwsfUkD6VMkiyMsfIvoCVhr6AskpVh4IVh4IVh5RgAhWHghWHghWHghWHghWHghWHghWHghWHghWHghWHghWHghWHghWHghWHghWHghWHggHER4HBhEdBgURHAUQNBAjAREdAREc8CACERQCQTMB+F8JggDJ+CJWGYBA9A5voRLy9NT0BNTU0QHQ1NTR0NN30z/SANN303fRViPQ1DH6UDHUMfpIMFKg8AkEyMt3E8s/ygDLd8t3yQHIzMzJA8jMEvQAEszMUiIRGYBA9ENWGtDUMfpQMdQx+kgwIsjLP/pSVhj6AsnIz48YAAQAtABaMfpQMdQx+kgwAsjLPxL6UlYX+gLJyM+PGAAEghDLxA5bzwv3cc8LYczJcPsAACSCEIuyX6jPC/dxzwthzMlw+wAAZRXEF8PMWwiIG6RMOAx0IIAygEh10mDB7qXIddKwADDAJFw4vL00//RggDKASGEB7vy9IACFFcQXw8xbCJTIbqSbCHgUyG8ngKi8AiWggDKAvLw4KkE4AKh8AiWggDKAvLw4IIAygIhmYT/IqkEI77DAJF/4vL0qIAIBIAC5ALoCAUgA0gDTAgEgALsAvAIBIADJAMoCASAAvQC+AgEgAMEAwgGdDc4ODg4ODg4OTk5PDw8PALDAJUgbrPDAJFw4p87EFoQSRA4EEdeI1UD2qHgMGwzMwbQ1DH6UDHUMfpIMdQx0x8x+lD0BDHRIG7jA18HcIAC/AekKMMAlS9us8MAkXDijhEKERYKCREVCQgRFAgv2rNO3OAyMwPQ0/8x1NQx9AQx9AQx0dD6SNM/1DHT/zH6SNECyPpSyQLI+lIX+lJQA/oCEszJyM+PGAAEghDpwAyXzwv3cM8LYRXLPxTMyXD7ACJukl8D4w6AAwACKItDTHzH6APoAMdH4KAPI+lIYzBPMycjPkcDwrWIWyz8UzFAF+gLLH/pS9ADJyM+FiBL6Us+EEHP6AnHPC2XMyYBA+wB/ADrIAfoCycjPhYgT+lKCEODogvXPC47LP8zJgED7AAP1DJWHdDUMfpQMdQx+kgx1DHTH/pQMfQEMdFSUPAVggDJ/VYe0NQx+lAx1DH6SDApxwXy9IIAyfknVhyAQPQOb6Ex8vQpVh7Q1DH6UDHUMfpIMdQx0x8x+lD0BDHRIG7jA1tsYm8AIm7jD8jPhQgS+lJxzwtuzMmAQPsAgAMMAxADFAfcIZYw8CQYXwjhNFtWFQFWFQFWFQFWFQFWFQFWFQFWFQFWFQFWFQFWFQFWFQFWFQFWFQFWFQFWFQFWFQFWFQFWFQFWFQFWFQERFfAekvAfAAERFgEBERUBAREUAQEREwEBERIBARERAQEREAEfHh0cGxoZGBcWFRRDMIAWgAMgC/jtWHgFWHgFWHgFWHgFWHgFWHgFWHgFWHgFWHgFWHgFWHgFWHgFWHgFWHgFWHgFWHgFWHgFWHgFWHgFWHgFWGwERG1YaVhpWGvAj+CgHyPpSEvQAEvQAycjPkxUdtK4Zyz8X+lIVyz9QBfoCyx8Tywf0APpS9ADJyM+FiBL6UokAxgDHAHwyyM+RscLLdhPLPyFviHNtVHIhqQaOGwHI9ABTIbYIUSKhIplTYG+BWPpSAaTkAckCoeQwMTPPCwf0APQAyQB+yM+QVjdfVhTLPyNviHNtVHIhqQaOGwHI9ABTIbYIUSKhIplTgG+BWPpSAaTkAckCoeQwMTXPCwcT9ADM9ADJAAEEAB7PFnP6AnHPC2XMyYBA+wAANH/tEdoBIMEAkX+WIIR3vMMA4paCAMoC8vDgAgEgAMsAzAIBIADNAM4AqRsxDQ0NDU1NTWAQPQOb6HwFI4UXwlwVHAAUwAQVhBFEDRDAHBQA3DhKQiSODiOITdUQRiSNybeggDJ9CiBJxC58vRSiKiBJxCpBBihEGcFBuJVJH+AAHQ0WyBus5THBcMAkltw4oAHhCTDAJUlbrPDAJFw4o4WVxAFEREFBBEQBIEAhwQREFYR2nNO3OBsIYIAygRWFtDU10zQAdAB+kj6UPpQ9AWS8CcAUoDsXwH6SDAkxwWSMH+U2gHDAOLy9G2CCJiWgPgvoIAU+wJtcCNviJJcuYroXwaAAzwAfDFsIiFus5THBcMAkltw4oAL+IaRSU2+BbymCANmUJY0IYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABMcFs/L0LG6zjilTTI4h7aLt+3Ahb4iSXLmOECGkUjNvgSTHBZVfBH/bMeDoXwRw2LPDAJFw4paCANmV8vDgcFOcgQEL9ApvoZEw4w0moADQANEACDH6ANEA/MgB+gJUIJ2BAQv0QcjPkAZagd7JL8jPkLWFgDL6UvQAHM7JyPQAz1AlyM+QPin6lhjLP1AH+gIU+lIS+lT0AAH6AhLOycjPhYhSQPpSUAP6As+Bc/oCcc8LZRLMyYAQ+wDIz48YAASCEKqHUCnPC/dwzwthEvpSAfoCyXD7AAIBIADUANUAsUE18DVxNXEF8PMzMD0NQx+lAx1DH6SDHUMdMf+lAx9AQx0VIw8BUBgED0Dm+hlltwVHAAcOHTH9Mf+gD6ANMP0w/SANGXXwdwVHAAcOEGlDAxA3/gMTQDf4AGMUKtfCWzzbDMhbpJfA+AB0PpI9AXIz4UIEvpSghAESdRnzwuOEss/Esof9ADJgED7AIAH3FcTVxBfDzOCAMn4NBKAQPQOb6ET8vQB1DH0BDHU1NECjlcw0NTU0QHQ03fTP9IA03fTd9H4I1AEoSOoFKAjtgj4IwHIy3fLP8oAEst3y3fJAdDTd9M/0gDTd9N30fgjUAShI6gUoCO2CPgjAcjLd8s/ygASy3fLd8ngMYADWAKzQ1NTRAdDTd9M/0gDTd9N30fgjUAShI6gUoCO2CPgjAcjLd8s/ygASy3fLd8kB0NN30z/SANN303fR+CNQBKEjqBSgI7YI+CMByMt3yz/KABLLd8t3yQIBIADZANoCASAA9wD4AgEgANsA3AIBIADrAOwCASAA3QDeAgEgAOcA6AIBIADfAOACASAA4wDkAgFmAOEA4gBFrcj2omhqahjo6GpqGOmDmPoCGPoCGOjoahj9KBjqGP0kGEAAUaBftRNDU1DHRINAx1NQx0wcx9AQx9AQx0dDUMfpQMdQx+kgx1DHXCx+AGmhx7UTQ1NQx0SDQMdQx1DHTBzH0BPQEMdFtIYBA9IZvpTKRAZ1SAm8CURKAQPR8b6Uy6DAxgIBIADlAOYAs63YdqJoampokOhqammD+gJ6AmjAgEO2tra2yXgGgDa2trbJeAYAB4iKB4cIiYcGiIkGhgiIhgWIiAWIZ4hfCFaITghFiD0INIgsCCOIGyKgNqghwIBEAfgJwABsqV+NCpsaW5rLmNoYWluLnRvbi5jY2lwLnBvb2wuQnVybk1pbnRUb2tlblBvb2yCLUwLjEuMIALKq0O1E0NTU0SHQ1NTTB/QE9ATRgQCHbW1tbZLwDQBtbW1tkvAMAA8RFg8OERUODREUDQwREwwLERILEK8QnhCNEHwQaxBaEEkQOEdgbVBlgQCIRRVQRAPwIwIBbgDpAOoArbAfO1E0NTU0SHQ1NTTB/QE9ATRgQCHbW1tbZLwDQBtbW1tkvAMAA8REw8OERIODRERDQwREAwQvxDeEM0QrBCbEIoQeRBoEFcQRhA1RDBtWoEAiALwHYAAtp1HaiaGpqGOjoahjqGOmD+gIY+gIY6MAGaRRBAFfkUBBCB935QkCASAA7QDuAK21L12omhqamiQ6GpqaYP6AnoCaMCAQ7a2trbJeAaANra2tsl4BgAHiImHhwiJBwaIiIaGCIgGCF+IbwhmiFYITYhFCDyINAgriCMIGqIYNq1AgEQBeBTACASAA7wDwAF+ycbtRNDU1DHRINAx1NQx0wcx9AQx9AQx0dDUMfpQMdQx+kgx1DHTHzH6UPQEMdGACASAA8QDyAgFiAPUA9gC4qoftRNDU1NEh0NTU0wf0BPQE0YEAh21tbW2S8A0AbW1tbZLwDAAPERcPDhEWDg0RFQ0MERQMCxETCxERERIREREQEREREAoREAoQnxCOEH0QbFVVbQaBAIgG8CoCASAA8wD0AGemO9qJoamoY6Ohqahjpg5j6Ahj6Ahjo6Gp9KBjqGP0kGOoY6Y+Y/SgY+gIY6Oh9JH0oGOjAAmlCwIDhQBLofu1E0NTUMdEg0DHU1DHTBzH0BDH0BDHR0NQx+lAx1DH6SDDHBYAT6B/tRNDU1DHRINAx1NQx0wcx9AQx9AQx0dDUMddM0PpI+lD6UPQE0YCASAA+QD6AgEgAPsA/ABbtH29qJoamoY6Ohqahjpg5j6Ahj6Ahjo6GoY/ShqGP0kGOoY6Y+Y/SgY+gIY6MAB9t9z9qJoamoY6JBoGOoY6hjpg5j6Ahj6AmjAIHoHN9DHCWmP6Y/9AH0AaYfph+kAaMCARUyYNra2tra2trhxQAJu0jb2omhqahjokGgY6hjqGOmDmPoCegIY6MEAZPwswCB6BzfQiXl6ahj6AmoY6hjotpDBg/pDN9LITwDqaKw3gSiJQYP6PjfS9AgRr4HACASAA/QD+AgFqAP8BAAA9shx7UTQ1NQx0dDUMdQx0wcx9AT0BDHRgED0Dm+hMYABfpV/aiaGpqGOiQaBjqGOoY6YOY+gJ6AhjowQBk/CzAIHoHN9CJeXpqegIY6hjqGOjAD2nA9qJoamoY6OhqGOppg5j6Ahj6Ahjo6HoCaID4A9n'); static Errors = { 'Common_Error.CrossChainAddressOutOfRange': 5, @@ -5792,16 +5593,9 @@ export class BurnMintTokenPool implements c.Contract { return TokenPool_ApplyTokenTransferFeeConfigUpdates.toCell(TokenPool_ApplyTokenTransferFeeConfigUpdates.create(body)); } - static createCellOfTokenPoolUpdateRampAccess(body: { - queryId?: uint64 - updates: SnakedCell - }) { - return TokenPool_UpdateRampAccess.toCell(TokenPool_UpdateRampAccess.create(body)); - } - static createCellOfTokenPoolSetRMNProxy(body: { queryId?: uint64 - rmnProxy: c.Address + rmnProxy: c.Address | null }) { return TokenPool_SetRMNProxy.toCell(TokenPool_SetRMNProxy.create(body)); } @@ -6110,20 +5904,9 @@ export class BurnMintTokenPool implements c.Contract { }); } - async sendTokenPoolUpdateRampAccess(provider: ContractProvider, via: Sender, msgValue: coins, body: { - queryId?: uint64 - updates: SnakedCell - }, extraOptions?: ExtraSendOptions) { - return provider.internal(via, { - value: msgValue, - body: TokenPool_UpdateRampAccess.toCell(TokenPool_UpdateRampAccess.create(body)), - ...extraOptions - }); - } - async sendTokenPoolSetRMNProxy(provider: ContractProvider, via: Sender, msgValue: coins, body: { queryId?: uint64 - rmnProxy: c.Address + rmnProxy: c.Address | null }, extraOptions?: ExtraSendOptions) { return provider.internal(via, { value: msgValue, @@ -6237,29 +6020,13 @@ export class BurnMintTokenPool implements c.Contract { return r.readBoolean(); } - async getOnRamp(provider: ContractProvider, remoteChainSelector: uint64): Promise { - const r = StackReader.fromGetMethod(1, await provider.get('onRamp', [ - { type: 'int', value: remoteChainSelector }, - ])); - return r.readNullable( - (r) => r.readSlice().loadAddress() - ); - } - - async getOffRamp(provider: ContractProvider, remoteChainSelector: uint64): Promise { - const r = StackReader.fromGetMethod(1, await provider.get('offRamp', [ - { type: 'int', value: remoteChainSelector }, - ])); + async getRMNProxy(provider: ContractProvider): Promise { + const r = StackReader.fromGetMethod(1, await provider.get('getRMNProxy', [])); return r.readNullable( (r) => r.readSlice().loadAddress() ); } - async getRMNProxy(provider: ContractProvider): Promise { - const r = StackReader.fromGetMethod(1, await provider.get('getRMNProxy', [])); - return r.readSlice().loadAddress(); - } - async getVerifyNotCursed(provider: ContractProvider, subject: uint128): Promise { const r = StackReader.fromGetMethod(1, await provider.get('verifyNotCursed', [ { type: 'int', value: subject }, diff --git a/contracts/wrappers/gen/ccip/pools/LockReleaseLockboxTokenPool.ts b/contracts/wrappers/gen/ccip/pools/LockReleaseLockboxTokenPool.ts index 43081d5f3..5570a9531 100644 --- a/contracts/wrappers/gen/ccip/pools/LockReleaseLockboxTokenPool.ts +++ b/contracts/wrappers/gen/ccip/pools/LockReleaseLockboxTokenPool.ts @@ -1032,7 +1032,7 @@ export const CursedSubjects = { /** > struct TokenPool_AdminConfig { > ownable: Cell - > rmnProxy: address + > rmnProxy: address? > dynamicConfig: Cell > jettonClient: JettonClient > allowedFinalityConfig: uint32 @@ -1043,7 +1043,7 @@ export const CursedSubjects = { export interface TokenPool_AdminConfig { readonly $: 'TokenPool_AdminConfig' ownable: Ownable2Step - rmnProxy: c.Address + rmnProxy: c.Address | null dynamicConfig: TokenPool_DynamicConfig jettonClient: JettonClient allowedFinalityConfig: uint32 /* = 0 as uint32 */ @@ -1054,7 +1054,7 @@ export interface TokenPool_AdminConfig { export const TokenPool_AdminConfig = { create(args: { ownable: Ownable2Step - rmnProxy: c.Address + rmnProxy: c.Address | null dynamicConfig: TokenPool_DynamicConfig jettonClient: JettonClient allowedFinalityConfig?: uint32 /* = 0 as uint32 */ @@ -1073,7 +1073,7 @@ export const TokenPool_AdminConfig = { return { $: 'TokenPool_AdminConfig', ownable: loadCellRef(s, Ownable2Step.fromSlice), - rmnProxy: s.loadAddress(), + rmnProxy: s.loadMaybeAddress(), dynamicConfig: loadCellRef(s, TokenPool_DynamicConfig.fromSlice), jettonClient: JettonClient.fromSlice(s), allowedFinalityConfig: s.loadUintBig(32), @@ -1100,7 +1100,7 @@ export const TokenPool_AdminConfig = { /** > struct TokenPool_Data { > adminConfig: Cell - > mirroredPolicy: Cell + > localPolicy: Cell > tokenDecimals: uint8 > remoteChainConfigs: map > tokenTransferFeeConfigs: map @@ -1109,7 +1109,7 @@ export const TokenPool_AdminConfig = { export interface TokenPool_Data { readonly $: 'TokenPool_Data' adminConfig: TokenPool_AdminConfig - mirroredPolicy: TokenPool_MirroredPolicy + localPolicy: TokenPool_LocalPolicy tokenDecimals: uint8 remoteChainConfigs: Map /* = [] as map */ tokenTransferFeeConfigs: Map /* = [] as map */ @@ -1118,7 +1118,7 @@ export interface TokenPool_Data { export const TokenPool_Data = { create(args: { adminConfig: TokenPool_AdminConfig - mirroredPolicy: TokenPool_MirroredPolicy + localPolicy: TokenPool_LocalPolicy tokenDecimals: uint8 remoteChainConfigs: Map /* = [] as map */ tokenTransferFeeConfigs: Map /* = [] as map */ @@ -1132,7 +1132,7 @@ export const TokenPool_Data = { return { $: 'TokenPool_Data', adminConfig: loadCellRef(s, TokenPool_AdminConfig.fromSlice), - mirroredPolicy: loadCellRef(s, TokenPool_MirroredPolicy.fromSlice), + localPolicy: loadCellRef(s, TokenPool_LocalPolicy.fromSlice), tokenDecimals: s.loadUintBig(8), remoteChainConfigs: dictToMap(c.Dictionary.load(c.Dictionary.Keys.BigUint(64), createDictionaryValue(TokenPool_RemoteChainConfig.fromSlice, TokenPool_RemoteChainConfig.store), s)), tokenTransferFeeConfigs: dictToMap(c.Dictionary.load(c.Dictionary.Keys.BigUint(64), createDictionaryValue(TokenPool_TokenTransferFeeConfig.fromSlice, TokenPool_TokenTransferFeeConfig.store), s)), @@ -1140,7 +1140,7 @@ export const TokenPool_Data = { }, store(self: TokenPool_Data, b: c.Builder): void { storeCellRef(self.adminConfig, b, TokenPool_AdminConfig.store); - storeCellRef(self.mirroredPolicy, b, TokenPool_MirroredPolicy.store); + storeCellRef(self.localPolicy, b, TokenPool_LocalPolicy.store); b.storeUint(self.tokenDecimals, 8); b.storeDict(mapToDict(self.remoteChainConfigs, c.Dictionary.Keys.BigUint(64), createDictionaryValue(TokenPool_RemoteChainConfig.fromSlice, TokenPool_RemoteChainConfig.store)), c.Dictionary.Keys.BigUint(64), createDictionaryValue(TokenPool_RemoteChainConfig.fromSlice, TokenPool_RemoteChainConfig.store)); b.storeDict(mapToDict(self.tokenTransferFeeConfigs, c.Dictionary.Keys.BigUint(64), createDictionaryValue(TokenPool_TokenTransferFeeConfig.fromSlice, TokenPool_TokenTransferFeeConfig.store)), c.Dictionary.Keys.BigUint(64), createDictionaryValue(TokenPool_TokenTransferFeeConfig.fromSlice, TokenPool_TokenTransferFeeConfig.store)); @@ -1200,108 +1200,35 @@ export const TokenPool_DynamicConfig = { } /** - > struct TokenPool_MirroredPolicy { - > onRamps: map - > offRamps: map + > struct TokenPool_LocalPolicy { > cursedSubjects: CursedSubjects > } */ -export interface TokenPool_MirroredPolicy { - readonly $: 'TokenPool_MirroredPolicy' - onRamps: Map /* = [] as map */ - offRamps: Map /* = [] as map */ +export interface TokenPool_LocalPolicy { + readonly $: 'TokenPool_LocalPolicy' cursedSubjects: CursedSubjects } -export const TokenPool_MirroredPolicy = { +export const TokenPool_LocalPolicy = { create(args: { - onRamps: Map /* = [] as map */ - offRamps: Map /* = [] as map */ cursedSubjects: CursedSubjects - }): TokenPool_MirroredPolicy { + }): TokenPool_LocalPolicy { return { - $: 'TokenPool_MirroredPolicy', + $: 'TokenPool_LocalPolicy', ...args } }, - fromSlice(s: c.Slice): TokenPool_MirroredPolicy { + fromSlice(s: c.Slice): TokenPool_LocalPolicy { return { - $: 'TokenPool_MirroredPolicy', - onRamps: dictToMap(c.Dictionary.load(c.Dictionary.Keys.BigUint(64), createDictionaryValue( - (s) => s.loadAddress(), - (v,b) => b.storeAddress(v) - ), s)), - offRamps: dictToMap(c.Dictionary.load(c.Dictionary.Keys.BigUint(64), createDictionaryValue( - (s) => s.loadAddress(), - (v,b) => b.storeAddress(v) - ), s)), + $: 'TokenPool_LocalPolicy', cursedSubjects: CursedSubjects.fromSlice(s), } }, - store(self: TokenPool_MirroredPolicy, b: c.Builder): void { - b.storeDict(mapToDict(self.onRamps, c.Dictionary.Keys.BigUint(64), createDictionaryValue( - (s) => s.loadAddress(), - (v,b) => b.storeAddress(v) - )), c.Dictionary.Keys.BigUint(64), createDictionaryValue( - (s) => s.loadAddress(), - (v,b) => b.storeAddress(v) - )); - b.storeDict(mapToDict(self.offRamps, c.Dictionary.Keys.BigUint(64), createDictionaryValue( - (s) => s.loadAddress(), - (v,b) => b.storeAddress(v) - )), c.Dictionary.Keys.BigUint(64), createDictionaryValue( - (s) => s.loadAddress(), - (v,b) => b.storeAddress(v) - )); + store(self: TokenPool_LocalPolicy, b: c.Builder): void { CursedSubjects.store(self.cursedSubjects, b); }, - toCell(self: TokenPool_MirroredPolicy): c.Cell { - return makeCellFrom(self, TokenPool_MirroredPolicy.store); - } -} - -/** - > struct TokenPool_RampUpdate { - > remoteChainSelector: uint64 - > onRamp: address? - > offRamp: address? - > } - */ -export interface TokenPool_RampUpdate { - readonly $: 'TokenPool_RampUpdate' - remoteChainSelector: uint64 - onRamp: c.Address | null /* = null */ - offRamp: c.Address | null /* = null */ -} - -export const TokenPool_RampUpdate = { - create(args: { - remoteChainSelector: uint64 - onRamp?: c.Address | null /* = null */ - offRamp?: c.Address | null /* = null */ - }): TokenPool_RampUpdate { - return { - $: 'TokenPool_RampUpdate', - onRamp: null, - offRamp: null, - ...args - } - }, - fromSlice(s: c.Slice): TokenPool_RampUpdate { - return { - $: 'TokenPool_RampUpdate', - remoteChainSelector: s.loadUintBig(64), - onRamp: s.loadMaybeAddress(), - offRamp: s.loadMaybeAddress(), - } - }, - store(self: TokenPool_RampUpdate, b: c.Builder): void { - b.storeUint(self.remoteChainSelector, 64); - b.storeAddress(self.onRamp); - b.storeAddress(self.offRamp); - }, - toCell(self: TokenPool_RampUpdate): c.Cell { - return makeCellFrom(self, TokenPool_RampUpdate.store); + toCell(self: TokenPool_LocalPolicy): c.Cell { + return makeCellFrom(self, TokenPool_LocalPolicy.store); } } @@ -2583,59 +2510,16 @@ export const TokenPool_ApplyTokenTransferFeeConfigUpdates = { } } -/** - > struct (0xe30764be) TokenPool_UpdateRampAccess { - > queryId: uint64 - > updates: SnakedCell - > } - */ -export interface TokenPool_UpdateRampAccess { - readonly $: 'TokenPool_UpdateRampAccess' - queryId: uint64 - updates: SnakedCell -} - -export const TokenPool_UpdateRampAccess = { - PREFIX: 0xe30764be, - - create(args: { - queryId?: uint64 - updates: SnakedCell - }): TokenPool_UpdateRampAccess { - return { - $: 'TokenPool_UpdateRampAccess', - ...args, - queryId: args.queryId ?? 0n - } - }, - fromSlice(s: c.Slice): TokenPool_UpdateRampAccess { - loadAndCheckPrefix32(s, 0xe30764be, 'TokenPool_UpdateRampAccess'); - return { - $: 'TokenPool_UpdateRampAccess', - queryId: s.loadUintBig(64), - updates: loadSnakedCellOf(s, TokenPool_RampUpdate.fromSlice), - } - }, - store(self: TokenPool_UpdateRampAccess, b: c.Builder): void { - b.storeUint(0xe30764be, 32); - b.storeUint(self.queryId, 64); - storeSnakedCellOf(self.updates, b, TokenPool_RampUpdate.store); - }, - toCell(self: TokenPool_UpdateRampAccess): c.Cell { - return makeCellFrom(self, TokenPool_UpdateRampAccess.store); - } -} - /** > struct (0x9929b642) TokenPool_SetRMNProxy { > queryId: uint64 - > rmnProxy: address + > rmnProxy: address? > } */ export interface TokenPool_SetRMNProxy { readonly $: 'TokenPool_SetRMNProxy' queryId: uint64 - rmnProxy: c.Address + rmnProxy: c.Address | null } export const TokenPool_SetRMNProxy = { @@ -2643,7 +2527,7 @@ export const TokenPool_SetRMNProxy = { create(args: { queryId?: uint64 - rmnProxy: c.Address + rmnProxy: c.Address | null }): TokenPool_SetRMNProxy { return { $: 'TokenPool_SetRMNProxy', @@ -2656,7 +2540,7 @@ export const TokenPool_SetRMNProxy = { return { $: 'TokenPool_SetRMNProxy', queryId: s.loadUintBig(64), - rmnProxy: s.loadAddress(), + rmnProxy: s.loadMaybeAddress(), } }, store(self: TokenPool_SetRMNProxy, b: c.Builder): void { @@ -3937,13 +3821,13 @@ export const TokenPool_RateLimitConfiguredNotification = { /** > struct (0xe5d08b2e) TokenPool_RMNProxySet { > queryId: uint64 - > rmnProxy: address + > rmnProxy: address? > } */ export interface TokenPool_RMNProxySet { readonly $: 'TokenPool_RMNProxySet' queryId: uint64 - rmnProxy: c.Address + rmnProxy: c.Address | null } export const TokenPool_RMNProxySet = { @@ -3951,7 +3835,7 @@ export const TokenPool_RMNProxySet = { create(args: { queryId?: uint64 - rmnProxy: c.Address + rmnProxy: c.Address | null }): TokenPool_RMNProxySet { return { $: 'TokenPool_RMNProxySet', @@ -3964,7 +3848,7 @@ export const TokenPool_RMNProxySet = { return { $: 'TokenPool_RMNProxySet', queryId: s.loadUintBig(64), - rmnProxy: s.loadAddress(), + rmnProxy: s.loadMaybeAddress(), } }, store(self: TokenPool_RMNProxySet, b: c.Builder): void { @@ -4058,44 +3942,6 @@ export const TokenPool_ChainUpdatesApplied = { } } -/** - > struct (0xd7f5c563) TokenPool_RampAccessUpdatesApplied { - > queryId: uint64 - > } - */ -export interface TokenPool_RampAccessUpdatesApplied { - readonly $: 'TokenPool_RampAccessUpdatesApplied' - queryId: uint64 -} - -export const TokenPool_RampAccessUpdatesApplied = { - PREFIX: 0xd7f5c563, - - create(args: { - queryId?: uint64 - }): TokenPool_RampAccessUpdatesApplied { - return { - $: 'TokenPool_RampAccessUpdatesApplied', - ...args, - queryId: args.queryId ?? 0n - } - }, - fromSlice(s: c.Slice): TokenPool_RampAccessUpdatesApplied { - loadAndCheckPrefix32(s, 0xd7f5c563, 'TokenPool_RampAccessUpdatesApplied'); - return { - $: 'TokenPool_RampAccessUpdatesApplied', - queryId: s.loadUintBig(64), - } - }, - store(self: TokenPool_RampAccessUpdatesApplied, b: c.Builder): void { - b.storeUint(0xd7f5c563, 32); - b.storeUint(self.queryId, 64); - }, - toCell(self: TokenPool_RampAccessUpdatesApplied): c.Cell { - return makeCellFrom(self, TokenPool_RampAccessUpdatesApplied.store); - } -} - /** > struct (0x28cbcc64) TokenPool_FeeConfigApplied { > queryId: uint64 @@ -5345,51 +5191,6 @@ export const TokenPool_RateLimitConfigured = { } } -/** - > struct TokenPool_RampAccessUpdated { - > remoteChainSelector: uint64 - > onRamp: address? - > offRamp: address? - > } - */ -export interface TokenPool_RampAccessUpdated { - readonly $: 'TokenPool_RampAccessUpdated' - remoteChainSelector: uint64 - onRamp: c.Address | null /* = null */ - offRamp: c.Address | null /* = null */ -} - -export const TokenPool_RampAccessUpdated = { - create(args: { - remoteChainSelector: uint64 - onRamp?: c.Address | null /* = null */ - offRamp?: c.Address | null /* = null */ - }): TokenPool_RampAccessUpdated { - return { - $: 'TokenPool_RampAccessUpdated', - onRamp: null, - offRamp: null, - ...args - } - }, - fromSlice(s: c.Slice): TokenPool_RampAccessUpdated { - return { - $: 'TokenPool_RampAccessUpdated', - remoteChainSelector: s.loadUintBig(64), - onRamp: s.loadMaybeAddress(), - offRamp: s.loadMaybeAddress(), - } - }, - store(self: TokenPool_RampAccessUpdated, b: c.Builder): void { - b.storeUint(self.remoteChainSelector, 64); - b.storeAddress(self.onRamp); - b.storeAddress(self.offRamp); - }, - toCell(self: TokenPool_RampAccessUpdated): c.Cell { - return makeCellFrom(self, TokenPool_RampAccessUpdated.store); - } -} - /** > struct RateLimiter_Config { > isEnabled: bool @@ -5525,7 +5326,7 @@ function calculateDeployedAddress(code: c.Cell, data: c.Cell, options: DeployedA } export class LockReleaseLockboxTokenPool implements c.Contract { - static CodeCell = c.Cell.fromBase64('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93HPC2HMyXD7AAAkghAw66vbzwv3cc8LYczJcPsAAgEgAH8AgAIBIACZAJoCASAAgQCCAgEgAJIAkwIBIACDAIQCASAAkACRAfEJsMAlSxus8MAkXDijh9XFAgRFggHERUHBhEUBlUEERMr2pMCERACUP6BAIcO4BEWERwRFhEVERsRFREUERoRFBETERkRExESERgREhERERcREREQERwREA8RGw8OERoODREZDQwRGAwLERcLChEcCgkRGwkIERoIgAIUB9wmwwCVK26zwwCRcOKOKFcUCBEWCAcRFQcGERQGVQQREyramAcRFQcGERQGBRETBYEAhxETVUDgI9DT/9TRINDTP/pIMfoA+kgwggDJ/VYi0NQx+kgx1DH6SDBYxwXy9IIAyfkiVh+AQPQOb6Ex8vRWIFYgViBWIFYgViCAAiAH+BxEZBwYRGAYFERcFBBEcBAMRGwMCERoCAREZAREYVhdWHVYdVh1WHVYd8BEEjjhfBFcXVxdXF1cXVxdXFxEQERYREA8RFQ8OERQODRETDQwREgwLERELChEQChCfEI4QfRBsVVVVBODIz5Pp9pESViHPCz8BESABzAERHgHLHwCGAfwBERwB9ABWGgH6VMnIAREc+gIBERz6AgERHAHMAREaAczJyM+Tno1BBgERHAHLPwERFgH6UgERFwHMAREZAczJyM+FiAERFQH6UnHPC24BERQBzMmAQPsAERARFhEQDxEVDw4RFA4NERMNDBESDAsREQsKERAKEJ8QjhB9EGwAhwAYEFsQShA5SBZFVQcDAfxWIFYgViBWIFYgViBWIFYgViBWIFYgViBWIFYgViBWIFYgVhjwElYgViBWIFYgViBWIFYgViBWIFYgViBWIFYgViBWIFYgViBWIFYgViBWIFYgViBWIFYZ8BNWIAJWIAJWIAJWIAJWIAJWIAJWIAJWIAJWIAJWIAJWIAJWIAIAiQP8ViACViACViACViACViACViACViACViACViACViACViACAREaAREZVh3wFFEioSXjD4IAyfhRIYBA9A5voRPy9AHU9AQx1DHUMdFWHcjL/8nIz5Pp9pESKc8LPyjPFCfPCx9SYPQAUlD6VMnIJfoCVh/6AiPPFCLPFMkrViMJAIoAiwCMAv5WH9DUMfpIMdQx+kgx1DHTH/pQMfQEMdFSYPAWggDJ+CJW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'); + static CodeCell = c.Cell.fromBase64('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'); static Errors = { 'Common_Error.CrossChainAddressOutOfRange': 5, @@ -5769,16 +5570,9 @@ export class LockReleaseLockboxTokenPool implements c.Contract { return TokenPool_ApplyTokenTransferFeeConfigUpdates.toCell(TokenPool_ApplyTokenTransferFeeConfigUpdates.create(body)); } - static createCellOfTokenPoolUpdateRampAccess(body: { - queryId?: uint64 - updates: SnakedCell - }) { - return TokenPool_UpdateRampAccess.toCell(TokenPool_UpdateRampAccess.create(body)); - } - static createCellOfTokenPoolSetRMNProxy(body: { queryId?: uint64 - rmnProxy: c.Address + rmnProxy: c.Address | null }) { return TokenPool_SetRMNProxy.toCell(TokenPool_SetRMNProxy.create(body)); } @@ -6099,20 +5893,9 @@ export class LockReleaseLockboxTokenPool implements c.Contract { }); } - async sendTokenPoolUpdateRampAccess(provider: ContractProvider, via: Sender, msgValue: coins, body: { - queryId?: uint64 - updates: SnakedCell - }, extraOptions?: ExtraSendOptions) { - return provider.internal(via, { - value: msgValue, - body: TokenPool_UpdateRampAccess.toCell(TokenPool_UpdateRampAccess.create(body)), - ...extraOptions - }); - } - async sendTokenPoolSetRMNProxy(provider: ContractProvider, via: Sender, msgValue: coins, body: { queryId?: uint64 - rmnProxy: c.Address + rmnProxy: c.Address | null }, extraOptions?: ExtraSendOptions) { return provider.internal(via, { value: msgValue, @@ -6247,29 +6030,13 @@ export class LockReleaseLockboxTokenPool implements c.Contract { return r.readBoolean(); } - async getOnRamp(provider: ContractProvider, remoteChainSelector: uint64): Promise { - const r = StackReader.fromGetMethod(1, await provider.get('onRamp', [ - { type: 'int', value: remoteChainSelector }, - ])); - return r.readNullable( - (r) => r.readSlice().loadAddress() - ); - } - - async getOffRamp(provider: ContractProvider, remoteChainSelector: uint64): Promise { - const r = StackReader.fromGetMethod(1, await provider.get('offRamp', [ - { type: 'int', value: remoteChainSelector }, - ])); + async getRMNProxy(provider: ContractProvider): Promise { + const r = StackReader.fromGetMethod(1, await provider.get('getRMNProxy', [])); return r.readNullable( (r) => r.readSlice().loadAddress() ); } - async getRMNProxy(provider: ContractProvider): Promise { - const r = StackReader.fromGetMethod(1, await provider.get('getRMNProxy', [])); - return r.readSlice().loadAddress(); - } - async getVerifyNotCursed(provider: ContractProvider, subject: uint128): Promise { const r = StackReader.fromGetMethod(1, await provider.get('verifyNotCursed', [ { type: 'int', value: subject }, diff --git a/contracts/wrappers/gen/ccip/pools/LockReleaseTokenPool.ts b/contracts/wrappers/gen/ccip/pools/LockReleaseTokenPool.ts index be09cdc0b..7db331372 100644 --- a/contracts/wrappers/gen/ccip/pools/LockReleaseTokenPool.ts +++ b/contracts/wrappers/gen/ccip/pools/LockReleaseTokenPool.ts @@ -1154,7 +1154,7 @@ export const CursedSubjects = { /** > struct TokenPool_AdminConfig { > ownable: Cell - > rmnProxy: address + > rmnProxy: address? > dynamicConfig: Cell > jettonClient: JettonClient > allowedFinalityConfig: uint32 @@ -1165,7 +1165,7 @@ export const CursedSubjects = { export interface TokenPool_AdminConfig { readonly $: 'TokenPool_AdminConfig' ownable: Ownable2Step - rmnProxy: c.Address + rmnProxy: c.Address | null dynamicConfig: TokenPool_DynamicConfig jettonClient: JettonClient allowedFinalityConfig: uint32 /* = 0 as uint32 */ @@ -1176,7 +1176,7 @@ export interface TokenPool_AdminConfig { export const TokenPool_AdminConfig = { create(args: { ownable: Ownable2Step - rmnProxy: c.Address + rmnProxy: c.Address | null dynamicConfig: TokenPool_DynamicConfig jettonClient: JettonClient allowedFinalityConfig?: uint32 /* = 0 as uint32 */ @@ -1195,7 +1195,7 @@ export const TokenPool_AdminConfig = { return { $: 'TokenPool_AdminConfig', ownable: loadCellRef(s, Ownable2Step.fromSlice), - rmnProxy: s.loadAddress(), + rmnProxy: s.loadMaybeAddress(), dynamicConfig: loadCellRef(s, TokenPool_DynamicConfig.fromSlice), jettonClient: JettonClient.fromSlice(s), allowedFinalityConfig: s.loadUintBig(32), @@ -1222,7 +1222,7 @@ export const TokenPool_AdminConfig = { /** > struct TokenPool_Data { > adminConfig: Cell - > mirroredPolicy: Cell + > localPolicy: Cell > tokenDecimals: uint8 > remoteChainConfigs: map > tokenTransferFeeConfigs: map @@ -1231,7 +1231,7 @@ export const TokenPool_AdminConfig = { export interface TokenPool_Data { readonly $: 'TokenPool_Data' adminConfig: TokenPool_AdminConfig - mirroredPolicy: TokenPool_MirroredPolicy + localPolicy: TokenPool_LocalPolicy tokenDecimals: uint8 remoteChainConfigs: Map /* = [] as map */ tokenTransferFeeConfigs: Map /* = [] as map */ @@ -1240,7 +1240,7 @@ export interface TokenPool_Data { export const TokenPool_Data = { create(args: { adminConfig: TokenPool_AdminConfig - mirroredPolicy: TokenPool_MirroredPolicy + localPolicy: TokenPool_LocalPolicy tokenDecimals: uint8 remoteChainConfigs: Map /* = [] as map */ tokenTransferFeeConfigs: Map /* = [] as map */ @@ -1254,7 +1254,7 @@ export const TokenPool_Data = { return { $: 'TokenPool_Data', adminConfig: loadCellRef(s, TokenPool_AdminConfig.fromSlice), - mirroredPolicy: loadCellRef(s, TokenPool_MirroredPolicy.fromSlice), + localPolicy: loadCellRef(s, TokenPool_LocalPolicy.fromSlice), tokenDecimals: s.loadUintBig(8), remoteChainConfigs: dictToMap(c.Dictionary.load(c.Dictionary.Keys.BigUint(64), createDictionaryValue(TokenPool_RemoteChainConfig.fromSlice, TokenPool_RemoteChainConfig.store), s)), tokenTransferFeeConfigs: dictToMap(c.Dictionary.load(c.Dictionary.Keys.BigUint(64), createDictionaryValue(TokenPool_TokenTransferFeeConfig.fromSlice, TokenPool_TokenTransferFeeConfig.store), s)), @@ -1262,7 +1262,7 @@ export const TokenPool_Data = { }, store(self: TokenPool_Data, b: c.Builder): void { storeCellRef(self.adminConfig, b, TokenPool_AdminConfig.store); - storeCellRef(self.mirroredPolicy, b, TokenPool_MirroredPolicy.store); + storeCellRef(self.localPolicy, b, TokenPool_LocalPolicy.store); b.storeUint(self.tokenDecimals, 8); b.storeDict(mapToDict(self.remoteChainConfigs, c.Dictionary.Keys.BigUint(64), createDictionaryValue(TokenPool_RemoteChainConfig.fromSlice, TokenPool_RemoteChainConfig.store)), c.Dictionary.Keys.BigUint(64), createDictionaryValue(TokenPool_RemoteChainConfig.fromSlice, TokenPool_RemoteChainConfig.store)); b.storeDict(mapToDict(self.tokenTransferFeeConfigs, c.Dictionary.Keys.BigUint(64), createDictionaryValue(TokenPool_TokenTransferFeeConfig.fromSlice, TokenPool_TokenTransferFeeConfig.store)), c.Dictionary.Keys.BigUint(64), createDictionaryValue(TokenPool_TokenTransferFeeConfig.fromSlice, TokenPool_TokenTransferFeeConfig.store)); @@ -1322,108 +1322,35 @@ export const TokenPool_DynamicConfig = { } /** - > struct TokenPool_MirroredPolicy { - > onRamps: map - > offRamps: map + > struct TokenPool_LocalPolicy { > cursedSubjects: CursedSubjects > } */ -export interface TokenPool_MirroredPolicy { - readonly $: 'TokenPool_MirroredPolicy' - onRamps: Map /* = [] as map */ - offRamps: Map /* = [] as map */ +export interface TokenPool_LocalPolicy { + readonly $: 'TokenPool_LocalPolicy' cursedSubjects: CursedSubjects } -export const TokenPool_MirroredPolicy = { +export const TokenPool_LocalPolicy = { create(args: { - onRamps: Map /* = [] as map */ - offRamps: Map /* = [] as map */ cursedSubjects: CursedSubjects - }): TokenPool_MirroredPolicy { + }): TokenPool_LocalPolicy { return { - $: 'TokenPool_MirroredPolicy', + $: 'TokenPool_LocalPolicy', ...args } }, - fromSlice(s: c.Slice): TokenPool_MirroredPolicy { + fromSlice(s: c.Slice): TokenPool_LocalPolicy { return { - $: 'TokenPool_MirroredPolicy', - onRamps: dictToMap(c.Dictionary.load(c.Dictionary.Keys.BigUint(64), createDictionaryValue( - (s) => s.loadAddress(), - (v,b) => b.storeAddress(v) - ), s)), - offRamps: dictToMap(c.Dictionary.load(c.Dictionary.Keys.BigUint(64), createDictionaryValue( - (s) => s.loadAddress(), - (v,b) => b.storeAddress(v) - ), s)), + $: 'TokenPool_LocalPolicy', cursedSubjects: CursedSubjects.fromSlice(s), } }, - store(self: TokenPool_MirroredPolicy, b: c.Builder): void { - b.storeDict(mapToDict(self.onRamps, c.Dictionary.Keys.BigUint(64), createDictionaryValue( - (s) => s.loadAddress(), - (v,b) => b.storeAddress(v) - )), c.Dictionary.Keys.BigUint(64), createDictionaryValue( - (s) => s.loadAddress(), - (v,b) => b.storeAddress(v) - )); - b.storeDict(mapToDict(self.offRamps, c.Dictionary.Keys.BigUint(64), createDictionaryValue( - (s) => s.loadAddress(), - (v,b) => b.storeAddress(v) - )), c.Dictionary.Keys.BigUint(64), createDictionaryValue( - (s) => s.loadAddress(), - (v,b) => b.storeAddress(v) - )); + store(self: TokenPool_LocalPolicy, b: c.Builder): void { CursedSubjects.store(self.cursedSubjects, b); }, - toCell(self: TokenPool_MirroredPolicy): c.Cell { - return makeCellFrom(self, TokenPool_MirroredPolicy.store); - } -} - -/** - > struct TokenPool_RampUpdate { - > remoteChainSelector: uint64 - > onRamp: address? - > offRamp: address? - > } - */ -export interface TokenPool_RampUpdate { - readonly $: 'TokenPool_RampUpdate' - remoteChainSelector: uint64 - onRamp: c.Address | null /* = null */ - offRamp: c.Address | null /* = null */ -} - -export const TokenPool_RampUpdate = { - create(args: { - remoteChainSelector: uint64 - onRamp?: c.Address | null /* = null */ - offRamp?: c.Address | null /* = null */ - }): TokenPool_RampUpdate { - return { - $: 'TokenPool_RampUpdate', - onRamp: null, - offRamp: null, - ...args - } - }, - fromSlice(s: c.Slice): TokenPool_RampUpdate { - return { - $: 'TokenPool_RampUpdate', - remoteChainSelector: s.loadUintBig(64), - onRamp: s.loadMaybeAddress(), - offRamp: s.loadMaybeAddress(), - } - }, - store(self: TokenPool_RampUpdate, b: c.Builder): void { - b.storeUint(self.remoteChainSelector, 64); - b.storeAddress(self.onRamp); - b.storeAddress(self.offRamp); - }, - toCell(self: TokenPool_RampUpdate): c.Cell { - return makeCellFrom(self, TokenPool_RampUpdate.store); + toCell(self: TokenPool_LocalPolicy): c.Cell { + return makeCellFrom(self, TokenPool_LocalPolicy.store); } } @@ -2705,59 +2632,16 @@ export const TokenPool_ApplyTokenTransferFeeConfigUpdates = { } } -/** - > struct (0xe30764be) TokenPool_UpdateRampAccess { - > queryId: uint64 - > updates: SnakedCell - > } - */ -export interface TokenPool_UpdateRampAccess { - readonly $: 'TokenPool_UpdateRampAccess' - queryId: uint64 - updates: SnakedCell -} - -export const TokenPool_UpdateRampAccess = { - PREFIX: 0xe30764be, - - create(args: { - queryId?: uint64 - updates: SnakedCell - }): TokenPool_UpdateRampAccess { - return { - $: 'TokenPool_UpdateRampAccess', - ...args, - queryId: args.queryId ?? 0n - } - }, - fromSlice(s: c.Slice): TokenPool_UpdateRampAccess { - loadAndCheckPrefix32(s, 0xe30764be, 'TokenPool_UpdateRampAccess'); - return { - $: 'TokenPool_UpdateRampAccess', - queryId: s.loadUintBig(64), - updates: loadSnakedCellOf(s, TokenPool_RampUpdate.fromSlice), - } - }, - store(self: TokenPool_UpdateRampAccess, b: c.Builder): void { - b.storeUint(0xe30764be, 32); - b.storeUint(self.queryId, 64); - storeSnakedCellOf(self.updates, b, TokenPool_RampUpdate.store); - }, - toCell(self: TokenPool_UpdateRampAccess): c.Cell { - return makeCellFrom(self, TokenPool_UpdateRampAccess.store); - } -} - /** > struct (0x9929b642) TokenPool_SetRMNProxy { > queryId: uint64 - > rmnProxy: address + > rmnProxy: address? > } */ export interface TokenPool_SetRMNProxy { readonly $: 'TokenPool_SetRMNProxy' queryId: uint64 - rmnProxy: c.Address + rmnProxy: c.Address | null } export const TokenPool_SetRMNProxy = { @@ -2765,7 +2649,7 @@ export const TokenPool_SetRMNProxy = { create(args: { queryId?: uint64 - rmnProxy: c.Address + rmnProxy: c.Address | null }): TokenPool_SetRMNProxy { return { $: 'TokenPool_SetRMNProxy', @@ -2778,7 +2662,7 @@ export const TokenPool_SetRMNProxy = { return { $: 'TokenPool_SetRMNProxy', queryId: s.loadUintBig(64), - rmnProxy: s.loadAddress(), + rmnProxy: s.loadMaybeAddress(), } }, store(self: TokenPool_SetRMNProxy, b: c.Builder): void { @@ -4059,13 +3943,13 @@ export const TokenPool_RateLimitConfiguredNotification = { /** > struct (0xe5d08b2e) TokenPool_RMNProxySet { > queryId: uint64 - > rmnProxy: address + > rmnProxy: address? > } */ export interface TokenPool_RMNProxySet { readonly $: 'TokenPool_RMNProxySet' queryId: uint64 - rmnProxy: c.Address + rmnProxy: c.Address | null } export const TokenPool_RMNProxySet = { @@ -4073,7 +3957,7 @@ export const TokenPool_RMNProxySet = { create(args: { queryId?: uint64 - rmnProxy: c.Address + rmnProxy: c.Address | null }): TokenPool_RMNProxySet { return { $: 'TokenPool_RMNProxySet', @@ -4086,7 +3970,7 @@ export const TokenPool_RMNProxySet = { return { $: 'TokenPool_RMNProxySet', queryId: s.loadUintBig(64), - rmnProxy: s.loadAddress(), + rmnProxy: s.loadMaybeAddress(), } }, store(self: TokenPool_RMNProxySet, b: c.Builder): void { @@ -4180,44 +4064,6 @@ export const TokenPool_ChainUpdatesApplied = { } } -/** - > struct (0xd7f5c563) TokenPool_RampAccessUpdatesApplied { - > queryId: uint64 - > } - */ -export interface TokenPool_RampAccessUpdatesApplied { - readonly $: 'TokenPool_RampAccessUpdatesApplied' - queryId: uint64 -} - -export const TokenPool_RampAccessUpdatesApplied = { - PREFIX: 0xd7f5c563, - - create(args: { - queryId?: uint64 - }): TokenPool_RampAccessUpdatesApplied { - return { - $: 'TokenPool_RampAccessUpdatesApplied', - ...args, - queryId: args.queryId ?? 0n - } - }, - fromSlice(s: c.Slice): TokenPool_RampAccessUpdatesApplied { - loadAndCheckPrefix32(s, 0xd7f5c563, 'TokenPool_RampAccessUpdatesApplied'); - return { - $: 'TokenPool_RampAccessUpdatesApplied', - queryId: s.loadUintBig(64), - } - }, - store(self: TokenPool_RampAccessUpdatesApplied, b: c.Builder): void { - b.storeUint(0xd7f5c563, 32); - b.storeUint(self.queryId, 64); - }, - toCell(self: TokenPool_RampAccessUpdatesApplied): c.Cell { - return makeCellFrom(self, TokenPool_RampAccessUpdatesApplied.store); - } -} - /** > struct (0x28cbcc64) TokenPool_FeeConfigApplied { > queryId: uint64 @@ -5065,51 +4911,6 @@ export const TokenPool_RateLimitConfigured = { } } -/** - > struct TokenPool_RampAccessUpdated { - > remoteChainSelector: uint64 - > onRamp: address? - > offRamp: address? - > } - */ -export interface TokenPool_RampAccessUpdated { - readonly $: 'TokenPool_RampAccessUpdated' - remoteChainSelector: uint64 - onRamp: c.Address | null /* = null */ - offRamp: c.Address | null /* = null */ -} - -export const TokenPool_RampAccessUpdated = { - create(args: { - remoteChainSelector: uint64 - onRamp?: c.Address | null /* = null */ - offRamp?: c.Address | null /* = null */ - }): TokenPool_RampAccessUpdated { - return { - $: 'TokenPool_RampAccessUpdated', - onRamp: null, - offRamp: null, - ...args - } - }, - fromSlice(s: c.Slice): TokenPool_RampAccessUpdated { - return { - $: 'TokenPool_RampAccessUpdated', - remoteChainSelector: s.loadUintBig(64), - onRamp: s.loadMaybeAddress(), - offRamp: s.loadMaybeAddress(), - } - }, - store(self: TokenPool_RampAccessUpdated, b: c.Builder): void { - b.storeUint(self.remoteChainSelector, 64); - b.storeAddress(self.onRamp); - b.storeAddress(self.offRamp); - }, - toCell(self: TokenPool_RampAccessUpdated): c.Cell { - return makeCellFrom(self, TokenPool_RampAccessUpdated.store); - } -} - /** > struct Storage { > poolData: Cell @@ -5288,7 +5089,7 @@ function calculateDeployedAddress(code: c.Cell, data: c.Cell, options: DeployedA } export class LockReleaseTokenPool implements c.Contract { - static CodeCell = c.Cell.fromBase64('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'); + static CodeCell = c.Cell.fromBase64('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'); static Errors = { 'Common_Error.CrossChainAddressOutOfRange': 5, @@ -5530,16 +5331,9 @@ export class LockReleaseTokenPool implements c.Contract { return TokenPool_ApplyTokenTransferFeeConfigUpdates.toCell(TokenPool_ApplyTokenTransferFeeConfigUpdates.create(body)); } - static createCellOfTokenPoolUpdateRampAccess(body: { - queryId?: uint64 - updates: SnakedCell - }) { - return TokenPool_UpdateRampAccess.toCell(TokenPool_UpdateRampAccess.create(body)); - } - static createCellOfTokenPoolSetRMNProxy(body: { queryId?: uint64 - rmnProxy: c.Address + rmnProxy: c.Address | null }) { return TokenPool_SetRMNProxy.toCell(TokenPool_SetRMNProxy.create(body)); } @@ -5840,20 +5634,9 @@ export class LockReleaseTokenPool implements c.Contract { }); } - async sendTokenPoolUpdateRampAccess(provider: ContractProvider, via: Sender, msgValue: coins, body: { - queryId?: uint64 - updates: SnakedCell - }, extraOptions?: ExtraSendOptions) { - return provider.internal(via, { - value: msgValue, - body: TokenPool_UpdateRampAccess.toCell(TokenPool_UpdateRampAccess.create(body)), - ...extraOptions - }); - } - async sendTokenPoolSetRMNProxy(provider: ContractProvider, via: Sender, msgValue: coins, body: { queryId?: uint64 - rmnProxy: c.Address + rmnProxy: c.Address | null }, extraOptions?: ExtraSendOptions) { return provider.internal(via, { value: msgValue, @@ -5955,29 +5738,13 @@ export class LockReleaseTokenPool implements c.Contract { return r.readBoolean(); } - async getOnRamp(provider: ContractProvider, remoteChainSelector: uint64): Promise { - const r = StackReader.fromGetMethod(1, await provider.get('onRamp', [ - { type: 'int', value: remoteChainSelector }, - ])); - return r.readNullable( - (r) => r.readSlice().loadAddress() - ); - } - - async getOffRamp(provider: ContractProvider, remoteChainSelector: uint64): Promise { - const r = StackReader.fromGetMethod(1, await provider.get('offRamp', [ - { type: 'int', value: remoteChainSelector }, - ])); + async getRMNProxy(provider: ContractProvider): Promise { + const r = StackReader.fromGetMethod(1, await provider.get('getRMNProxy', [])); return r.readNullable( (r) => r.readSlice().loadAddress() ); } - async getRMNProxy(provider: ContractProvider): Promise { - const r = StackReader.fromGetMethod(1, await provider.get('getRMNProxy', [])); - return r.readSlice().loadAddress(); - } - async getVerifyNotCursed(provider: ContractProvider, subject: uint128): Promise { const r = StackReader.fromGetMethod(1, await provider.get('verifyNotCursed', [ { type: 'int', value: subject }, diff --git a/contracts/wrappers/gen/ccip/pools/TokenPool.ts b/contracts/wrappers/gen/ccip/pools/TokenPool.ts index 16ed12042..dbbc23cce 100644 --- a/contracts/wrappers/gen/ccip/pools/TokenPool.ts +++ b/contracts/wrappers/gen/ccip/pools/TokenPool.ts @@ -394,108 +394,35 @@ export const TokenPool_DynamicConfig = { } /** - > struct TokenPool_MirroredPolicy { - > onRamps: map - > offRamps: map + > struct TokenPool_LocalPolicy { > cursedSubjects: CursedSubjects > } */ -export interface TokenPool_MirroredPolicy { - readonly $: 'TokenPool_MirroredPolicy' - onRamps: Map /* = [] as map */ - offRamps: Map /* = [] as map */ +export interface TokenPool_LocalPolicy { + readonly $: 'TokenPool_LocalPolicy' cursedSubjects: CursedSubjects } -export const TokenPool_MirroredPolicy = { +export const TokenPool_LocalPolicy = { create(args: { - onRamps: Map /* = [] as map */ - offRamps: Map /* = [] as map */ cursedSubjects: CursedSubjects - }): TokenPool_MirroredPolicy { + }): TokenPool_LocalPolicy { return { - $: 'TokenPool_MirroredPolicy', + $: 'TokenPool_LocalPolicy', ...args } }, - fromSlice(s: c.Slice): TokenPool_MirroredPolicy { + fromSlice(s: c.Slice): TokenPool_LocalPolicy { return { - $: 'TokenPool_MirroredPolicy', - onRamps: dictToMap(c.Dictionary.load(c.Dictionary.Keys.BigUint(64), createDictionaryValue( - (s) => s.loadAddress(), - (v,b) => b.storeAddress(v) - ), s)), - offRamps: dictToMap(c.Dictionary.load(c.Dictionary.Keys.BigUint(64), createDictionaryValue( - (s) => s.loadAddress(), - (v,b) => b.storeAddress(v) - ), s)), + $: 'TokenPool_LocalPolicy', cursedSubjects: CursedSubjects.fromSlice(s), } }, - store(self: TokenPool_MirroredPolicy, b: c.Builder): void { - b.storeDict(mapToDict(self.onRamps, c.Dictionary.Keys.BigUint(64), createDictionaryValue( - (s) => s.loadAddress(), - (v,b) => b.storeAddress(v) - )), c.Dictionary.Keys.BigUint(64), createDictionaryValue( - (s) => s.loadAddress(), - (v,b) => b.storeAddress(v) - )); - b.storeDict(mapToDict(self.offRamps, c.Dictionary.Keys.BigUint(64), createDictionaryValue( - (s) => s.loadAddress(), - (v,b) => b.storeAddress(v) - )), c.Dictionary.Keys.BigUint(64), createDictionaryValue( - (s) => s.loadAddress(), - (v,b) => b.storeAddress(v) - )); + store(self: TokenPool_LocalPolicy, b: c.Builder): void { CursedSubjects.store(self.cursedSubjects, b); }, - toCell(self: TokenPool_MirroredPolicy): c.Cell { - return makeCellFrom(self, TokenPool_MirroredPolicy.store); - } -} - -/** - > struct TokenPool_RampUpdate { - > remoteChainSelector: uint64 - > onRamp: address? - > offRamp: address? - > } - */ -export interface TokenPool_RampUpdate { - readonly $: 'TokenPool_RampUpdate' - remoteChainSelector: uint64 - onRamp: c.Address | null /* = null */ - offRamp: c.Address | null /* = null */ -} - -export const TokenPool_RampUpdate = { - create(args: { - remoteChainSelector: uint64 - onRamp?: c.Address | null /* = null */ - offRamp?: c.Address | null /* = null */ - }): TokenPool_RampUpdate { - return { - $: 'TokenPool_RampUpdate', - onRamp: null, - offRamp: null, - ...args - } - }, - fromSlice(s: c.Slice): TokenPool_RampUpdate { - return { - $: 'TokenPool_RampUpdate', - remoteChainSelector: s.loadUintBig(64), - onRamp: s.loadMaybeAddress(), - offRamp: s.loadMaybeAddress(), - } - }, - store(self: TokenPool_RampUpdate, b: c.Builder): void { - b.storeUint(self.remoteChainSelector, 64); - b.storeAddress(self.onRamp); - b.storeAddress(self.offRamp); - }, - toCell(self: TokenPool_RampUpdate): c.Cell { - return makeCellFrom(self, TokenPool_RampUpdate.store); + toCell(self: TokenPool_LocalPolicy): c.Cell { + return makeCellFrom(self, TokenPool_LocalPolicy.store); } } @@ -1233,7 +1160,7 @@ export const TokenPool_ReleaseOrMintOutV1 = { /** > struct TokenPool_AdminConfig { > ownable: Cell - > rmnProxy: address + > rmnProxy: address? > dynamicConfig: Cell > jettonClient: JettonClient > allowedFinalityConfig: uint32 @@ -1244,7 +1171,7 @@ export const TokenPool_ReleaseOrMintOutV1 = { export interface TokenPool_AdminConfig { readonly $: 'TokenPool_AdminConfig' ownable: Ownable2Step - rmnProxy: c.Address + rmnProxy: c.Address | null dynamicConfig: TokenPool_DynamicConfig jettonClient: JettonClient allowedFinalityConfig: uint32 /* = 0 as uint32 */ @@ -1255,7 +1182,7 @@ export interface TokenPool_AdminConfig { export const TokenPool_AdminConfig = { create(args: { ownable: Ownable2Step - rmnProxy: c.Address + rmnProxy: c.Address | null dynamicConfig: TokenPool_DynamicConfig jettonClient: JettonClient allowedFinalityConfig?: uint32 /* = 0 as uint32 */ @@ -1274,7 +1201,7 @@ export const TokenPool_AdminConfig = { return { $: 'TokenPool_AdminConfig', ownable: loadCellRef(s, Ownable2Step.fromSlice), - rmnProxy: s.loadAddress(), + rmnProxy: s.loadMaybeAddress(), dynamicConfig: loadCellRef(s, TokenPool_DynamicConfig.fromSlice), jettonClient: JettonClient.fromSlice(s), allowedFinalityConfig: s.loadUintBig(32), @@ -1301,7 +1228,7 @@ export const TokenPool_AdminConfig = { /** > struct TokenPool_Data { > adminConfig: Cell - > mirroredPolicy: Cell + > localPolicy: Cell > tokenDecimals: uint8 > remoteChainConfigs: map > tokenTransferFeeConfigs: map @@ -1310,7 +1237,7 @@ export const TokenPool_AdminConfig = { export interface TokenPool_Data { readonly $: 'TokenPool_Data' adminConfig: TokenPool_AdminConfig - mirroredPolicy: TokenPool_MirroredPolicy + localPolicy: TokenPool_LocalPolicy tokenDecimals: uint8 remoteChainConfigs: Map /* = [] as map */ tokenTransferFeeConfigs: Map /* = [] as map */ @@ -1319,7 +1246,7 @@ export interface TokenPool_Data { export const TokenPool_Data = { create(args: { adminConfig: TokenPool_AdminConfig - mirroredPolicy: TokenPool_MirroredPolicy + localPolicy: TokenPool_LocalPolicy tokenDecimals: uint8 remoteChainConfigs: Map /* = [] as map */ tokenTransferFeeConfigs: Map /* = [] as map */ @@ -1333,7 +1260,7 @@ export const TokenPool_Data = { return { $: 'TokenPool_Data', adminConfig: loadCellRef(s, TokenPool_AdminConfig.fromSlice), - mirroredPolicy: loadCellRef(s, TokenPool_MirroredPolicy.fromSlice), + localPolicy: loadCellRef(s, TokenPool_LocalPolicy.fromSlice), tokenDecimals: s.loadUintBig(8), remoteChainConfigs: dictToMap(c.Dictionary.load(c.Dictionary.Keys.BigUint(64), createDictionaryValue(TokenPool_RemoteChainConfig.fromSlice, TokenPool_RemoteChainConfig.store), s)), tokenTransferFeeConfigs: dictToMap(c.Dictionary.load(c.Dictionary.Keys.BigUint(64), createDictionaryValue(TokenPool_TokenTransferFeeConfig.fromSlice, TokenPool_TokenTransferFeeConfig.store), s)), @@ -1341,7 +1268,7 @@ export const TokenPool_Data = { }, store(self: TokenPool_Data, b: c.Builder): void { storeCellRef(self.adminConfig, b, TokenPool_AdminConfig.store); - storeCellRef(self.mirroredPolicy, b, TokenPool_MirroredPolicy.store); + storeCellRef(self.localPolicy, b, TokenPool_LocalPolicy.store); b.storeUint(self.tokenDecimals, 8); b.storeDict(mapToDict(self.remoteChainConfigs, c.Dictionary.Keys.BigUint(64), createDictionaryValue(TokenPool_RemoteChainConfig.fromSlice, TokenPool_RemoteChainConfig.store)), c.Dictionary.Keys.BigUint(64), createDictionaryValue(TokenPool_RemoteChainConfig.fromSlice, TokenPool_RemoteChainConfig.store)); b.storeDict(mapToDict(self.tokenTransferFeeConfigs, c.Dictionary.Keys.BigUint(64), createDictionaryValue(TokenPool_TokenTransferFeeConfig.fromSlice, TokenPool_TokenTransferFeeConfig.store)), c.Dictionary.Keys.BigUint(64), createDictionaryValue(TokenPool_TokenTransferFeeConfig.fromSlice, TokenPool_TokenTransferFeeConfig.store)); @@ -1898,59 +1825,16 @@ export const TokenPool_ApplyTokenTransferFeeConfigUpdates = { } } -/** - > struct (0xe30764be) TokenPool_UpdateRampAccess { - > queryId: uint64 - > updates: SnakedCell - > } - */ -export interface TokenPool_UpdateRampAccess { - readonly $: 'TokenPool_UpdateRampAccess' - queryId: uint64 - updates: SnakedCell -} - -export const TokenPool_UpdateRampAccess = { - PREFIX: 0xe30764be, - - create(args: { - queryId?: uint64 - updates: SnakedCell - }): TokenPool_UpdateRampAccess { - return { - $: 'TokenPool_UpdateRampAccess', - ...args, - queryId: args.queryId ?? 0n - } - }, - fromSlice(s: c.Slice): TokenPool_UpdateRampAccess { - loadAndCheckPrefix32(s, 0xe30764be, 'TokenPool_UpdateRampAccess'); - return { - $: 'TokenPool_UpdateRampAccess', - queryId: s.loadUintBig(64), - updates: loadSnakedCellOf(s, TokenPool_RampUpdate.fromSlice), - } - }, - store(self: TokenPool_UpdateRampAccess, b: c.Builder): void { - b.storeUint(0xe30764be, 32); - b.storeUint(self.queryId, 64); - storeSnakedCellOf(self.updates, b, TokenPool_RampUpdate.store); - }, - toCell(self: TokenPool_UpdateRampAccess): c.Cell { - return makeCellFrom(self, TokenPool_UpdateRampAccess.store); - } -} - /** > struct (0x9929b642) TokenPool_SetRMNProxy { > queryId: uint64 - > rmnProxy: address + > rmnProxy: address? > } */ export interface TokenPool_SetRMNProxy { readonly $: 'TokenPool_SetRMNProxy' queryId: uint64 - rmnProxy: c.Address + rmnProxy: c.Address | null } export const TokenPool_SetRMNProxy = { @@ -1958,7 +1842,7 @@ export const TokenPool_SetRMNProxy = { create(args: { queryId?: uint64 - rmnProxy: c.Address + rmnProxy: c.Address | null }): TokenPool_SetRMNProxy { return { $: 'TokenPool_SetRMNProxy', @@ -1971,7 +1855,7 @@ export const TokenPool_SetRMNProxy = { return { $: 'TokenPool_SetRMNProxy', queryId: s.loadUintBig(64), - rmnProxy: s.loadAddress(), + rmnProxy: s.loadMaybeAddress(), } }, store(self: TokenPool_SetRMNProxy, b: c.Builder): void { @@ -3349,44 +3233,6 @@ export const TokenPool_ChainUpdatesApplied = { } } -/** - > struct (0xd7f5c563) TokenPool_RampAccessUpdatesApplied { - > queryId: uint64 - > } - */ -export interface TokenPool_RampAccessUpdatesApplied { - readonly $: 'TokenPool_RampAccessUpdatesApplied' - queryId: uint64 -} - -export const TokenPool_RampAccessUpdatesApplied = { - PREFIX: 0xd7f5c563, - - create(args: { - queryId?: uint64 - }): TokenPool_RampAccessUpdatesApplied { - return { - $: 'TokenPool_RampAccessUpdatesApplied', - ...args, - queryId: args.queryId ?? 0n - } - }, - fromSlice(s: c.Slice): TokenPool_RampAccessUpdatesApplied { - loadAndCheckPrefix32(s, 0xd7f5c563, 'TokenPool_RampAccessUpdatesApplied'); - return { - $: 'TokenPool_RampAccessUpdatesApplied', - queryId: s.loadUintBig(64), - } - }, - store(self: TokenPool_RampAccessUpdatesApplied, b: c.Builder): void { - b.storeUint(0xd7f5c563, 32); - b.storeUint(self.queryId, 64); - }, - toCell(self: TokenPool_RampAccessUpdatesApplied): c.Cell { - return makeCellFrom(self, TokenPool_RampAccessUpdatesApplied.store); - } -} - /** > struct (0x28cbcc64) TokenPool_FeeConfigApplied { > queryId: uint64 @@ -3901,51 +3747,6 @@ export const TokenPool_RateLimitConfigured = { } } -/** - > struct TokenPool_RampAccessUpdated { - > remoteChainSelector: uint64 - > onRamp: address? - > offRamp: address? - > } - */ -export interface TokenPool_RampAccessUpdated { - readonly $: 'TokenPool_RampAccessUpdated' - remoteChainSelector: uint64 - onRamp: c.Address | null /* = null */ - offRamp: c.Address | null /* = null */ -} - -export const TokenPool_RampAccessUpdated = { - create(args: { - remoteChainSelector: uint64 - onRamp?: c.Address | null /* = null */ - offRamp?: c.Address | null /* = null */ - }): TokenPool_RampAccessUpdated { - return { - $: 'TokenPool_RampAccessUpdated', - onRamp: null, - offRamp: null, - ...args - } - }, - fromSlice(s: c.Slice): TokenPool_RampAccessUpdated { - return { - $: 'TokenPool_RampAccessUpdated', - remoteChainSelector: s.loadUintBig(64), - onRamp: s.loadMaybeAddress(), - offRamp: s.loadMaybeAddress(), - } - }, - store(self: TokenPool_RampAccessUpdated, b: c.Builder): void { - b.storeUint(self.remoteChainSelector, 64); - b.storeAddress(self.onRamp); - b.storeAddress(self.offRamp); - }, - toCell(self: TokenPool_RampAccessUpdated): c.Cell { - return makeCellFrom(self, TokenPool_RampAccessUpdated.store); - } -} - /** > type SnakedCell = cell */ @@ -4473,7 +4274,7 @@ function calculateDeployedAddress(code: c.Cell, data: c.Cell, options: DeployedA } export class TokenPool implements c.Contract { - static CodeCell = c.Cell.fromBase64('te6ccgECOgEAAY4AART/APSkE/S88sgLAQIBYgIDABTQMPiR8kCED/LwAgEgBAUCASAGBwIBIC4vAgEgCAkCASAaGwIBIAoLAgEgFBUCASAMDQIBSBITAgFmDg8CAUgQEQALoF4QP8vCAAuhxhA/y8IAC6V1CB/l4QALpyMIH+XhAAypX4QP8vAADKrQhA/y8AIBbhYXAgEgGBkAC6dRCB/l4QALpFEIH+XhAA2sPkIH+XhAAA2sgMIH+XhAAgEgHB0CASAoKQIBIB4fAgEgJicCASAgIQIBYiQlAAyqh4QP8vACASAiIwALpjsIH+XhAAulCwgf5eEAC6H6ED/LwgALoH4QP8vCAA2vRUIH+XhAAA2s40IH+XhAAgFYKisCAnUsLQAMqXqED/LwAAyqtoQP8vAAC6OuED/LwgALohoQP8vCAgEgMDECASAyMwANtH2wgf5eEAANt9zwgf5eEAANtI2wgf5eEAIBIDQ1AgFqNjcCASA4OQALpV8IH+XhAAunAwgf5eEADaxrwgf5eEAADaw4wgf5eEA='); + static CodeCell = c.Cell.fromBase64('te6ccgECNAEAAWgAART/APSkE/S88sgLAQIBYgIDABTQMPiR8kCED/LwAgEgBAUCASAGBwIBICgpAgEgCAkCASAWFwIBIAoLAgEgEhMCASAMDQIBSBARAgFmDg8ADa3Iwgf5eEAAC6BeED/LwgALocYQP8vCAAypX4QP8vAADKrQhA/y8AIBbhQVAA2wHyED/LwgAAunUQgf5eEAC6RRCB/l4QIBIBgZAgEgJCUCASAaGwIBICIjAgEgHB0CAWIgIQAMqoeED/LwAgEgHh8AC6Y7CB/l4QALpQsIH+XhAAuh+hA/y8IAC6B+ED/LwgANr0VCB/l4QAANrONCB/l4QAIBWCYnAA2yuuED/LwgAAypeoQP8vAADKq2hA/y8AIBICorAgEgLC0ADbR9sIH+XhAADbfc8IH+XhAADbSNsIH+XhACASAuLwIBajAxAgEgMjMAC6VfCB/l4QALpwMIH+XhAA2sa8IH+XhAAA2sOMIH+XhA'); static Errors = { } @@ -4503,7 +4304,7 @@ export class TokenPool implements c.Contract { static fromStorage(emptyStorage: { adminConfig: TokenPool_AdminConfig - mirroredPolicy: TokenPool_MirroredPolicy + localPolicy: TokenPool_LocalPolicy tokenDecimals: uint8 remoteChainConfigs: Map /* = [] as map */ tokenTransferFeeConfigs: Map /* = [] as map */ @@ -4683,16 +4484,9 @@ export class TokenPool implements c.Contract { return TokenPool_ApplyTokenTransferFeeConfigUpdates.toCell(TokenPool_ApplyTokenTransferFeeConfigUpdates.create(body)); } - static createCellOfTokenPoolUpdateRampAccess(body: { - queryId?: uint64 - updates: SnakedCell - }) { - return TokenPool_UpdateRampAccess.toCell(TokenPool_UpdateRampAccess.create(body)); - } - static createCellOfTokenPoolSetRMNProxy(body: { queryId?: uint64 - rmnProxy: c.Address + rmnProxy: c.Address | null }) { return TokenPool_SetRMNProxy.toCell(TokenPool_SetRMNProxy.create(body)); } @@ -4974,20 +4768,9 @@ export class TokenPool implements c.Contract { }); } - async sendTokenPoolUpdateRampAccess(provider: ContractProvider, via: Sender, msgValue: coins, body: { - queryId?: uint64 - updates: SnakedCell - }, extraOptions?: ExtraSendOptions) { - return provider.internal(via, { - value: msgValue, - body: TokenPool_UpdateRampAccess.toCell(TokenPool_UpdateRampAccess.create(body)), - ...extraOptions - }); - } - async sendTokenPoolSetRMNProxy(provider: ContractProvider, via: Sender, msgValue: coins, body: { queryId?: uint64 - rmnProxy: c.Address + rmnProxy: c.Address | null }, extraOptions?: ExtraSendOptions) { return provider.internal(via, { value: msgValue, @@ -5058,29 +4841,13 @@ export class TokenPool implements c.Contract { return r.readBoolean(); } - async getOnRamp(provider: ContractProvider, remoteChainSelector: uint64): Promise { - const r = StackReader.fromGetMethod(1, await provider.get('onRamp', [ - { type: 'int', value: remoteChainSelector }, - ])); - return r.readNullable( - (r) => r.readSlice().loadAddress() - ); - } - - async getOffRamp(provider: ContractProvider, remoteChainSelector: uint64): Promise { - const r = StackReader.fromGetMethod(1, await provider.get('offRamp', [ - { type: 'int', value: remoteChainSelector }, - ])); + async getRMNProxy(provider: ContractProvider): Promise { + const r = StackReader.fromGetMethod(1, await provider.get('getRMNProxy', [])); return r.readNullable( (r) => r.readSlice().loadAddress() ); } - async getRMNProxy(provider: ContractProvider): Promise { - const r = StackReader.fromGetMethod(1, await provider.get('getRMNProxy', [])); - return r.readSlice().loadAddress(); - } - async getVerifyNotCursed(provider: ContractProvider, subject: uint128): Promise { const r = StackReader.fromGetMethod(1, await provider.get('verifyNotCursed', [ { type: 'int', value: subject }, @@ -5200,7 +4967,9 @@ export class TokenPool implements c.Contract { return ({ $: 'TokenPool_AdminConfig', ownable: r.readCellRef(Ownable2Step.fromSlice), - rmnProxy: r.readSlice().loadAddress(), + rmnProxy: r.readNullable( + (r) => r.readSlice().loadAddress() + ), dynamicConfig: r.readCellRef(TokenPool_DynamicConfig.fromSlice), jettonClient: ({ $: 'JettonClient', @@ -5217,28 +4986,6 @@ export class TokenPool implements c.Contract { }); } - async getMirroredPolicy(provider: ContractProvider): Promise { - const r = StackReader.fromGetMethod(3, await provider.get('getMirroredPolicy', [])); - return ({ - $: 'TokenPool_MirroredPolicy', - onRamps: dictToMap(r.readDictionary(c.Dictionary.Keys.BigUint(64), createDictionaryValue( - (s) => s.loadAddress(), - (v,b) => b.storeAddress(v) - ))), - offRamps: dictToMap(r.readDictionary(c.Dictionary.Keys.BigUint(64), createDictionaryValue( - (s) => s.loadAddress(), - (v,b) => b.storeAddress(v) - ))), - cursedSubjects: ({ - $: 'CursedSubjects', - data: dictToSet(r.readDictionary(c.Dictionary.Keys.BigUint(128), createDictionaryValue<[]>( - (s) => [], - (v,b) => { {} } - ))), - }), - }); - } - async getRemoteChainConfig(provider: ContractProvider, remoteChainSelector: uint64): Promise { const r = StackReader.fromGetMethod(5, await provider.get('getRemoteChainConfig', [ { type: 'int', value: remoteChainSelector }, From 6068b3038fb74a521e92b198b7e8e90e271db9a4 Mon Sep 17 00:00:00 2001 From: Kristijan Date: Tue, 25 Aug 2026 13:27:02 +0200 Subject: [PATCH 02/23] Use Cell.EMPTY --- contracts/tests/ccip/pools/TokenPool.asyncHook.behavior.ts | 2 +- contracts/tests/ccip/pools/TokenPool.ccvFees.behavior.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/contracts/tests/ccip/pools/TokenPool.asyncHook.behavior.ts b/contracts/tests/ccip/pools/TokenPool.asyncHook.behavior.ts index 8c942df81..a5554e004 100644 --- a/contracts/tests/ccip/pools/TokenPool.asyncHook.behavior.ts +++ b/contracts/tests/ccip/pools/TokenPool.asyncHook.behavior.ts @@ -356,7 +356,7 @@ export function runTokenPoolAsyncHookBehaviorTests( ) expect(result.transactions).toHaveTransaction({ - from: ctx.deployer.address, + from: ctx.deployer.address, to: ctx.pool.address, success: true, }) diff --git a/contracts/tests/ccip/pools/TokenPool.ccvFees.behavior.ts b/contracts/tests/ccip/pools/TokenPool.ccvFees.behavior.ts index df1cd3844..8c98c3837 100644 --- a/contracts/tests/ccip/pools/TokenPool.ccvFees.behavior.ts +++ b/contracts/tests/ccip/pools/TokenPool.ccvFees.behavior.ts @@ -1,6 +1,6 @@ import '@ton/test-utils' import { Blockchain, SandboxContract, internal } from '@ton/sandbox' -import { Address, beginCell, toNano } from '@ton/core' +import { Address, beginCell, Cell, toNano } from '@ton/core' import { TokenPool, TokenPool_CCVs, @@ -473,7 +473,7 @@ export function runTokenPoolCcvFeesBehaviorTests( TokenPool_QueryCCVsReply.create({ queryId: 23n, requiredCCVs: [ctx.pool.address], - replyPayload: beginCell().endCell(), + replyPayload: Cell.EMPTY, }), ), }), From 1897f1a7803291609949c3be162b98986e327d45 Mon Sep 17 00:00:00 2001 From: Kristijan Date: Tue, 25 Aug 2026 13:47:20 +0200 Subject: [PATCH 03/23] Fix TP test - use bindings --- .../ccip/accounts/DepositAccount.spec.ts | 19 +++++++++++-------- .../tests/ccip/accounts/OnRampAccount.spec.ts | 17 ++++++++++------- 2 files changed, 21 insertions(+), 15 deletions(-) diff --git a/contracts/tests/ccip/accounts/DepositAccount.spec.ts b/contracts/tests/ccip/accounts/DepositAccount.spec.ts index e7e3193d2..d2ccea9ad 100644 --- a/contracts/tests/ccip/accounts/DepositAccount.spec.ts +++ b/contracts/tests/ccip/accounts/DepositAccount.spec.ts @@ -9,6 +9,7 @@ import { DepositAccount_InMessageForward, DepositAccount_Reply, } from '../../../wrappers/gen/ccip/DepositAccount' +import { TransferNotificationForRecipient } from '../../../wrappers/gen/ccip/pools/TokenPool' describe('DepositAccount (default forward hook, off-ramp role)', () => { let blockchain: Blockchain @@ -45,15 +46,17 @@ describe('DepositAccount (default forward hook, off-ramp role)', () => { forwardPayload: ForwardPayloadRemainder.fromSlice(Cell.EMPTY.beginParse()), }) - // Build a boxed Jetton `TransferNotificationForRecipient`-shaped body carried by a real wallet. + // Build a boxed Jetton `TransferNotificationForRecipient` body as a real wallet would send it + // (the forward payload is boxed as a maybe_ref; here empty — no CCIPSend carried). const buildNotificationBody = (queryId: bigint, amount: bigint, to: Address) => - beginCell() - .storeUint(0x7362d09c, 32) // TransferNotificationForRecipient - .storeUint(queryId, 64) - .storeCoins(amount) - .storeAddress(to) - .storeMaybeRef(null) - .endCell() + TransferNotificationForRecipient.toCell( + TransferNotificationForRecipient.create({ + queryId, + jettonAmount: amount, + transferInitiator: to, + forwardPayload: beginCell().storeMaybeRef(null).asSlice(), + }), + ) beforeEach(async () => { blockchain = await Blockchain.create() diff --git a/contracts/tests/ccip/accounts/OnRampAccount.spec.ts b/contracts/tests/ccip/accounts/OnRampAccount.spec.ts index e281cbb69..c580ffaab 100644 --- a/contracts/tests/ccip/accounts/OnRampAccount.spec.ts +++ b/contracts/tests/ccip/accounts/OnRampAccount.spec.ts @@ -7,6 +7,7 @@ import { ForwardPayloadRemainder, DepositAccount_WithdrawFailed, } from '../../../wrappers/gen/ccip/OnRampAccount' +import { TransferNotificationForRecipient } from '../../../wrappers/gen/ccip/pools/TokenPool' import { JettonMinter, JettonWallet } from '../../../wrappers/examples/jetton' import { contractCode } from '../../../wrappers/codeLoader' @@ -188,13 +189,15 @@ describe('OnRampAccount (generic DepositAccount with CCIPSend hook)', () => { to: account.address, value: toNano('0.5'), bounce: false, - body: beginCell() - .storeUint(0x7362d09c, 32) // TransferNotificationForRecipient - .storeUint(5n, 64) - .storeCoins(toNano('1')) - .storeAddress(user.address) - .storeMaybeRef(ccipSendCell()) - .endCell(), + body: TransferNotificationForRecipient.toCell( + TransferNotificationForRecipient.create({ + queryId: 5n, + jettonAmount: toNano('1'), + transferInitiator: user.address, + // A real jetton wallet boxes the transfer's forward payload as a maybe_ref. + forwardPayload: beginCell().storeMaybeRef(ccipSendCell()).asSlice(), + }), + ), }) // The CCIPSend (op 0x31768d95) is relayed to the Router. expect(res.transactions).toHaveTransaction({ From 0299a8a2cf7c36a12f3de903a29c8b6a8596a18c Mon Sep 17 00:00:00 2001 From: Kristijan Date: Tue, 25 Aug 2026 14:01:03 +0200 Subject: [PATCH 04/23] Add forceAbiExport to TP contract metadata --- .../ccip/pools/burn_mint/contract.tolk | 5 ++ .../ccip/pools/lock_release/contract.tolk | 2 + .../pools/lock_release_lockbox/contract.tolk | 5 ++ .../ccip/pools/BurnMintTokenPool.spec.ts | 18 +++-- .../pools/LockReleaseLockboxTokenPool.spec.ts | 11 +-- .../gen/ccip/pools/BurnMintTokenPool.ts | 79 +++++++++++++++++++ .../ccip/pools/LockReleaseLockboxTokenPool.ts | 74 +++++++++++++++++ .../gen/ccip/pools/LockReleaseTokenPool.ts | 37 +++++++++ 8 files changed, 219 insertions(+), 12 deletions(-) diff --git a/contracts/contracts/ccip/pools/burn_mint/contract.tolk b/contracts/contracts/ccip/pools/burn_mint/contract.tolk index ab26e5632..efe072e67 100644 --- a/contracts/contracts/ccip/pools/burn_mint/contract.tolk +++ b/contracts/contracts/ccip/pools/burn_mint/contract.tolk @@ -36,6 +36,11 @@ contract BurnMintTokenPool { incomingMessages: | TokenPool_InMessage | BurnMintTokenPool_InMessage + + forceAbiExport: ( + BurnMintTokenPool_BurnContext, + BurnMintTokenPool_MintContext + ) } const CONTRACT_VERSION = "0.1.0".literalSlice(); diff --git a/contracts/contracts/ccip/pools/lock_release/contract.tolk b/contracts/contracts/ccip/pools/lock_release/contract.tolk index 342627186..23d15dbd0 100644 --- a/contracts/contracts/ccip/pools/lock_release/contract.tolk +++ b/contracts/contracts/ccip/pools/lock_release/contract.tolk @@ -34,6 +34,8 @@ contract LockReleaseTokenPool { incomingMessages: | TokenPool_InMessage | LockReleaseTokenPool_InMessage + + forceAbiExport: (LockReleaseTokenPool_ReleaseContext) } const CONTRACT_VERSION = "0.1.0".literalSlice(); diff --git a/contracts/contracts/ccip/pools/lock_release_lockbox/contract.tolk b/contracts/contracts/ccip/pools/lock_release_lockbox/contract.tolk index e0208302b..f79f6ac56 100644 --- a/contracts/contracts/ccip/pools/lock_release_lockbox/contract.tolk +++ b/contracts/contracts/ccip/pools/lock_release_lockbox/contract.tolk @@ -34,6 +34,11 @@ contract LockReleaseLockboxTokenPool { incomingMessages: | TokenPool_InMessage | LockReleaseLockboxTokenPool_InMessage + + forceAbiExport: ( + LockReleaseLockboxTokenPool_LockContext, + LockReleaseLockboxTokenPool_ReleaseContext + ) } const CONTRACT_VERSION = "0.1.0".literalSlice(); diff --git a/contracts/tests/ccip/pools/BurnMintTokenPool.spec.ts b/contracts/tests/ccip/pools/BurnMintTokenPool.spec.ts index 48a6d3b77..41b000f89 100644 --- a/contracts/tests/ccip/pools/BurnMintTokenPool.spec.ts +++ b/contracts/tests/ccip/pools/BurnMintTokenPool.spec.ts @@ -20,6 +20,7 @@ import { TokenPool_LockOrBurnForwardPayload, TokenPool_LockOrBurnPrepared, TokenPool_LockOrBurnOutV1, + TokenPool_LockOrBurnWithdraw, TokenPool_ReleaseOrMintInV1, TokenPool_ReleaseOrMintFinished, TokenPool_LocalPolicy, @@ -29,17 +30,20 @@ import { TokenPool_TokenTransferFeeConfig, TokenPool_TokenTransferFeeConfigArgs, } from '../../../wrappers/gen/ccip/pools/TokenPool' -import { TokenPool_LockOrBurnWithdraw } from '../../../wrappers/gen/ccip/pools/BurnMintTokenPool' -import { BurnMintTokenPool, JettonClient } from '../../../wrappers/gen/ccip/pools/BurnMintTokenPool' +import { + JettonClient, + BurnMintTokenPool, + BurnMintTokenPool_BurnContext, +} from '../../../wrappers/gen/ccip/pools/BurnMintTokenPool' import { CCT_ReturnExcessesBack } from '../../../wrappers/gen/ccip/cct/JettonMinter' -import { runTokenPoolBehaviorTests } from './TokenPool.behavior' -import { runTokenPoolAsyncHookBehaviorTests } from './TokenPool.asyncHook.behavior' -import { runTokenPoolWithdrawFeeTokensBehaviorTests } from './TokenPool.withdrawFeeTokens.behavior' -import { runTokenPoolCcvFeesBehaviorTests } from './TokenPool.ccvFees.behavior' import { MockAdvancedPoolHooks } from '../../../wrappers/gen/ccip/test/MockAdvancedPoolHooks' import * as CrossChainAddressCodec from '../../../wrappers/ccip/common/CrossChainAddressCodec' import { contractCode } from '../../../wrappers/codeLoader' import { DepositAccount } from '../../../wrappers/gen/ccip/DepositAccount' +import { runTokenPoolBehaviorTests } from './TokenPool.behavior' +import { runTokenPoolAsyncHookBehaviorTests } from './TokenPool.asyncHook.behavior' +import { runTokenPoolWithdrawFeeTokensBehaviorTests } from './TokenPool.withdrawFeeTokens.behavior' +import { runTokenPoolCcvFeesBehaviorTests } from './TokenPool.ccvFees.behavior' // Builds a forged `CCT_ReturnExcessesBack` carrying a burn continuation payload. It is sent // from an unauthorized sender, so the pool must reject it (sender not the CCT minter). @@ -48,7 +52,7 @@ function buildForgedCCTReturnExcessesBack(poolAddress: Address): Cell { CCT_ReturnExcessesBack.create({ queryId: 999n, initiator: poolAddress, - forwardPayload: beginCell().storeUint(0xba302a47, 32).endCell(), + forwardPayload: beginCell().storeUint(BurnMintTokenPool_BurnContext.PREFIX, 32).endCell(), }), ) } diff --git a/contracts/tests/ccip/pools/LockReleaseLockboxTokenPool.spec.ts b/contracts/tests/ccip/pools/LockReleaseLockboxTokenPool.spec.ts index bdcf75429..35017bf49 100644 --- a/contracts/tests/ccip/pools/LockReleaseLockboxTokenPool.spec.ts +++ b/contracts/tests/ccip/pools/LockReleaseLockboxTokenPool.spec.ts @@ -32,22 +32,23 @@ import { } from '../../../wrappers/gen/ccip/pools/LockReleaseLockboxTokenPool' import { JettonLockBox, + AccessControl_Data, JettonLockBox_WithdrawExtra, } from '../../../wrappers/gen/ccip/pools/JettonLockBox' import { ContractClient as AccessControlClient } from '../../../wrappers/lib/access/AccessControl' -import { runTokenPoolBehaviorTests } from './TokenPool.behavior' -import { runTokenPoolAsyncHookBehaviorTests } from './TokenPool.asyncHook.behavior' -import { runTokenPoolWithdrawFeeTokensBehaviorTests } from './TokenPool.withdrawFeeTokens.behavior' -import { runTokenPoolCcvFeesBehaviorTests } from './TokenPool.ccvFees.behavior' import { MockAdvancedPoolHooks } from '../../../wrappers/gen/ccip/test/MockAdvancedPoolHooks' -import { AccessControl_Data } from '../../../wrappers/gen/ccip/pools/JettonLockBox' import * as CrossChainAddressCodec from '../../../wrappers/ccip/common/CrossChainAddressCodec' import { contractCode } from '../../../wrappers/codeLoader' import { DepositAccount, DepositAccount_ForwardNotification, } from '../../../wrappers/gen/ccip/DepositAccount' +import { runTokenPoolBehaviorTests } from './TokenPool.behavior' +import { runTokenPoolAsyncHookBehaviorTests } from './TokenPool.asyncHook.behavior' +import { runTokenPoolWithdrawFeeTokensBehaviorTests } from './TokenPool.withdrawFeeTokens.behavior' +import { runTokenPoolCcvFeesBehaviorTests } from './TokenPool.ccvFees.behavior' + function emptyAccessControlData(): AccessControl_Data { return { diff --git a/contracts/wrappers/gen/ccip/pools/BurnMintTokenPool.ts b/contracts/wrappers/gen/ccip/pools/BurnMintTokenPool.ts index ac7907841..05b3ec101 100644 --- a/contracts/wrappers/gen/ccip/pools/BurnMintTokenPool.ts +++ b/contracts/wrappers/gen/ccip/pools/BurnMintTokenPool.ts @@ -4412,6 +4412,85 @@ export const BurnMintTokenPool_ClaimMinterAdmin = { } } +/** + > struct (0xba302a47) BurnMintTokenPool_BurnContext { + > wallet: address + > forwardPayload: Cell + > } + */ +export interface BurnMintTokenPool_BurnContext { + readonly $: 'BurnMintTokenPool_BurnContext' + wallet: c.Address + forwardPayload: TokenPool_LockOrBurnForwardPayload +} + +export const BurnMintTokenPool_BurnContext = { + PREFIX: 0xba302a47, + + create(args: { + wallet: c.Address + forwardPayload: TokenPool_LockOrBurnForwardPayload + }): BurnMintTokenPool_BurnContext { + return { + $: 'BurnMintTokenPool_BurnContext', + ...args + } + }, + fromSlice(s: c.Slice): BurnMintTokenPool_BurnContext { + loadAndCheckPrefix32(s, 0xba302a47, 'BurnMintTokenPool_BurnContext'); + return { + $: 'BurnMintTokenPool_BurnContext', + wallet: s.loadAddress(), + forwardPayload: loadCellRef(s, TokenPool_LockOrBurnForwardPayload.fromSlice), + } + }, + store(self: BurnMintTokenPool_BurnContext, b: c.Builder): void { + b.storeUint(0xba302a47, 32); + b.storeAddress(self.wallet); + storeCellRef(self.forwardPayload, b, TokenPool_LockOrBurnForwardPayload.store); + }, + toCell(self: BurnMintTokenPool_BurnContext): c.Cell { + return makeCellFrom(self, BurnMintTokenPool_BurnContext.store); + } +} + +/** + > struct (0xb3d52361) BurnMintTokenPool_MintContext { + > forwardPayload: Cell + > } + */ +export interface BurnMintTokenPool_MintContext { + readonly $: 'BurnMintTokenPool_MintContext' + forwardPayload: TokenPool_ReleaseOrMintForwardPayload +} + +export const BurnMintTokenPool_MintContext = { + PREFIX: 0xb3d52361, + + create(args: { + forwardPayload: TokenPool_ReleaseOrMintForwardPayload + }): BurnMintTokenPool_MintContext { + return { + $: 'BurnMintTokenPool_MintContext', + ...args + } + }, + fromSlice(s: c.Slice): BurnMintTokenPool_MintContext { + loadAndCheckPrefix32(s, 0xb3d52361, 'BurnMintTokenPool_MintContext'); + return { + $: 'BurnMintTokenPool_MintContext', + forwardPayload: loadCellRef(s, TokenPool_ReleaseOrMintForwardPayload.fromSlice), + } + }, + store(self: BurnMintTokenPool_MintContext, b: c.Builder): void { + b.storeUint(0xb3d52361, 32); + storeCellRef(self.forwardPayload, b, TokenPool_ReleaseOrMintForwardPayload.store); + }, + toCell(self: BurnMintTokenPool_MintContext): c.Cell { + return makeCellFrom(self, BurnMintTokenPool_MintContext.store); + } +} + /** > struct Storage { > poolData: Cell diff --git a/contracts/wrappers/gen/ccip/pools/LockReleaseLockboxTokenPool.ts b/contracts/wrappers/gen/ccip/pools/LockReleaseLockboxTokenPool.ts index 5570a9531..bcd1285a1 100644 --- a/contracts/wrappers/gen/ccip/pools/LockReleaseLockboxTokenPool.ts +++ b/contracts/wrappers/gen/ccip/pools/LockReleaseLockboxTokenPool.ts @@ -4260,6 +4260,80 @@ export const JettonLockBox_WithdrawFailed = { } } +/** + > struct (0x60fdb63b) LockReleaseLockboxTokenPool_LockContext { + > forwardPayload: Cell + > } + */ +export interface LockReleaseLockboxTokenPool_LockContext { + readonly $: 'LockReleaseLockboxTokenPool_LockContext' + forwardPayload: TokenPool_LockOrBurnForwardPayload +} + +export const LockReleaseLockboxTokenPool_LockContext = { + PREFIX: 0x60fdb63b, + + create(args: { + forwardPayload: TokenPool_LockOrBurnForwardPayload + }): LockReleaseLockboxTokenPool_LockContext { + return { + $: 'LockReleaseLockboxTokenPool_LockContext', + ...args + } + }, + fromSlice(s: c.Slice): LockReleaseLockboxTokenPool_LockContext { + loadAndCheckPrefix32(s, 0x60fdb63b, 'LockReleaseLockboxTokenPool_LockContext'); + return { + $: 'LockReleaseLockboxTokenPool_LockContext', + forwardPayload: loadCellRef(s, TokenPool_LockOrBurnForwardPayload.fromSlice), + } + }, + store(self: LockReleaseLockboxTokenPool_LockContext, b: c.Builder): void { + b.storeUint(0x60fdb63b, 32); + storeCellRef(self.forwardPayload, b, TokenPool_LockOrBurnForwardPayload.store); + }, + toCell(self: LockReleaseLockboxTokenPool_LockContext): c.Cell { + return makeCellFrom(self, LockReleaseLockboxTokenPool_LockContext.store); + } +} + +/** + > struct (0x90230477) LockReleaseLockboxTokenPool_ReleaseContext { + > forwardPayload: Cell + > } + */ +export interface LockReleaseLockboxTokenPool_ReleaseContext { + readonly $: 'LockReleaseLockboxTokenPool_ReleaseContext' + forwardPayload: TokenPool_ReleaseOrMintForwardPayload +} + +export const LockReleaseLockboxTokenPool_ReleaseContext = { + PREFIX: 0x90230477, + + create(args: { + forwardPayload: TokenPool_ReleaseOrMintForwardPayload + }): LockReleaseLockboxTokenPool_ReleaseContext { + return { + $: 'LockReleaseLockboxTokenPool_ReleaseContext', + ...args + } + }, + fromSlice(s: c.Slice): LockReleaseLockboxTokenPool_ReleaseContext { + loadAndCheckPrefix32(s, 0x90230477, 'LockReleaseLockboxTokenPool_ReleaseContext'); + return { + $: 'LockReleaseLockboxTokenPool_ReleaseContext', + forwardPayload: loadCellRef(s, TokenPool_ReleaseOrMintForwardPayload.fromSlice), + } + }, + store(self: LockReleaseLockboxTokenPool_ReleaseContext, b: c.Builder): void { + b.storeUint(0x90230477, 32); + storeCellRef(self.forwardPayload, b, TokenPool_ReleaseOrMintForwardPayload.store); + }, + toCell(self: LockReleaseLockboxTokenPool_ReleaseContext): c.Cell { + return makeCellFrom(self, LockReleaseLockboxTokenPool_ReleaseContext.store); + } +} + /** > struct Storage { > poolData: Cell diff --git a/contracts/wrappers/gen/ccip/pools/LockReleaseTokenPool.ts b/contracts/wrappers/gen/ccip/pools/LockReleaseTokenPool.ts index 7db331372..094f731e3 100644 --- a/contracts/wrappers/gen/ccip/pools/LockReleaseTokenPool.ts +++ b/contracts/wrappers/gen/ccip/pools/LockReleaseTokenPool.ts @@ -4911,6 +4911,43 @@ export const TokenPool_RateLimitConfigured = { } } +/** + > struct (0xed696f9b) LockReleaseTokenPool_ReleaseContext { + > forwardPayload: Cell + > } + */ +export interface LockReleaseTokenPool_ReleaseContext { + readonly $: 'LockReleaseTokenPool_ReleaseContext' + forwardPayload: TokenPool_ReleaseOrMintForwardPayload +} + +export const LockReleaseTokenPool_ReleaseContext = { + PREFIX: 0xed696f9b, + + create(args: { + forwardPayload: TokenPool_ReleaseOrMintForwardPayload + }): LockReleaseTokenPool_ReleaseContext { + return { + $: 'LockReleaseTokenPool_ReleaseContext', + ...args + } + }, + fromSlice(s: c.Slice): LockReleaseTokenPool_ReleaseContext { + loadAndCheckPrefix32(s, 0xed696f9b, 'LockReleaseTokenPool_ReleaseContext'); + return { + $: 'LockReleaseTokenPool_ReleaseContext', + forwardPayload: loadCellRef(s, TokenPool_ReleaseOrMintForwardPayload.fromSlice), + } + }, + store(self: LockReleaseTokenPool_ReleaseContext, b: c.Builder): void { + b.storeUint(0xed696f9b, 32); + storeCellRef(self.forwardPayload, b, TokenPool_ReleaseOrMintForwardPayload.store); + }, + toCell(self: LockReleaseTokenPool_ReleaseContext): c.Cell { + return makeCellFrom(self, LockReleaseTokenPool_ReleaseContext.store); + } +} + /** > struct Storage { > poolData: Cell From 76d77ed467410e99f10c35c10f20f5490e1c0736 Mon Sep 17 00:00:00 2001 From: Kristijan Date: Tue, 25 Aug 2026 22:12:58 +0200 Subject: [PATCH 05/23] Use a set vs. map for allowedDepositNamespaces --- .../ccip/pools/lib/token_pool/entrypoint.tolk | 2 +- .../ccip/pools/lib/token_pool/messages.tolk | 2 +- .../ccip/pools/lib/token_pool/types.tolk | 2 +- .../e2e/CCIPSendWithTokenTransfer.spec.ts | 2 +- .../ccip/pools/BurnMintTokenPool.spec.ts | 2 +- .../pools/LockReleaseLockboxTokenPool.spec.ts | 2 +- .../ccip/pools/LockReleaseTokenPool.spec.ts | 2 +- contracts/wrappers/gen/ccip/MockTokenPool.ts | 42 ++++++++++++----- .../gen/ccip/pools/BurnMintTokenPool.ts | 47 ++++++++++++++----- .../ccip/pools/LockReleaseLockboxTokenPool.ts | 47 ++++++++++++++----- .../gen/ccip/pools/LockReleaseTokenPool.ts | 47 ++++++++++++++----- .../wrappers/gen/ccip/pools/TokenPool.ts | 47 ++++++++++++++----- 12 files changed, 173 insertions(+), 71 deletions(-) diff --git a/contracts/contracts/ccip/pools/lib/token_pool/entrypoint.tolk b/contracts/contracts/ccip/pools/lib/token_pool/entrypoint.tolk index 281bbefe9..04f2fe43f 100644 --- a/contracts/contracts/ccip/pools/lib/token_pool/entrypoint.tolk +++ b/contracts/contracts/ccip/pools/lib/token_pool/entrypoint.tolk @@ -453,7 +453,7 @@ fun TokenPool.setAllowedDepositNamespaces( mutate self, sender: address, queryId: uint64, - allowedDepositNamespaces: map, + allowedDepositNamespaces: map, ) { var adminConfig = self.data.adminConfig.load(); adminConfig.ownable.load().requireOwner(sender); diff --git a/contracts/contracts/ccip/pools/lib/token_pool/messages.tolk b/contracts/contracts/ccip/pools/lib/token_pool/messages.tolk index 1d3708456..02754125d 100644 --- a/contracts/contracts/ccip/pools/lib/token_pool/messages.tolk +++ b/contracts/contracts/ccip/pools/lib/token_pool/messages.tolk @@ -61,7 +61,7 @@ struct (0x89d602e5) TokenPool_DeployableCodeSet { /// `TokenPool_AdminConfig.deployableCode` is registered. Replaces any previous set. struct (0x84384142) TokenPool_SetAllowedDepositNamespaces { queryId: uint64; - allowedDepositNamespaces: map; + allowedDepositNamespaces: map; } /// Replied on `TokenPool_SetAllowedDepositNamespaces` to confirm tx and return excess to sender. diff --git a/contracts/contracts/ccip/pools/lib/token_pool/types.tolk b/contracts/contracts/ccip/pools/lib/token_pool/types.tolk index a7e46749f..8837bb467 100644 --- a/contracts/contracts/ccip/pools/lib/token_pool/types.tolk +++ b/contracts/contracts/ccip/pools/lib/token_pool/types.tolk @@ -30,7 +30,7 @@ struct TokenPool_DynamicConfig { /// @dev This field is part of dynamic config so it can be updated without redeploying the /// pool. Only namespaces whose deployable code is registered (see `TokenPool_AdminConfig`) /// are meaningful. - allowedDepositNamespaces: map = []; + allowedDepositNamespaces: map = []; } struct TokenPool_LocalPolicy { diff --git a/contracts/tests/ccip/e2e/CCIPSendWithTokenTransfer.spec.ts b/contracts/tests/ccip/e2e/CCIPSendWithTokenTransfer.spec.ts index 0c98226ab..1a8d3b6bc 100644 --- a/contracts/tests/ccip/e2e/CCIPSendWithTokenTransfer.spec.ts +++ b/contracts/tests/ccip/e2e/CCIPSendWithTokenTransfer.spec.ts @@ -162,7 +162,7 @@ describe('CCIPSend with token transfer (e2e)', () => { router: router.address, rateLimitAdmin: deployer.address, feeAdmin: deployer.address, - allowedDepositNamespaces: new Map(), + allowedDepositNamespaces: new Set(), }), jettonClient: tp.JettonClient.create({ masterAddress: minter.address, diff --git a/contracts/tests/ccip/pools/BurnMintTokenPool.spec.ts b/contracts/tests/ccip/pools/BurnMintTokenPool.spec.ts index 41b000f89..6d5b8ef38 100644 --- a/contracts/tests/ccip/pools/BurnMintTokenPool.spec.ts +++ b/contracts/tests/ccip/pools/BurnMintTokenPool.spec.ts @@ -121,7 +121,7 @@ describe('BurnMintTokenPool', () => { router: deployer.address, rateLimitAdmin: null, feeAdmin: null, - allowedDepositNamespaces: new Map(), + allowedDepositNamespaces: new Set(), }), jettonClient: JettonClient.create({ masterAddress: cctMinter.address, diff --git a/contracts/tests/ccip/pools/LockReleaseLockboxTokenPool.spec.ts b/contracts/tests/ccip/pools/LockReleaseLockboxTokenPool.spec.ts index 35017bf49..02020b55b 100644 --- a/contracts/tests/ccip/pools/LockReleaseLockboxTokenPool.spec.ts +++ b/contracts/tests/ccip/pools/LockReleaseLockboxTokenPool.spec.ts @@ -154,7 +154,7 @@ describe('LockReleaseLockboxTokenPool', () => { router: deployer.address, rateLimitAdmin: null, feeAdmin: null, - allowedDepositNamespaces: new Map(), + allowedDepositNamespaces: new Set(), }), jettonClient: JettonClient.create({ masterAddress: jettonMinter.address, diff --git a/contracts/tests/ccip/pools/LockReleaseTokenPool.spec.ts b/contracts/tests/ccip/pools/LockReleaseTokenPool.spec.ts index aa51bbc73..4693ea632 100644 --- a/contracts/tests/ccip/pools/LockReleaseTokenPool.spec.ts +++ b/contracts/tests/ccip/pools/LockReleaseTokenPool.spec.ts @@ -121,7 +121,7 @@ describe('LockReleaseTokenPool', () => { router: deployer.address, rateLimitAdmin: null, feeAdmin: null, - allowedDepositNamespaces: new Map(), + allowedDepositNamespaces: new Set(), }), jettonClient: JettonClient.create({ masterAddress: jettonMinter.address, diff --git a/contracts/wrappers/gen/ccip/MockTokenPool.ts b/contracts/wrappers/gen/ccip/MockTokenPool.ts index d8d1dcedc..4dfcba9a8 100644 --- a/contracts/wrappers/gen/ccip/MockTokenPool.ts +++ b/contracts/wrappers/gen/ccip/MockTokenPool.ts @@ -770,13 +770,13 @@ export const TokenPool_DeployableCodeSet = { /** > struct (0x84384142) TokenPool_SetAllowedDepositNamespaces { > queryId: uint64 - > allowedDepositNamespaces: map + > allowedDepositNamespaces: map > } */ export interface TokenPool_SetAllowedDepositNamespaces { readonly $: 'TokenPool_SetAllowedDepositNamespaces' queryId: uint64 - allowedDepositNamespaces: Map + allowedDepositNamespaces: Set } export const TokenPool_SetAllowedDepositNamespaces = { @@ -784,7 +784,7 @@ export const TokenPool_SetAllowedDepositNamespaces = { create(args: { queryId?: uint64 - allowedDepositNamespaces: Map + allowedDepositNamespaces: Set }): TokenPool_SetAllowedDepositNamespaces { return { $: 'TokenPool_SetAllowedDepositNamespaces', @@ -797,13 +797,22 @@ export const TokenPool_SetAllowedDepositNamespaces = { return { $: 'TokenPool_SetAllowedDepositNamespaces', queryId: s.loadUintBig(64), - allowedDepositNamespaces: dictToMap(c.Dictionary.load(c.Dictionary.Keys.BigUint(32), c.Dictionary.Values.Bool(), s)), + allowedDepositNamespaces: dictToSet(c.Dictionary.load(c.Dictionary.Keys.BigUint(32), createDictionaryValue<[]>( + (s) => [], + (v,b) => { {} } + ), s)), } }, store(self: TokenPool_SetAllowedDepositNamespaces, b: c.Builder): void { b.storeUint(0x84384142, 32); b.storeUint(self.queryId, 64); - b.storeDict(mapToDict(self.allowedDepositNamespaces, c.Dictionary.Keys.BigUint(32), c.Dictionary.Values.Bool()), c.Dictionary.Keys.BigUint(32), c.Dictionary.Values.Bool()); + b.storeDict(setToDict(self.allowedDepositNamespaces, c.Dictionary.Keys.BigUint(32), createDictionaryValue<[]>( + (s) => [], + (v,b) => { {} } + )), c.Dictionary.Keys.BigUint(32), createDictionaryValue<[]>( + (s) => [], + (v,b) => { {} } + )); }, toCell(self: TokenPool_SetAllowedDepositNamespaces): c.Cell { return makeCellFrom(self, TokenPool_SetAllowedDepositNamespaces.store); @@ -2933,7 +2942,7 @@ export const CursedSubjects = { > router: address > rateLimitAdmin: address? > feeAdmin: address? - > allowedDepositNamespaces: map + > allowedDepositNamespaces: map > } */ export interface TokenPool_DynamicConfig { @@ -2941,7 +2950,7 @@ export interface TokenPool_DynamicConfig { router: c.Address rateLimitAdmin: c.Address | null /* = null */ feeAdmin: c.Address | null - allowedDepositNamespaces: Map /* = [] as map */ + allowedDepositNamespaces: Set /* = [] as map */ } export const TokenPool_DynamicConfig = { @@ -2949,7 +2958,7 @@ export const TokenPool_DynamicConfig = { router: c.Address rateLimitAdmin?: c.Address | null /* = null */ feeAdmin: c.Address | null - allowedDepositNamespaces: Map /* = [] as map */ + allowedDepositNamespaces: Set /* = [] as map */ }): TokenPool_DynamicConfig { return { $: 'TokenPool_DynamicConfig', @@ -2963,14 +2972,23 @@ export const TokenPool_DynamicConfig = { router: s.loadAddress(), rateLimitAdmin: s.loadMaybeAddress(), feeAdmin: s.loadMaybeAddress(), - allowedDepositNamespaces: dictToMap(c.Dictionary.load(c.Dictionary.Keys.BigUint(32), c.Dictionary.Values.Bool(), s)), + allowedDepositNamespaces: dictToSet(c.Dictionary.load(c.Dictionary.Keys.BigUint(32), createDictionaryValue<[]>( + (s) => [], + (v,b) => { {} } + ), s)), } }, store(self: TokenPool_DynamicConfig, b: c.Builder): void { b.storeAddress(self.router); b.storeAddress(self.rateLimitAdmin); b.storeAddress(self.feeAdmin); - b.storeDict(mapToDict(self.allowedDepositNamespaces, c.Dictionary.Keys.BigUint(32), c.Dictionary.Values.Bool()), c.Dictionary.Keys.BigUint(32), c.Dictionary.Values.Bool()); + b.storeDict(setToDict(self.allowedDepositNamespaces, c.Dictionary.Keys.BigUint(32), createDictionaryValue<[]>( + (s) => [], + (v,b) => { {} } + )), c.Dictionary.Keys.BigUint(32), createDictionaryValue<[]>( + (s) => [], + (v,b) => { {} } + )); }, toCell(self: TokenPool_DynamicConfig): c.Cell { return makeCellFrom(self, TokenPool_DynamicConfig.store); @@ -4839,7 +4857,7 @@ export class MockTokenPool implements c.Contract { static createCellOfTokenPoolSetAllowedDepositNamespaces(body: { queryId?: uint64 - allowedDepositNamespaces: Map + allowedDepositNamespaces: Set }) { return TokenPool_SetAllowedDepositNamespaces.toCell(TokenPool_SetAllowedDepositNamespaces.create(body)); } @@ -5111,7 +5129,7 @@ export class MockTokenPool implements c.Contract { async sendTokenPoolSetAllowedDepositNamespaces(provider: ContractProvider, via: Sender, msgValue: coins, body: { queryId?: uint64 - allowedDepositNamespaces: Map + allowedDepositNamespaces: Set }, extraOptions?: ExtraSendOptions) { return provider.internal(via, { value: msgValue, diff --git a/contracts/wrappers/gen/ccip/pools/BurnMintTokenPool.ts b/contracts/wrappers/gen/ccip/pools/BurnMintTokenPool.ts index 05b3ec101..79001c0c5 100644 --- a/contracts/wrappers/gen/ccip/pools/BurnMintTokenPool.ts +++ b/contracts/wrappers/gen/ccip/pools/BurnMintTokenPool.ts @@ -1506,7 +1506,7 @@ export const TokenPool_Data = { > router: address > rateLimitAdmin: address? > feeAdmin: address? - > allowedDepositNamespaces: map + > allowedDepositNamespaces: map > } */ export interface TokenPool_DynamicConfig { @@ -1514,7 +1514,7 @@ export interface TokenPool_DynamicConfig { router: c.Address rateLimitAdmin: c.Address | null /* = null */ feeAdmin: c.Address | null - allowedDepositNamespaces: Map /* = [] as map */ + allowedDepositNamespaces: Set /* = [] as map */ } export const TokenPool_DynamicConfig = { @@ -1522,7 +1522,7 @@ export const TokenPool_DynamicConfig = { router: c.Address rateLimitAdmin?: c.Address | null /* = null */ feeAdmin: c.Address | null - allowedDepositNamespaces: Map /* = [] as map */ + allowedDepositNamespaces: Set /* = [] as map */ }): TokenPool_DynamicConfig { return { $: 'TokenPool_DynamicConfig', @@ -1536,14 +1536,23 @@ export const TokenPool_DynamicConfig = { router: s.loadAddress(), rateLimitAdmin: s.loadMaybeAddress(), feeAdmin: s.loadMaybeAddress(), - allowedDepositNamespaces: dictToMap(c.Dictionary.load(c.Dictionary.Keys.BigUint(32), c.Dictionary.Values.Bool(), s)), + allowedDepositNamespaces: dictToSet(c.Dictionary.load(c.Dictionary.Keys.BigUint(32), createDictionaryValue<[]>( + (s) => [], + (v,b) => { {} } + ), s)), } }, store(self: TokenPool_DynamicConfig, b: c.Builder): void { b.storeAddress(self.router); b.storeAddress(self.rateLimitAdmin); b.storeAddress(self.feeAdmin); - b.storeDict(mapToDict(self.allowedDepositNamespaces, c.Dictionary.Keys.BigUint(32), c.Dictionary.Values.Bool()), c.Dictionary.Keys.BigUint(32), c.Dictionary.Values.Bool()); + b.storeDict(setToDict(self.allowedDepositNamespaces, c.Dictionary.Keys.BigUint(32), createDictionaryValue<[]>( + (s) => [], + (v,b) => { {} } + )), c.Dictionary.Keys.BigUint(32), createDictionaryValue<[]>( + (s) => [], + (v,b) => { {} } + )); }, toCell(self: TokenPool_DynamicConfig): c.Cell { return makeCellFrom(self, TokenPool_DynamicConfig.store); @@ -2692,13 +2701,13 @@ export const TokenPool_DeployableCodeSet = { /** > struct (0x84384142) TokenPool_SetAllowedDepositNamespaces { > queryId: uint64 - > allowedDepositNamespaces: map + > allowedDepositNamespaces: map > } */ export interface TokenPool_SetAllowedDepositNamespaces { readonly $: 'TokenPool_SetAllowedDepositNamespaces' queryId: uint64 - allowedDepositNamespaces: Map + allowedDepositNamespaces: Set } export const TokenPool_SetAllowedDepositNamespaces = { @@ -2706,7 +2715,7 @@ export const TokenPool_SetAllowedDepositNamespaces = { create(args: { queryId?: uint64 - allowedDepositNamespaces: Map + allowedDepositNamespaces: Set }): TokenPool_SetAllowedDepositNamespaces { return { $: 'TokenPool_SetAllowedDepositNamespaces', @@ -2719,13 +2728,22 @@ export const TokenPool_SetAllowedDepositNamespaces = { return { $: 'TokenPool_SetAllowedDepositNamespaces', queryId: s.loadUintBig(64), - allowedDepositNamespaces: dictToMap(c.Dictionary.load(c.Dictionary.Keys.BigUint(32), c.Dictionary.Values.Bool(), s)), + allowedDepositNamespaces: dictToSet(c.Dictionary.load(c.Dictionary.Keys.BigUint(32), createDictionaryValue<[]>( + (s) => [], + (v,b) => { {} } + ), s)), } }, store(self: TokenPool_SetAllowedDepositNamespaces, b: c.Builder): void { b.storeUint(0x84384142, 32); b.storeUint(self.queryId, 64); - b.storeDict(mapToDict(self.allowedDepositNamespaces, c.Dictionary.Keys.BigUint(32), c.Dictionary.Values.Bool()), c.Dictionary.Keys.BigUint(32), c.Dictionary.Values.Bool()); + b.storeDict(setToDict(self.allowedDepositNamespaces, c.Dictionary.Keys.BigUint(32), createDictionaryValue<[]>( + (s) => [], + (v,b) => { {} } + )), c.Dictionary.Keys.BigUint(32), createDictionaryValue<[]>( + (s) => [], + (v,b) => { {} } + )); }, toCell(self: TokenPool_SetAllowedDepositNamespaces): c.Cell { return makeCellFrom(self, TokenPool_SetAllowedDepositNamespaces.store); @@ -5652,7 +5670,7 @@ export class BurnMintTokenPool implements c.Contract { static createCellOfTokenPoolSetAllowedDepositNamespaces(body: { queryId?: uint64 - allowedDepositNamespaces: Map + allowedDepositNamespaces: Set }) { return TokenPool_SetAllowedDepositNamespaces.toCell(TokenPool_SetAllowedDepositNamespaces.create(body)); } @@ -5951,7 +5969,7 @@ export class BurnMintTokenPool implements c.Contract { async sendTokenPoolSetAllowedDepositNamespaces(provider: ContractProvider, via: Sender, msgValue: coins, body: { queryId?: uint64 - allowedDepositNamespaces: Map + allowedDepositNamespaces: Set }, extraOptions?: ExtraSendOptions) { return provider.internal(via, { value: msgValue, @@ -6150,7 +6168,10 @@ export class BurnMintTokenPool implements c.Contract { feeAdmin: r.readNullable( (r) => r.readSlice().loadAddress() ), - allowedDepositNamespaces: dictToMap(r.readDictionary(c.Dictionary.Keys.BigUint(32), c.Dictionary.Values.Bool())), + allowedDepositNamespaces: dictToSet(r.readDictionary(c.Dictionary.Keys.BigUint(32), createDictionaryValue<[]>( + (s) => [], + (v,b) => { {} } + ))), }); } diff --git a/contracts/wrappers/gen/ccip/pools/LockReleaseLockboxTokenPool.ts b/contracts/wrappers/gen/ccip/pools/LockReleaseLockboxTokenPool.ts index bcd1285a1..815fe191a 100644 --- a/contracts/wrappers/gen/ccip/pools/LockReleaseLockboxTokenPool.ts +++ b/contracts/wrappers/gen/ccip/pools/LockReleaseLockboxTokenPool.ts @@ -1155,7 +1155,7 @@ export const TokenPool_Data = { > router: address > rateLimitAdmin: address? > feeAdmin: address? - > allowedDepositNamespaces: map + > allowedDepositNamespaces: map > } */ export interface TokenPool_DynamicConfig { @@ -1163,7 +1163,7 @@ export interface TokenPool_DynamicConfig { router: c.Address rateLimitAdmin: c.Address | null /* = null */ feeAdmin: c.Address | null - allowedDepositNamespaces: Map /* = [] as map */ + allowedDepositNamespaces: Set /* = [] as map */ } export const TokenPool_DynamicConfig = { @@ -1171,7 +1171,7 @@ export const TokenPool_DynamicConfig = { router: c.Address rateLimitAdmin?: c.Address | null /* = null */ feeAdmin: c.Address | null - allowedDepositNamespaces: Map /* = [] as map */ + allowedDepositNamespaces: Set /* = [] as map */ }): TokenPool_DynamicConfig { return { $: 'TokenPool_DynamicConfig', @@ -1185,14 +1185,23 @@ export const TokenPool_DynamicConfig = { router: s.loadAddress(), rateLimitAdmin: s.loadMaybeAddress(), feeAdmin: s.loadMaybeAddress(), - allowedDepositNamespaces: dictToMap(c.Dictionary.load(c.Dictionary.Keys.BigUint(32), c.Dictionary.Values.Bool(), s)), + allowedDepositNamespaces: dictToSet(c.Dictionary.load(c.Dictionary.Keys.BigUint(32), createDictionaryValue<[]>( + (s) => [], + (v,b) => { {} } + ), s)), } }, store(self: TokenPool_DynamicConfig, b: c.Builder): void { b.storeAddress(self.router); b.storeAddress(self.rateLimitAdmin); b.storeAddress(self.feeAdmin); - b.storeDict(mapToDict(self.allowedDepositNamespaces, c.Dictionary.Keys.BigUint(32), c.Dictionary.Values.Bool()), c.Dictionary.Keys.BigUint(32), c.Dictionary.Values.Bool()); + b.storeDict(setToDict(self.allowedDepositNamespaces, c.Dictionary.Keys.BigUint(32), createDictionaryValue<[]>( + (s) => [], + (v,b) => { {} } + )), c.Dictionary.Keys.BigUint(32), createDictionaryValue<[]>( + (s) => [], + (v,b) => { {} } + )); }, toCell(self: TokenPool_DynamicConfig): c.Cell { return makeCellFrom(self, TokenPool_DynamicConfig.store); @@ -2341,13 +2350,13 @@ export const TokenPool_DeployableCodeSet = { /** > struct (0x84384142) TokenPool_SetAllowedDepositNamespaces { > queryId: uint64 - > allowedDepositNamespaces: map + > allowedDepositNamespaces: map > } */ export interface TokenPool_SetAllowedDepositNamespaces { readonly $: 'TokenPool_SetAllowedDepositNamespaces' queryId: uint64 - allowedDepositNamespaces: Map + allowedDepositNamespaces: Set } export const TokenPool_SetAllowedDepositNamespaces = { @@ -2355,7 +2364,7 @@ export const TokenPool_SetAllowedDepositNamespaces = { create(args: { queryId?: uint64 - allowedDepositNamespaces: Map + allowedDepositNamespaces: Set }): TokenPool_SetAllowedDepositNamespaces { return { $: 'TokenPool_SetAllowedDepositNamespaces', @@ -2368,13 +2377,22 @@ export const TokenPool_SetAllowedDepositNamespaces = { return { $: 'TokenPool_SetAllowedDepositNamespaces', queryId: s.loadUintBig(64), - allowedDepositNamespaces: dictToMap(c.Dictionary.load(c.Dictionary.Keys.BigUint(32), c.Dictionary.Values.Bool(), s)), + allowedDepositNamespaces: dictToSet(c.Dictionary.load(c.Dictionary.Keys.BigUint(32), createDictionaryValue<[]>( + (s) => [], + (v,b) => { {} } + ), s)), } }, store(self: TokenPool_SetAllowedDepositNamespaces, b: c.Builder): void { b.storeUint(0x84384142, 32); b.storeUint(self.queryId, 64); - b.storeDict(mapToDict(self.allowedDepositNamespaces, c.Dictionary.Keys.BigUint(32), c.Dictionary.Values.Bool()), c.Dictionary.Keys.BigUint(32), c.Dictionary.Values.Bool()); + b.storeDict(setToDict(self.allowedDepositNamespaces, c.Dictionary.Keys.BigUint(32), createDictionaryValue<[]>( + (s) => [], + (v,b) => { {} } + )), c.Dictionary.Keys.BigUint(32), createDictionaryValue<[]>( + (s) => [], + (v,b) => { {} } + )); }, toCell(self: TokenPool_SetAllowedDepositNamespaces): c.Cell { return makeCellFrom(self, TokenPool_SetAllowedDepositNamespaces.store); @@ -5624,7 +5642,7 @@ export class LockReleaseLockboxTokenPool implements c.Contract { static createCellOfTokenPoolSetAllowedDepositNamespaces(body: { queryId?: uint64 - allowedDepositNamespaces: Map + allowedDepositNamespaces: Set }) { return TokenPool_SetAllowedDepositNamespaces.toCell(TokenPool_SetAllowedDepositNamespaces.create(body)); } @@ -5935,7 +5953,7 @@ export class LockReleaseLockboxTokenPool implements c.Contract { async sendTokenPoolSetAllowedDepositNamespaces(provider: ContractProvider, via: Sender, msgValue: coins, body: { queryId?: uint64 - allowedDepositNamespaces: Map + allowedDepositNamespaces: Set }, extraOptions?: ExtraSendOptions) { return provider.internal(via, { value: msgValue, @@ -6155,7 +6173,10 @@ export class LockReleaseLockboxTokenPool implements c.Contract { feeAdmin: r.readNullable( (r) => r.readSlice().loadAddress() ), - allowedDepositNamespaces: dictToMap(r.readDictionary(c.Dictionary.Keys.BigUint(32), c.Dictionary.Values.Bool())), + allowedDepositNamespaces: dictToSet(r.readDictionary(c.Dictionary.Keys.BigUint(32), createDictionaryValue<[]>( + (s) => [], + (v,b) => { {} } + ))), }); } diff --git a/contracts/wrappers/gen/ccip/pools/LockReleaseTokenPool.ts b/contracts/wrappers/gen/ccip/pools/LockReleaseTokenPool.ts index 094f731e3..07ff0c1e8 100644 --- a/contracts/wrappers/gen/ccip/pools/LockReleaseTokenPool.ts +++ b/contracts/wrappers/gen/ccip/pools/LockReleaseTokenPool.ts @@ -1277,7 +1277,7 @@ export const TokenPool_Data = { > router: address > rateLimitAdmin: address? > feeAdmin: address? - > allowedDepositNamespaces: map + > allowedDepositNamespaces: map > } */ export interface TokenPool_DynamicConfig { @@ -1285,7 +1285,7 @@ export interface TokenPool_DynamicConfig { router: c.Address rateLimitAdmin: c.Address | null /* = null */ feeAdmin: c.Address | null - allowedDepositNamespaces: Map /* = [] as map */ + allowedDepositNamespaces: Set /* = [] as map */ } export const TokenPool_DynamicConfig = { @@ -1293,7 +1293,7 @@ export const TokenPool_DynamicConfig = { router: c.Address rateLimitAdmin?: c.Address | null /* = null */ feeAdmin: c.Address | null - allowedDepositNamespaces: Map /* = [] as map */ + allowedDepositNamespaces: Set /* = [] as map */ }): TokenPool_DynamicConfig { return { $: 'TokenPool_DynamicConfig', @@ -1307,14 +1307,23 @@ export const TokenPool_DynamicConfig = { router: s.loadAddress(), rateLimitAdmin: s.loadMaybeAddress(), feeAdmin: s.loadMaybeAddress(), - allowedDepositNamespaces: dictToMap(c.Dictionary.load(c.Dictionary.Keys.BigUint(32), c.Dictionary.Values.Bool(), s)), + allowedDepositNamespaces: dictToSet(c.Dictionary.load(c.Dictionary.Keys.BigUint(32), createDictionaryValue<[]>( + (s) => [], + (v,b) => { {} } + ), s)), } }, store(self: TokenPool_DynamicConfig, b: c.Builder): void { b.storeAddress(self.router); b.storeAddress(self.rateLimitAdmin); b.storeAddress(self.feeAdmin); - b.storeDict(mapToDict(self.allowedDepositNamespaces, c.Dictionary.Keys.BigUint(32), c.Dictionary.Values.Bool()), c.Dictionary.Keys.BigUint(32), c.Dictionary.Values.Bool()); + b.storeDict(setToDict(self.allowedDepositNamespaces, c.Dictionary.Keys.BigUint(32), createDictionaryValue<[]>( + (s) => [], + (v,b) => { {} } + )), c.Dictionary.Keys.BigUint(32), createDictionaryValue<[]>( + (s) => [], + (v,b) => { {} } + )); }, toCell(self: TokenPool_DynamicConfig): c.Cell { return makeCellFrom(self, TokenPool_DynamicConfig.store); @@ -2463,13 +2472,13 @@ export const TokenPool_DeployableCodeSet = { /** > struct (0x84384142) TokenPool_SetAllowedDepositNamespaces { > queryId: uint64 - > allowedDepositNamespaces: map + > allowedDepositNamespaces: map > } */ export interface TokenPool_SetAllowedDepositNamespaces { readonly $: 'TokenPool_SetAllowedDepositNamespaces' queryId: uint64 - allowedDepositNamespaces: Map + allowedDepositNamespaces: Set } export const TokenPool_SetAllowedDepositNamespaces = { @@ -2477,7 +2486,7 @@ export const TokenPool_SetAllowedDepositNamespaces = { create(args: { queryId?: uint64 - allowedDepositNamespaces: Map + allowedDepositNamespaces: Set }): TokenPool_SetAllowedDepositNamespaces { return { $: 'TokenPool_SetAllowedDepositNamespaces', @@ -2490,13 +2499,22 @@ export const TokenPool_SetAllowedDepositNamespaces = { return { $: 'TokenPool_SetAllowedDepositNamespaces', queryId: s.loadUintBig(64), - allowedDepositNamespaces: dictToMap(c.Dictionary.load(c.Dictionary.Keys.BigUint(32), c.Dictionary.Values.Bool(), s)), + allowedDepositNamespaces: dictToSet(c.Dictionary.load(c.Dictionary.Keys.BigUint(32), createDictionaryValue<[]>( + (s) => [], + (v,b) => { {} } + ), s)), } }, store(self: TokenPool_SetAllowedDepositNamespaces, b: c.Builder): void { b.storeUint(0x84384142, 32); b.storeUint(self.queryId, 64); - b.storeDict(mapToDict(self.allowedDepositNamespaces, c.Dictionary.Keys.BigUint(32), c.Dictionary.Values.Bool()), c.Dictionary.Keys.BigUint(32), c.Dictionary.Values.Bool()); + b.storeDict(setToDict(self.allowedDepositNamespaces, c.Dictionary.Keys.BigUint(32), createDictionaryValue<[]>( + (s) => [], + (v,b) => { {} } + )), c.Dictionary.Keys.BigUint(32), createDictionaryValue<[]>( + (s) => [], + (v,b) => { {} } + )); }, toCell(self: TokenPool_SetAllowedDepositNamespaces): c.Cell { return makeCellFrom(self, TokenPool_SetAllowedDepositNamespaces.store); @@ -5348,7 +5366,7 @@ export class LockReleaseTokenPool implements c.Contract { static createCellOfTokenPoolSetAllowedDepositNamespaces(body: { queryId?: uint64 - allowedDepositNamespaces: Map + allowedDepositNamespaces: Set }) { return TokenPool_SetAllowedDepositNamespaces.toCell(TokenPool_SetAllowedDepositNamespaces.create(body)); } @@ -5639,7 +5657,7 @@ export class LockReleaseTokenPool implements c.Contract { async sendTokenPoolSetAllowedDepositNamespaces(provider: ContractProvider, via: Sender, msgValue: coins, body: { queryId?: uint64 - allowedDepositNamespaces: Map + allowedDepositNamespaces: Set }, extraOptions?: ExtraSendOptions) { return provider.internal(via, { value: msgValue, @@ -5833,7 +5851,10 @@ export class LockReleaseTokenPool implements c.Contract { feeAdmin: r.readNullable( (r) => r.readSlice().loadAddress() ), - allowedDepositNamespaces: dictToMap(r.readDictionary(c.Dictionary.Keys.BigUint(32), c.Dictionary.Values.Bool())), + allowedDepositNamespaces: dictToSet(r.readDictionary(c.Dictionary.Keys.BigUint(32), createDictionaryValue<[]>( + (s) => [], + (v,b) => { {} } + ))), }); } diff --git a/contracts/wrappers/gen/ccip/pools/TokenPool.ts b/contracts/wrappers/gen/ccip/pools/TokenPool.ts index dbbc23cce..914dc55da 100644 --- a/contracts/wrappers/gen/ccip/pools/TokenPool.ts +++ b/contracts/wrappers/gen/ccip/pools/TokenPool.ts @@ -349,7 +349,7 @@ export const CrossChainAddress = { > router: address > rateLimitAdmin: address? > feeAdmin: address? - > allowedDepositNamespaces: map + > allowedDepositNamespaces: map > } */ export interface TokenPool_DynamicConfig { @@ -357,7 +357,7 @@ export interface TokenPool_DynamicConfig { router: c.Address rateLimitAdmin: c.Address | null /* = null */ feeAdmin: c.Address | null - allowedDepositNamespaces: Map /* = [] as map */ + allowedDepositNamespaces: Set /* = [] as map */ } export const TokenPool_DynamicConfig = { @@ -365,7 +365,7 @@ export const TokenPool_DynamicConfig = { router: c.Address rateLimitAdmin?: c.Address | null /* = null */ feeAdmin: c.Address | null - allowedDepositNamespaces: Map /* = [] as map */ + allowedDepositNamespaces: Set /* = [] as map */ }): TokenPool_DynamicConfig { return { $: 'TokenPool_DynamicConfig', @@ -379,14 +379,23 @@ export const TokenPool_DynamicConfig = { router: s.loadAddress(), rateLimitAdmin: s.loadMaybeAddress(), feeAdmin: s.loadMaybeAddress(), - allowedDepositNamespaces: dictToMap(c.Dictionary.load(c.Dictionary.Keys.BigUint(32), c.Dictionary.Values.Bool(), s)), + allowedDepositNamespaces: dictToSet(c.Dictionary.load(c.Dictionary.Keys.BigUint(32), createDictionaryValue<[]>( + (s) => [], + (v,b) => { {} } + ), s)), } }, store(self: TokenPool_DynamicConfig, b: c.Builder): void { b.storeAddress(self.router); b.storeAddress(self.rateLimitAdmin); b.storeAddress(self.feeAdmin); - b.storeDict(mapToDict(self.allowedDepositNamespaces, c.Dictionary.Keys.BigUint(32), c.Dictionary.Values.Bool()), c.Dictionary.Keys.BigUint(32), c.Dictionary.Values.Bool()); + b.storeDict(setToDict(self.allowedDepositNamespaces, c.Dictionary.Keys.BigUint(32), createDictionaryValue<[]>( + (s) => [], + (v,b) => { {} } + )), c.Dictionary.Keys.BigUint(32), createDictionaryValue<[]>( + (s) => [], + (v,b) => { {} } + )); }, toCell(self: TokenPool_DynamicConfig): c.Cell { return makeCellFrom(self, TokenPool_DynamicConfig.store); @@ -1656,13 +1665,13 @@ export const TokenPool_DeployableCodeSet = { /** > struct (0x84384142) TokenPool_SetAllowedDepositNamespaces { > queryId: uint64 - > allowedDepositNamespaces: map + > allowedDepositNamespaces: map > } */ export interface TokenPool_SetAllowedDepositNamespaces { readonly $: 'TokenPool_SetAllowedDepositNamespaces' queryId: uint64 - allowedDepositNamespaces: Map + allowedDepositNamespaces: Set } export const TokenPool_SetAllowedDepositNamespaces = { @@ -1670,7 +1679,7 @@ export const TokenPool_SetAllowedDepositNamespaces = { create(args: { queryId?: uint64 - allowedDepositNamespaces: Map + allowedDepositNamespaces: Set }): TokenPool_SetAllowedDepositNamespaces { return { $: 'TokenPool_SetAllowedDepositNamespaces', @@ -1683,13 +1692,22 @@ export const TokenPool_SetAllowedDepositNamespaces = { return { $: 'TokenPool_SetAllowedDepositNamespaces', queryId: s.loadUintBig(64), - allowedDepositNamespaces: dictToMap(c.Dictionary.load(c.Dictionary.Keys.BigUint(32), c.Dictionary.Values.Bool(), s)), + allowedDepositNamespaces: dictToSet(c.Dictionary.load(c.Dictionary.Keys.BigUint(32), createDictionaryValue<[]>( + (s) => [], + (v,b) => { {} } + ), s)), } }, store(self: TokenPool_SetAllowedDepositNamespaces, b: c.Builder): void { b.storeUint(0x84384142, 32); b.storeUint(self.queryId, 64); - b.storeDict(mapToDict(self.allowedDepositNamespaces, c.Dictionary.Keys.BigUint(32), c.Dictionary.Values.Bool()), c.Dictionary.Keys.BigUint(32), c.Dictionary.Values.Bool()); + b.storeDict(setToDict(self.allowedDepositNamespaces, c.Dictionary.Keys.BigUint(32), createDictionaryValue<[]>( + (s) => [], + (v,b) => { {} } + )), c.Dictionary.Keys.BigUint(32), createDictionaryValue<[]>( + (s) => [], + (v,b) => { {} } + )); }, toCell(self: TokenPool_SetAllowedDepositNamespaces): c.Cell { return makeCellFrom(self, TokenPool_SetAllowedDepositNamespaces.store); @@ -4464,7 +4482,7 @@ export class TokenPool implements c.Contract { static createCellOfTokenPoolSetAllowedDepositNamespaces(body: { queryId?: uint64 - allowedDepositNamespaces: Map + allowedDepositNamespaces: Set }) { return TokenPool_SetAllowedDepositNamespaces.toCell(TokenPool_SetAllowedDepositNamespaces.create(body)); } @@ -4736,7 +4754,7 @@ export class TokenPool implements c.Contract { async sendTokenPoolSetAllowedDepositNamespaces(provider: ContractProvider, via: Sender, msgValue: coins, body: { queryId?: uint64 - allowedDepositNamespaces: Map + allowedDepositNamespaces: Set }, extraOptions?: ExtraSendOptions) { return provider.internal(via, { value: msgValue, @@ -4885,7 +4903,10 @@ export class TokenPool implements c.Contract { feeAdmin: r.readNullable( (r) => r.readSlice().loadAddress() ), - allowedDepositNamespaces: dictToMap(r.readDictionary(c.Dictionary.Keys.BigUint(32), c.Dictionary.Values.Bool())), + allowedDepositNamespaces: dictToSet(r.readDictionary(c.Dictionary.Keys.BigUint(32), createDictionaryValue<[]>( + (s) => [], + (v,b) => { {} } + ))), }); } From e9417d37ace64ec5a87d9c0b579447749fb1e76a Mon Sep 17 00:00:00 2001 From: Kristijan Date: Tue, 25 Aug 2026 22:29:07 +0200 Subject: [PATCH 06/23] burn/mint tp - remove unnecessary wallet addr check on excess --- contracts/contracts/ccip/pools/burn_mint/contract.tolk | 4 +--- contracts/wrappers/gen/ccip/pools/BurnMintTokenPool.ts | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/contracts/contracts/ccip/pools/burn_mint/contract.tolk b/contracts/contracts/ccip/pools/burn_mint/contract.tolk index efe072e67..088ef3267 100644 --- a/contracts/contracts/ccip/pools/burn_mint/contract.tolk +++ b/contracts/contracts/ccip/pools/burn_mint/contract.tolk @@ -256,7 +256,7 @@ fun onClaimMinterAdmin( /// The minter relays the burn continuation context (the `BurnMintTokenPool_BurnContext` /// embedded by this pool in `CCT_AskToBurn.forwardPayload`) back to this pool, which then /// finalizes the lock/burn. Context-less excess signals (e.g. from the mint/transfer paths) -/// are ignored. Mint still finalizes via OffRampAccount. +/// are ignored. fun onCCTReturnExcessesBack( mutate st: Storage, sender: address, @@ -275,8 +275,6 @@ fun onCCTReturnExcessesBack( val context = lazy BurnMintTokenPool_BurnContext.fromCell(msg.forwardPayload!); val operation = lazy context.forwardPayload.load(); - // TODO: is this check necessary? - assert(context.wallet == pool.data.jettonClient().walletAddress(), BurnMintTokenPool_Error.UnexpectedBurnBounce); pool.onLockOrBurnTransferFinalize(operation); st.poolData = pool.data.toCell(); diff --git a/contracts/wrappers/gen/ccip/pools/BurnMintTokenPool.ts b/contracts/wrappers/gen/ccip/pools/BurnMintTokenPool.ts index 79001c0c5..4755460c3 100644 --- a/contracts/wrappers/gen/ccip/pools/BurnMintTokenPool.ts +++ b/contracts/wrappers/gen/ccip/pools/BurnMintTokenPool.ts @@ -5448,7 +5448,7 @@ function calculateDeployedAddress(code: c.Cell, data: c.Cell, options: DeployedA } export class BurnMintTokenPool implements c.Contract { - static CodeCell = c.Cell.fromBase64('te6ccgICAQEAAQAAP0oAAAEU/wD0pBP0vPLICwABAgFiAAIAAwICygAEAAUCASAA1wDYAgEgAAYABwIBSAC3ALgCASAACAAJAgEgAH0AfgIBIAAbABwCASAACgALAgEgAAwADQIBIAASABMCASAADgAPAgEgABAAEQBpCDCTZMwcHHgcXqTIsIAjiAicbDAAZyE/yKpBCG+8oRmqAHeAqsAIMIAlFEgqALeAugwMXCAAjwwI7ORf5UgwADDAOKRMOBTUvgjJ6EQaF40EDdIgFKA8As1UWW5lYE/rfLw4FM0uY4QXwUglYE/rvLw4TCBP67y8OBQNKFQNIABZDAjs5F/lSDAAMMA4pEw4FNS+CMnoRBoXjQQN0iAUoDwCzVQRaBQBbYIREQDgADUII4VNly8lYE/rPLw4FFSqKAUtgj4I1BE4FuACASAAFAAVAgEgABcAGAD1GwzMyDQAsj6UswSzMkB1ywn0+0iJPK/1ws/IdDUMddM0PoAMfoAMIIK+vCA+CjIz5LowKkeUmD6UiXPFMnIz5LowKkeUnD6UhbMycjPkWV8HvIVyz9QA/oCEvpUE/QA9ADJyM+FiBP6UgH6As+Bc/oCcc8LZczJcfsAgAfUggDKBQnDABny9CTQ0/8x10zQyM+Q1H3fjifPCz8WzBTLHxL6VMkByMsfWPoCUAX6AskDyPpSFMwSzMkC+kgw+ChtyEAzgQEL9EEhyPpSEvpS9ADJI8jPks9UjYYUzMnIz4mIAVMkyM+E0MzM+RbPC//PhBBz+gKBAIyAAFgAwzwtrFMzMz5GiQogWyz/0AMmAQPsAgQCHAfcMiFukl8D4CTQNQTU1NMH9AT0BNGCAMn+JdDUMfpQMdQx+kgwGMcFF/L0ggDJ/vgoGccFGPL0A9DXLCXRgVI88r/6SNdM0IIAr8gk0NQx+lAx1DH6SNdM+CjIz4QC+lIS+lLJAcjPhNDMzPkWyM+KAEDL/89QE8cFEvL0gABkDpTtou37INcsJ9PtIiSebCHTP9TTH/QE+lAw8BCPs9csIEeX/byPKNcsJTb9MRyOndcsI5sWhOSOEjHTP/oA+lBVA/GAF4AbgBTbOOMO4w3jDeJ/gAEAAQQBCAfD6SNTXTAHQAdAB1ywn0+0iJPK/0z/U0x8x9AH6UDAB0NP/MdTR0NQx0z/6SDH6ADH6SNEE+gAx+gDU10wGyPpSF/pSIfoCycjPjxgABIIQN91vbs8L93DPC2ETyz8SzMlw+wAhbpJfBeMOAcjMzMsHE/QAEvQAyQEAGgBCBMjME8zJyM+FiBP6UoIQ9DKk488Ljss/zAH6AsmAQPsAAgFIAB0AHgIBWAA9AD4C9z4keMC7UTQ1NTRIdDU1NMH9AT0BNGBAIdtbW1tkvANAG1tbW2S8AwAbYEAiFYTVhP4kviXAxEQAxAvED4QLRA8ECsQOhApEDgQJxA2XiIQI1YY8A8/XwwCjh44OAfDAJE0kzUQNOICyMzMywf0ABL0AMnIzMzJ7VTgXweAAHwAgAak7aLt+9csJ5Db7QyORNcsJ88U8lSUW3DbMeGCAMKKI26z8vQhggDCigTHBRPy9CBtA9cLP4sCAcjLPxX6UhL6UsnIz4cgFM5xzwthE8zJcPsA4w1/gADwEdu1E0NTU0QLXLCf////08r/U0wcx1wofAdDXLCB8U/Us4wLXLCLK+D3k4wLXLCAAAACs4wLXLCNEhRAsACEAIgAjACQDjCLXLCHMTHJs4wLXLCapk7bcjhczAtM/+kj0BfiSEEVVIPAOAcjMzMntVODXLCbQIxhk4wLXLCWn8uBk4wJfA4QPAccA8vQANQA2ADcA+jEh0NTUMdMHMfQEMfQEMdHQ1DH6UDHUMfpI10yCAK/I+JL4KCTIz4QCEvpS+lLJI8jPhNDMzPkWyM+KAEDL/89QxwXy9ALTP/oA+kj6UPQE+gD4KMjPhAL6Uhj6UslQCMjPhNDMzPkWyM+KAEDL/89QB1UF8AYwyMzMye1UAf4x0z8x+gAx+lAx9AWCAK/IIW6z8vTQ1ywl0YFSPPK/+kjXTIIAr8j4klADxwUS8vTQIdBsEtTU0wf0BPQE0QX6SDHU10wh0NcsJ9PtIiTyv9M/10zQ0/8x10zQ0z8x+kj6ADCCEAX14QAp0NQx+lAx1DH6SNdM+CjIz4QC+lISACUB/jGCAK/J+JIj0NTUMdMHMfQEMfQEMdHQ1DH6UDHUMfpIMMcF8vTXTNDXLCC8aijM8r/TPzH6ADH6UDH6UDH6ADH0BCFumDEgxwCSMG3gktHQ4iBus5PIzsmSMG3iggCvySFus/L00NcsJZ6pGwzyv9dM0CHQbBLU1NMH9AT0BNEAKwIa4wLXLCYqO2lc4wLyPwAsAC0D/vpSyQHIz4TQzMz5FsjPigBAy//PUG2LBMjPkD4p+pYXyz9QBPoCUkD6UhT6VBL0AM+EIBPOycjPhQgS+lJY+gJxzwtqzMlz+wAh0NcsJ9PtIiTyv9M/MdTXCx8B0NP/MddM0ALQAtcLPwL6ADH6ADAB4w/Q1ywn0+0iJPK/0z8AJgAnACgC/oIAyfhTJIBA9A5voRLy9NT0BNTU0SDQ1NTRAdDTd9M/0gDTd9N30SKON18GAdDU1NEB0NN30z/SANN303fRL9DUMfpQMdQx+kgwUqDwCgTIy3cTyz/KAMt3y3fJyMzMyQHjDQPIzBL0AMzMVCAlgED0QybQ1DH6UDHUMfpIMAIAKQAqAfqCAMn4UySAQPQOb6ES8vTU9ATU1NEB0NTU0QHQ03fTP9IA03fTd9Ev0NQx+lAx1DH6SDBSoPAKBMjLdxPLP8oAy3fLd8nIzMzJA8jMEvQAEszMVCAlgED0QybQ1DH6UDHUMfpIMALIyz8S+lJQA/oCycjPjxgABIIQMOur2wAzAHrUMdMfMfQB+lAwIG6RW44ayM+FCPpSghA0dupyzwuOyz/Pir8iyYBA+wDiA8jMEszLB/QA9ADJyMzMye1UAFQ2L9DUMfpQMdQx+kgwEEUQNEEwVCag8AoEyMt3E8s/ygDLd8t3ycjMzMkARsjLPxL6UlAD+gLJyM+PGAAEghAUH34szwv3cc8LYczJcPsAAvYF+kgx1NdMIdDXLCGo+78c8r/TPzHU1wsfAdDT/zHXTNAC0AL6SDHXCz8C0x8x+gAwAeMPBMjME8zLB/QAEvQAyQHQ1ywhqPu/HPK/0z/THzH6UDAgbpFbjhrIz4UI+lKCEO8Ms27PC47LP8+KvybJgED7AOLIzMzJ7VQALgAvA/4x0z8x9AWCAK/MIW6z8vTQ1ywlnqkbDPK/1NHQIdBsEtTU0wf0BPQE0QX6SDHU10wh0NcsIaj7vxzyv9M/MdTXCx8B0NP/MddM0ALQAvpIMdcLPwLTHzH6ADAB4w8EyMwTzMsH9AAS9ADJAdDXLCGo+78c8r/TP9MfMfpQMCBuAC4ALwAwAfwi0NTU0wf0BPQE0YEAh21tbW2S8A0AbW1tbZLwDABtgQCIVhURE9M/+kjTP/oA0x/TByHCAfJF9AT6SPQFVhoRGVYaERkhERkhERkhERkRGBEiERgRFxEgERcBERYBERURFBEiERQRExEgERMBERIBEREREBEiERAPESAPUO0ANAL+ggDJ+FMkgED0Dm+hEvL01PQE1NTRINDU1NHQ03fTP9IA03fTd9EijjdfBgHQ1NTR0NN30z/SANN303fRL9DUMfpQMdQx+kgwUqDwCgTIy3cTyz/KAMt3y3fJAcjMzMkB4w0DyMwS9ADMzFQgJYBA9EMm0NQx+lAx1DH6SDACyAAxADIB+oIAyfhTJIBA9A5voRLy9NT0BNTU0QHQ1NTR0NN30z/SANN303fRL9DUMfpQMdQx+kgwUqDwCgTIy3cTyz/KAMt3y3fJAcjMzMkDyMwS9AASzMxUICWAQPRDJtDUMfpQMdQx+kgwAsjLPxL6UlAD+gLJyM+PGAAEghB0Ca2PADMASpFbjhrIz4UI+lKCEO8Ms27PC47LP8+KvzLJgED7AOLIzMzJ7VQAVjYv0NQx+lAx1DH6SDAQRRA0QTBUJqDwCgTIy3cTyz/KAMt3y3fJAcjMzMkARMs/EvpSUAP6AsnIz48YAASCEDR//HzPC/dxzwthzMlw+wAAGM8L93HPC2HMyXD7AABoDBEiDAsRIAtQqQgRIggHESAHUGUEESIEAxEgA1gRIfAoAcjMzBPLBxL0APQAycjMzMntVAD2MwLXCz/4kiLQ1NQx0wcx9AQx9AQx0dDU+lAx1DH6SDHUMdMfMfpQMfQEMdHQ+kj6UDHRAYIAwogCxwXy9IIK+vCAItDU1DHTBzH0BDH0BDHR0NQx+lAx1DH6SDDIz4WI+lIB+gKCEPuI4RnPC4rLP8mAQPsAyMzMye1UAfgzAtM/9AX4koIAr8oibrPy9CHQ1ywlnqkbDPK/1NHQ1DHXTNAi0NcsJZ6pGwzyv9TR0NdM0NcsIaj7vxzyv9dM0NP/MddM0PpIMCXQ1NQx0wcx9AQx9AQx0dDUMfpQMdQx+kgw+ChtyEBEgQEL9EEiyPpSUjD6UvQAyVKAADgC/jMC10z4kgHQ+kj6ADH0BDH6ADHTPzHTHzHU0dDXLCObFoTk8r/TPzH6ADH6UIIAr8sCbhLy9PQEIW6YMSDHAJIwbeCS0dDiIG6zk8jOyZIwbeKCAK/LIW6z8vQg0NcsJZ6pGwzyv9dM0AHQ1ywlnqkbDPK/1NHQ10zQidcn8r8AsAA5AO6CAK/KAsjPhNDMzPkWyM+KAEDL/89QJccF8vQC0x8x+gAwghAF9eEAIG2CCJiWgAjI9ADPUMjPkF41FGYqzws/UAX6AvpUFPpUUAb6As7JyM+FiBP6UlAE+gLPgXP6AoAVzwuFFMs/+lIB+gLMyXH7AMjMzMntVAH+10zQ0/8x10zQ+kgwJNDU1DHTBzH0BDH0BDHR0NQx+lAx1DH6SNdM+ChtyEBVgQEL9EEjyPpSFPpSE/QAySeCAK/LUyHIz4TQzMz5FsjPigBAy//PUBjHBRfy9FAFyM+E0MzM+RbIz4oAQMv/z1DIz4QC+lIU+lLJUAPIz4TQzAA6AfrM+RbIz4oAQMv/z1ABggCvywLHBfL0IdBsEtTU0wf0BPQE0QX6SDHU10wB0NcsIaj7vxzyv9M/1NMfMfpQMAHQ0/8x10zQA9AD+kjTP9P/MfpIMAXTHzH6ADH6ADD4KAPI+lLJBsj6UhP6UiL6AhXMycjPjxgABIIQ6cAMlwA7AJDPC/dwzwthFcs/FMzJcPsAIG6SXwOOHshQA/oCycjPhQgT+lKCEODogvXPC47LP8zJgED7AOIDyMwSzMsH9AD0AMnIzMzJ7VQAZmwS0z/6SDCCAMKIUTTHBRPy9IIAwolTI8cFs/L0IYsCyM+HIM5wzwthEss/EvpSyXD7AAH1FR2VFR2VCZsYfQEIW6YMSDHAJIwbeCS0dDiIG6VMG1tbXCOFdcsIWsLAGSX+kj0BIEAheAwbW1tcOKUIW7DAJF/4pZfA21tbXCOFSHQ1ywgDLUDvDGTgQCF4F8DbW1tcOJsIZNfCXDhCMj6Us+QPin6lhfLP1AF+gITgAD8AVwhbpJbcOCCaQAAAAAAAAAAAAAAAAAAASKDBvQOb6Exklt/4AGDBvQOb6ExgADr6UvpU9AAB+gLOycjPhQgS+lJxzwtuzMmAQPsAfwLs1ywhqPu/HI7r1ywk8VNbNI5gbCHTPzHXTFYV0NQx+lAx1DH6SDHUMdMfMfpQ9AQx0YIAyf4hbrOVA8cFwwCTMTJw4hLy9ND6SNTU0QHQAdAB1ywhqPu/HPK/0z/U0x/6UDAE0x/6APoAMBBWEEUQNPAh4w7jDQBDAEQD+mwh0z8x10xWFdDUMfpQMdQx+kgx1DHTHzH6UPQEMdGCAMn+IW6zlQPHBcMAkzEycOIS8vTQ+kgx1NTRIdDXLCfT7SIk8r/TPzHU1wsfAdDT/zHXTNAC0ALXCz8C+gAx+gAwAeMP0NcsJ9PtIiTyv9M/1DHTHzH0AfpQMCBuAHUAdgB3Af5sIdM/MddMVhXQ1DH6UDHUMfpIMdQx0x8x+lD0BDHRggDJ/iFus5UDxwXDAJMxMnDiEvL00PpI1NTRAdAB0AHXLCfT7SIk8r/TP9TTH/QE+lAwBfoA+gDU10zIz5Pp9pESKM8LPxfMFcsfE/QAUmD6VMnIWPoCWPoCEswSzMnIAHsDeNcsIQ847DyPMdcsJio7aVyOHGwh0z/6SNM/+gDTH9MHIcIB8kX0BPpI9AVt8CKPCdcsJpFKJqzjD+LjDQBFAEYARwAYbCHTP9TTH/pQMPAbAf5sIdM/+kjTP/oA0x/TByHCAfJF9AT0BVYc0NQx+lAx1DH6SDHUMdMf+lAx9AQx0VJA8BWCAMn9Vh3Q1DH6UDHUMfpIMCjHBfL0ggDJ+SZWG4BA9A5voTHy9FYcVhxWHFYcVhxWHFYcVhxWHFYcVhxWHFYcVhxWHFYcVhxWHFYcAEgDKNcsIYMJWLyPCdcsIre56bzjD+MNAEkASgBLA/hsIdM/MddMVhXQ1DH6UDHUMfpIMdQx0x8x+lD0BDHRggDJ/iFus5UDxwXDAJMxMnDiEvL00PpIMdTU0SHQ1ywhqPu/HPK/0z8x1NcLHwHQ0/8x10zQAtAC+kgx1ws/AtMfMfoAMAHjD9DXLCGo+78c8r/TP9MfMfpQMCBuAG8AcABxAFhWHFYZVhlWGVYZ8CQIyMsfF8sfUAX6AlAD+gLLD8sPygAB+gLKAMn4KFnwIgP+bCHTP9TXTFYX0NT6UDHUMfpIMdQx0x8x+lAx9AQx0dD6SPpQMdEkggDCiALHBfL0AdCUIMcAs45AINdLAZEwm4E0vAHAAfL010zQ4tM/UhARFoBA9FuCAMn4AfL0yM+PGAAEghAnkIKLzwv3cM8LYRLLP8lw+wARFOgw0IqK6ABMAE0ATgMo1ywgvhIW5I8J1ywiE1xmJOMP4w0AUgBTAFQD/mwh0z9vAAHTB/QEkyFus44SAdD0BJr6SFBVb4wkxwAV5jAB6DEib4hYuvKJ9AVWF9DUMfpQMdQx+kgx1DHTHzH6UPQEMdGCAMn+IW6zlQXHBcMAkzE0cOIU8vSCAMoGI26z8vQC0PpI9AT0BSBu4w/Iz4UIEvpScc8LbszJgEAAbABtAG4ACCDHALMB/iDXSwGRMJuBNLwBwAHy9NdM0OLTP9TU1IIAyfcj0NMHIcFB8oUBqgLXGNHXScMA8vSCAMn7JVYZgED0Dm+hMbPy9AHQ1NTRbQLQ0gDTd9N30fgjIsjLd8s/E8oAy3fLd8kB0NIA03fTd9H4IyLIy3fLPxPKAMt3y3fJAcjMzMkATwAwMMjPhQgS+lKCEK14M9fPC47LP8mAQPsAAbj4I3DIy3fLP3DPC/DJ+CNwyMt3yz9wzwvwyQHIzMzJJAbQlCDHALOK6DAFyMwS9ADME8xSMhEXgED0Q8jPjxgABIIQ7TfEvM8L93DPC2ETyz8BERUBzMlw+wAREwBQAfog10sBkTCbgTS8AcAB8vTXTNDi0wchwUHyhQGqAtcYyCLXSSCpOALyRasCIMFB8oXPCwcSzsmCAMn3IdDTByHBQfKFAaoC1xjR10nDAPL0IPkAggDJ/1MWgwf0Dm+hMbPy9FRBFoMH9BfIz48YAASCEL8NGrbPC/dwzwthKQBRABLPCz8VzMlw+wAB/Gwh0z/TP9dMVhfQ1PpQMdQx+kgx1DHTHzH6UDH0BDHR0PpI+lAx0SSCAMKIAscF8vSCAMn4IlYWgED0Dm+hMfL0ggDJ+CJWFoBA9A5voRLy9NT0BNTU0ST5AFADgwf0W4IAygAB8vQDyMwT9AASzMxSIhEWgED0Q8jPjxgABABVAurXLCa7iUCEjurXLCHihRzcjl9sIdM/1wsfERbQ1PpQ1PpI1NMfMfpQ9ATRJtD6SPpQMdEpggDCiALHBfL0VhwHyMwW+lQUzBL6UswTyx8S+lT0AMnIz4UIE/pSghBCanE7zwuOyz8BERUByx/JgED7AOMO4w0AVgBXAf5sIdM/0z/XTFYX0NT6UDHUMfpIMdQx0x8x+lAx9AQx0dD6SPpQMdEkggDCiALHBfL0ggDJ+CJWFoBA9A5voTHy9IIAyfgiVhaAQPQOb6ES8vTU9ATU1NGCAMn3JdDTByHBQfKFAaoC1xjR10nDAPL0JPkAggDJ/1MUgwf0Dm+hAGsAcIIQvBTH6M8L93DPC2Eizws/VhXPFMlw+wDIz4UIFPpSghDhe/PMzwuOEss/yz8BERIBzMmAQPsAA/jXLCH65Pq8j3HXLCHDRxhMjlxsIdM/9AURFtDU+lDU+kjU0x/6UPQEMdEm0PpI+lAx0SmCAMKIAscF8vRWHAfIzBb6VBTMEvpSzMsf+lT0AMnIz4UIE/pSghCJ1gLlzwuOyz8BERUB9ADJgED7AI8J1ywkIcIKFOMP4uMNAFgAWQBaAv5sIdM/+kj6UPpQMBEY0NT6UNQx+kjU0x/6UPQE0SbQ+kj6UDHRK4IAwogCxwXy9IIAyfcpjQhgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAExwWz8vSCAMn3Vh9ukX/jDvL0bSnI+lJSkPpUViAB+lT0AMkHyMwWAGkAagD0bCHTP/QFERbQ1PpQ1PpI1NMf+lD0BNEn0PpI+lAx0SqCAMKIAscF8vQF0PpI+lD6UPQEMdECyPpS+lT6VAERHQH0AMkGyMwV+lQVzPpSE8zLHwERFwH6VAERFgH0AMnIz4UIEvpSghDB/+OmzwuOAREVAcs/yYBA+wAC7NcsIn8Wk2SO62wh0z/XTFYW0NT6UDHU+kgx1DHTHzH6UDH0BDHR0PpI+lD6UPQE0QTQ+kj6UDHRkvAlAFQlgOxfJIIAyf4DxwWSMH+U2gHDAOLy9NCUIMcAs4roMMjPhQgS+lKCEN17DHHPC47LP8mAQPsA4w4AWwBcALxsIdM/+lAwERbQ1PpQ1PpI1NMf+lAx9ATRJtD6SPpQMdEpggDCiALHBfL0VhwHyMwW+lQUzBL6UszLHxL6VPQAycjPhQgT+lKCEDyGnYDPC47LPwERFQH6VMmAQPsAAv4g10sBkTCbgTS8AcAB8vTXTNDi0z/SANTUggDJ+CVWGYBA9A5voRLy9NT0BNTU0SeOPwHQ1DHUMdEl0NIA03fTd9H4IyLIy3fLPxPKAMt3y3fJJdDSANN303fR+CMiyMt3yz8TygDLd8t3yQHIzMzJAeMNA8jMEvQAzMxSUhEZAF0AXgMo1ywhhQ6PvI8J1ywkyU2yFOMP4w0AXwBgAGEAetDUMdQx0SXQ0gDTd9N30fgjIsjLd8s/E8oAy3fLd8kl0NIA03fTd9H4IyLIy3fLPxPKAMt3y3fJAcjMzMkASoBA9EPIz48YAASCEP+dv3bPC/dwzwthFcs/E8oAzMzJcPsAERMB/Gwh0z/6UDARFtDU+lAx1PpI1NMf+lD0BNEm0PpI+lAx0SmCAMKIAscF8vSCAMn3Vh1ukX+OK1YdjQhgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAExwWzwwDi8vRWHAfIzBf6VBXME/pSzMsf+lT0AMnIz4UIEwBiAfTXLCTtJtBMjm9sIdM/9AVWFtDU+lDUMfpIMdQx0x8x+lAx9AQx0QHQ+kj6UDHRJIIAyf4CxwWSMX+OECFus5ZSQscFwwCSMXDiwwDi8vQRFdD0BDHRVhTI9ADJyM+FCBP6UoIQFYABYc8Ljss/AREUAfQAyYBA+wDjDgBjAv5sIdM/1NdMVhfQ1PpQMdQx+kgx1DHTHzH6UDH0BDHR0PpI+lAx0SSCAMKIAscF8vQB0JQgxwCziugw0JQgxwCzjjog10sBkTCbgTS8AcAB8vTXTNDi0z9SEBEUgED0WzDIz48YAASCENZGx9HPC/dwzwthEss/yXD7ABES6DDIAGUAZgAw+lKCEOXQiy7PC47LPwERFQH6VMmAQPsAAe7XLCBoBMrkjlQwMVYV0NT6UNT6SNTTH/pQ9ATRB9D6SPpQ0UEKKfABjio4VxwRG8j6Uhb6VMnIzBP6VMz6UhLMAREWAcsf+lQBERQB9ADJERN/2zHgEIlfCccA2zHhMdM/bwAB0wf0BZMgbrOK6DAhb4i68onwJgBkAFrQ9ASOJvpI+gDXLCB8U/Us8r/TP/oA+kj6UPQE+gCLCAxVgG8Jb4wjxwAU5jAB/iDXSwGRMJuBNLwBwAHy9NdM0OLTP9Mf0x/6APoA0w/TD9IAggDJ+ClWHoBA9A5voTHy9IIAyfUi8vSCAMn0JIEnELny9IIAyfQjgScQufL0ggDJ9SjCAPL0J8jLHyfPCx8m+gIl+gIkzwsPI88LDyLPCgBSkhEdgED0QwfIyx8AZwEsic8WEvpSghAoy8xkzwuOyz/JgED7AABoAF4Wyx9QBPoCWPoCyw/LD8oAycjPjxgABIIQ++YfFc8L93DPC2ETyz8SzMlw+wAREwABQgBWVh+NCGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAATHBbPDAABu+lQWzBP6UszLHxL6VPQAycjPktzXjDIUyz8S+lL6VAERFgH6VMnIz4UIEvpScc8LbszJgED7AACyMbPy9FRFFIMH9BfIz48YAASCEL8NGrbPC/dwzwthJs8LPyXPFMlw+wADyMwT9AASzMxSIhEWgED0Q8jPhQgU+lKCEBLMSYXPC44Syz/LPwEREgHMyYBA+wAAfjDIz5Gxwst2E8s/I2+Ic21UciGpBo4bAcj0AFMhtghRIqEimVOAb4FY+lIBpOQByQKh5DAxNc8LBxP0APQAyQCCyM+QVjdfVhTLPyRviHNtVHIhqQaOGwHI9ABTIbYIUSKhIplTkG+BWPpSAaTkAckCoeQwMTbPCwcU9AASzBL0AMkABPsAAvyCAMn4IlYVgED0Dm+hEvL01PQE1NTRINDU1NHQ03fTP9IA03fTd9EijjhfBgHQ1NTR0NN30z/SANN303fRVh/Q1DH6UDHUMfpIMFKg8AoEyMt3E8s/ygDLd8t3yQHIzMzJAeMNA8jMEvQAzMxSIhEVgED0Q1YW0NQx+lAx1DEAcgBzAfiCAMn4IlYVgED0Dm+hEvL01PQE1NTRAdDU1NHQ03fTP9IA03fTd9FWH9DUMfpQMdQx+kgwUqDwCgTIy3cTyz/KAMt3y3fJAcjMzMkDyMwS9AASzMxSIhEVgED0Q1YW0NQx+lAx1DH6SDACyMs/EvpSARET+gLJyM+PGAAEAHQAPpFbjhrIz4UI+lKCEO8Ms27PC47LP8+LKBbJgED7AOIAWDZWH9DUMfpQMdQx+kgwEEUQNEEwVCag8AoEyMt3E8s/ygDLd8t3yQHIzMzJAFD6SDACyMs/EvpSARET+gLJyM+PGAAEghA0f/x8zwv3cc8LYczJcPsAACSCEHQJrY/PC/dxzwthzMlw+wAC/oIAyfgiVhWAQPQOb6ES8vTU9ATU1NEg0NTU0QHQ03fTP9IA03fTd9EijjhfBgHQ1NTRAdDTd9M/0gDTd9N30VYf0NQx+lAx1DH6SDBSoPAKBMjLdxPLP8oAy3fLd8nIzMzJAeMNA8jMEvQAzMxSIhEVgED0Q1YW0NQx+lAx1DEAeAB5AfiCAMn4IlYVgED0Dm+hEvL01PQE1NTRAdDU1NEB0NN30z/SANN303fRVh/Q1DH6UDHUMfpIMFKg8AoEyMt3E8s/ygDLd8t3ycjMzMkDyMwS9AASzMxSIhEVgED0Q1YW0NQx+lAx1DH6SDACyMs/EvpSARET+gLJyM+PGAAEAHoAPpFbjhrIz4UI+lKCEDR26nLPC47LP8+LKBbJgED7AOIAVjZWH9DUMfpQMdQx+kgwEEUQNEEwVCag8AoEyMt3E8s/ygDLd8t3ycjMzMkAUPpIMALIyz8S+lIBERP6AsnIz48YAASCEBQffizPC/dxzwthzMlw+wAAJIIQMOur288L93HPC2HMyXD7AAE+ic8WE8s/FPpSE8wSzMnIz4WIEvpScc8LbszJgED7AAB8AAjno1BBAgEgAH8AgAIBIACcAJ0CASAAgQCCAgEgAJEAkgIBIACDAIQCASAAjwCQAfMVhnQ1DH6UDHU+kgx1DHTHzH6UDH0BDHR0PpI+lAx+lAx9AQx0SaCAMn+AscF8vQmwwCVLG6zwwCRcOKOF1cSBxETBwYREgZVBBERK9qCUNyBAIcM4BETERkRExESERgREhERERcREREQERYREA8RFQ8OERQODREZDYACFAfcJsMAlStus8MAkXDijiBXEgcREwcGERIGVQQRESrahwYREgYFEREFgQCHERFVQOAj0NP/1NEg0NM/+kgx+gD6SDCCAMn9Vh/Q1DH6UDHUMfpIMFjHBfL0ggDJ+SJWHIBA9A5voTHy9FYdVh1WHVYdVh1WHVYdVh1WHVYdgAIcB/gwRGAwLERcLChEWCgkRFQkIERQIBxEZBwYRGAYFERcFBBEWBAMRFQMCERQCAREZAREYVhdWF1YXVhdWHVYd8BEEjiRfBFcUVxRXFFcUVxRXFA0REw0MERIMCxERCwoREAoQnxCOVVfgyM+T6faRElYbzws/AREaAcwBERgByx8AhgD4AREcAfQAVhoB+lTJyAERHPoCAREW+gIBERYBzAERFAHMycjPk56NQQYBERYByz8BERYB+lIBERcBzAEREwHMycjPhYgBERUB+lJxzwtuAREUAczJgED7AA0REw0MERIMCxERCwoREAoQnxCOEH0QbBBbEEoQOUgWRVUHAwP+Vh1WHVYdVh1WHVYdVh1WHVYdVh1WFfASVh0CVh0CVh0CVh0CVh0CVh0CVh0CVh0CVh0CVh0CVh0CVh0CVh0CVh0CVh0CVh0CVh0CVh0CVh0CVh0CAREXAREWVhrwE2ahJeMPggDJ+FExgED0Dm+hFPL0AtT0BDHUMdQx0VYayACIAIkAigL+VhzQ1DH6UDHUMfpIMdQx0x/6UDH0BDHRUmDwFYIAyfgjVhuAQPQOb6ES8vTU9ATU1NHQ1NTRAdDTd9M/0gDTd9N30SKOM1Yl0NQx+lAx1DH6SDBSoPAJBMjLdxPLP8oAy3fLd8nIzMzJA8jMEvQAzMxSMhEbgED0Q+MOVhzQ1ACLAIwB9IIAyfgjVhuAQPQOb6ES8vTU9ATU1NEB0NTU0QHQ03fTP9IA03fTd9FWJdDUMfpQMdQx+kgwUqDwCQTIy3cTyz/KAMt3y3fJyMzMyQPIzBL0ABLMzFIyERuAQPRDVhzQ1DH6UDHUMfpIMCPIyz/6UlYa+gLJyM+PGAAEAI0B/Mv/ycjPk+n2kRIpzws/KM8UJ88LH1Jg9ABSUPpUycgk+gJWHPoCI88UIs8UyStWIAlWIAlWIFGQCVYgCVYgCVYgCVYgCVYgCVYgCVYgCVYgCVYgCVYgCVYgCVYgCVYgCVYgCVYgCVYgCQgRIAgHER8HBhEeBgURHQVQQ/AWBACOAfhfCYIAyfgjVhuAQPQOb6ES8vTU9ATU1NEB0NTU0QHQ03fTP9IA03fTd9FWJdDUMfpQMdQx+kgwUqDwCQTIy3cTyz/KAMt3y3fJyMzMyQPIzBL0ABLMzFIyERuAQPRDVhzQ1DH6UDHUMfpIMCPIyz/6UlYa+gLJyM+PGAAEAI0AWDH6UDHUMfpIMCPIyz/6UlYa+gLJyM+PGAAEghDrpIwLzwv3cc8LYczJcPsAACSCEM9QWfzPC/dxzwthzMlw+wAABhEVWQBZFcQVxBfCjY3ggDJ+gbQ9ATRI/AHsxby9ALDAJUibrPDAJFw4pREBNpA4F8FgAHcVxNXEF8PbDPQ0z/6SDH6ADACgED0Dm+h8BQxbDMzApNfBHDhA5EykTDiggDJ9CKBJxC58vSogScQqQSACASAAkwCUAgEgAJUAlgBXJkwbW1tbW1tbXDh0x/TH/oA+gDTD9MP0gDRIJOBAIqaXwdtbW1tbW1tcOKAAKwhkVvhggDKCSGUArrDAJNsIXDi8vSABow4OTk5Ojo6Ojo6Oj09PT0EwwCVKm6zwwCRcOKOEDwQaxBaEEkIEGdGFBAj2rHgNTU1NjYH0NQx+lAx1DH6SDHUMdMfMfpQ9AQx0SBu4wNfCHCAAlwH1CbDAJUpbrPDAJFw4o4YMFcRBhESBgUREQVVAxEQJ9pyUNyBAIcM4IIAyf5WGtDUMfpQMdQx+kjXTPgoyM+EAvpSEvpSyQHIz4TQzMz5FsjPigBAy//PUCfHBfL0VhlWGVYZVhlWGVYZVhlWGVYZVhlWGVYZVhlWGVYZgAJgAliLQ+gAx+gDUMdQx0fgoBcj6UhfME8zJyM+RBKdEJhLLPxfME8sfFPQAWPoCEvpSEvQAycjPhYgS+lLPhBBz+gJxzwtlzMmAQPsAfwFQVhlWGVYZVhlWGVYZVhlWGVYZVhmTW/Aa7eO6gBl/7RGK7UHt8QHy/wCZAu4h9AQhbpgxIMcAkjBt4JLR0OL6SNTU0VYcAVYcAVYcAVYcAVYcAVYcAVYcAVYcAVYcAVYcAVYcAVYcAVYcAVYcAVYcAVYcAVYcAVYcAVYcAVYcAVYcAVYcAVYcAVYcAVYcAREcVhqK7eO6gBt/7RGK7UHt8QHy/wCaAJsAqDEQRxA2RXbwGvgnbxBTAbyRopJbcOL4L6By+wIB0NcsJ9PtIiTyv9M/1DHTHzH0AfpQMCBukl8DjhnIz4UI+lKCEDR26nLPC47LP8sPyYEAgvsA4gDkINDXLCfT7SIk8r/XTNDT/zHXTNDTPzH6SPoAMIIAyghRGLry9IIAygcmbrPy9FYcAVYcAVYcAVYcAVYcAVYcAVYcAVYcAVYcAVYcAVYcAVYcAVYcAVYcAVYcAVYcAVYcAVYcAVYcAVYcAVYZAfAYWPAZAgEgAJ4AnwIBIACoAKkCASAAoAChAgEgAKQApQGTO2i7ftXElcQXw9sIiLQ1DH6UDHU+kgx1DHTHzH6UDH0BDHR0PpI+lAx+lAx9ATRUyHHBZJfBeAggCD0hm+lMpEBiuiCAMn+8vCAAogHzCjDAJUqbrPDAJFw4o4YVxQJERUJCBEUCFUGERNWFdqiUNyBAIcM4GwzMzMC0AHQAdcsJ9PtIiTyv9M/1NMfMfQB+lAwAdDT/zHU0dDUMdM/+kgx+gAx+kjRBPoAMfoA1NdMBsj6Uhf6UiH6AsnIz48YAASCEDfdb26AAowCgUwXQ1DH6UDHUMfpIMdQx0x8x+lAx9ATRggDJ/iFus/L0JMj6UhLLH1Jg+lLJAcjPhNDMzPkWyM+KAEDL/89QJMcFlF8G2zHgIYAg9HxvpTIAcs8L93DPC2ETyz8SzMlw+wAhbpJfBY4hBMjME8zJyM+FiBP6UoIQ9DKk488Ljss/zAH6AsmAQPsA4gCDDAgbpJfBOCCEAX14QBtiwTIz5A+KfqWFss/UAT6AlIg+lIS+lQS9ADPhCASzsnIz4UIE/pSAfoCcc8LaszJc/sAgAfMVhjQ1DH6UDHU+kgx1DHTHzH6UDH0BDHR0PpI+lAx+lAx9AQx0SWCAMn+AscF8vQlwwCVL26zwwCRcOKOFzRXEAUREQUEERAEWlQfDdpiUNyBAIcM4BETERgRExESERcREhERERYREREQERUREA8RFA8OERgODREXDYACmAfQMERYMCxEVCwoRFAoJERgJCBEXCAcRFgcGERUGBREUBQQRGAQDERcDAhEWAgERFQERFFYYVhhWGFYYVhjwHAOOIF8DVxRXFFcUVxRXFA4REw4NERINDBERDAsREAsQr1VJ4BEWERsRFhEVERoRFREUERkRFBETERgREwCnAHIREhEXERIREREWEREREBEVERAPERQPDhETDg0REg0MEREMCxEQCxCvEJ4QjRB8EGsQWhBJEDhY8CECASAAqgCrAgEgALUAtgH1CXDAJUubrPDAJFw4o4gVxEGERIGBRERBVUDERAt2nYFEREFBBEQBIEAhxEQVTDgItDT/zHU1PQE9AQx0QLQ+kgx0z/UMdP/+kjRggDJ/VYe0NQx+lAx1DH6SDBYxwXy9IIAyfkiVhuAQPQOb6Ex8vRWHFYcVhxWHFYcgAKwATxXE1cQXw8zMwKAQPQOb6GSW3Dh1DH0BNQx1DHRAfkAAYMH9A5voTGAB/FYcVhxWHFYcVhxWHFYcVhxWHFYcVhxWHFYcVhxWHFYV8BJWHFYcVhxWHFYcVhxWHFYcVhxWHFYcVhxWHFYcVhxWHFYcVhxWHFYcVhWCAMoAERjwHRPy9FYbAVYbAVYbAVYbAVYbAVYbAVYbAVYbAVYbAVYbAVYbAVYbAVYbAQCtBPxWGwFWGwFWGwFWGwFWGwFWGwFWGwERFvAekvAfABJWHAJWHAJWHAJWHAJWHAJWHAJWHAJWHAJWHAJWHAJWHAJWHAJWHAJWHAJWHAJWHAJWHAJWHAJWHAJWHAKAFn/tEdoBIMEAkX+WIIR3vMMA4paCAMoC8vDgI+MPIlYXyIkArgCvALAAsQL+VhrQ1DH6UDHUMfpIMdQx0x/6UDH0BDHRUkDwFYIAyfgiVhmAQPQOb6ES8vTU9ATU1NHQ1NTR0NN30z/SANN303fRIo40ViPQ1DH6UDHUMfpIMFKg8AkEyMt3E8s/ygDLd8t3yQHIzMzJA8jMEvQAzMxSIhEZgED0Q+MOVhrQ1ACyALMB9oIAyfgiVhmAQPQOb6ES8vTU9ATU1NEB0NTU0dDTd9M/0gDTd9N30VYj0NQx+lAx1DH6SDBSoPAJBMjLdxPLP8oAy3fLd8kByMzMyQPIzBL0ABLMzFIiERmAQPRDVhrQ1DH6UDHUMfpIMALIyz8S+lJWF/oCycjPjxgABAC0AAg1H3fjAPDPFifPCz8mzxQlzwsfUkD6VMkiyMsfIvoCVhr6AskpVh4IVh4IVh5RgAhWHghWHghWHghWHghWHghWHghWHghWHghWHghWHghWHghWHghWHghWHghWHghWHggHER4HBhEdBgURHAUQNBAjAREdAREc8CACERQCQTMB+F8JggDJ+CJWGYBA9A5voRLy9NT0BNTU0QHQ1NTR0NN30z/SANN303fRViPQ1DH6UDHUMfpIMFKg8AkEyMt3E8s/ygDLd8t3yQHIzMzJA8jMEvQAEszMUiIRGYBA9ENWGtDUMfpQMdQx+kgwIsjLP/pSVhj6AsnIz48YAAQAtABaMfpQMdQx+kgwAsjLPxL6UlYX+gLJyM+PGAAEghDLxA5bzwv3cc8LYczJcPsAACSCEIuyX6jPC/dxzwthzMlw+wAAZRXEF8PMWwiIG6RMOAx0IIAygEh10mDB7qXIddKwADDAJFw4vL00//RggDKASGEB7vy9IACFFcQXw8xbCJTIbqSbCHgUyG8ngKi8AiWggDKAvLw4KkE4AKh8AiWggDKAvLw4IIAygIhmYT/IqkEI77DAJF/4vL0qIAIBIAC5ALoCAUgA0gDTAgEgALsAvAIBIADJAMoCASAAvQC+AgEgAMEAwgGdDc4ODg4ODg4OTk5PDw8PALDAJUgbrPDAJFw4p87EFoQSRA4EEdeI1UD2qHgMGwzMwbQ1DH6UDHUMfpIMdQx0x8x+lD0BDHRIG7jA18HcIAC/AekKMMAlS9us8MAkXDijhEKERYKCREVCQgRFAgv2rNO3OAyMwPQ0/8x1NQx9AQx9AQx0dD6SNM/1DHT/zH6SNECyPpSyQLI+lIX+lJQA/oCEszJyM+PGAAEghDpwAyXzwv3cM8LYRXLPxTMyXD7ACJukl8D4w6AAwACKItDTHzH6APoAMdH4KAPI+lIYzBPMycjPkcDwrWIWyz8UzFAF+gLLH/pS9ADJyM+FiBL6Us+EEHP6AnHPC2XMyYBA+wB/ADrIAfoCycjPhYgT+lKCEODogvXPC47LP8zJgED7AAP1DJWHdDUMfpQMdQx+kgx1DHTH/pQMfQEMdFSUPAVggDJ/VYe0NQx+lAx1DH6SDApxwXy9IIAyfknVhyAQPQOb6Ex8vQpVh7Q1DH6UDHUMfpIMdQx0x8x+lD0BDHRIG7jA1tsYm8AIm7jD8jPhQgS+lJxzwtuzMmAQPsAgAMMAxADFAfcIZYw8CQYXwjhNFtWFQFWFQFWFQFWFQFWFQFWFQFWFQFWFQFWFQFWFQFWFQFWFQFWFQFWFQFWFQFWFQFWFQFWFQFWFQFWFQERFfAekvAfAAERFgEBERUBAREUAQEREwEBERIBARERAQEREAEfHh0cGxoZGBcWFRRDMIAWgAMgC/jtWHgFWHgFWHgFWHgFWHgFWHgFWHgFWHgFWHgFWHgFWHgFWHgFWHgFWHgFWHgFWHgFWHgFWHgFWHgFWHgFWGwERG1YaVhpWGvAj+CgHyPpSEvQAEvQAycjPkxUdtK4Zyz8X+lIVyz9QBfoCyx8Tywf0APpS9ADJyM+FiBL6UokAxgDHAHwyyM+RscLLdhPLPyFviHNtVHIhqQaOGwHI9ABTIbYIUSKhIplTYG+BWPpSAaTkAckCoeQwMTPPCwf0APQAyQB+yM+QVjdfVhTLPyNviHNtVHIhqQaOGwHI9ABTIbYIUSKhIplTgG+BWPpSAaTkAckCoeQwMTXPCwcT9ADM9ADJAAEEAB7PFnP6AnHPC2XMyYBA+wAANH/tEdoBIMEAkX+WIIR3vMMA4paCAMoC8vDgAgEgAMsAzAIBIADNAM4AqRsxDQ0NDU1NTWAQPQOb6HwFI4UXwlwVHAAUwAQVhBFEDRDAHBQA3DhKQiSODiOITdUQRiSNybeggDJ9CiBJxC58vRSiKiBJxCpBBihEGcFBuJVJH+AAHQ0WyBus5THBcMAkltw4oAHhCTDAJUlbrPDAJFw4o4WVxAFEREFBBEQBIEAhwQREFYR2nNO3OBsIYIAygRWFtDU10zQAdAB+kj6UPpQ9AWS8CcAUoDsXwH6SDAkxwWSMH+U2gHDAOLy9G2CCJiWgPgvoIAU+wJtcCNviJJcuYroXwaAAzwAfDFsIiFus5THBcMAkltw4oAL+IaRSU2+BbymCANmUJY0IYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABMcFs/L0LG6zjilTTI4h7aLt+3Ahb4iSXLmOECGkUjNvgSTHBZVfBH/bMeDoXwRw2LPDAJFw4paCANmV8vDgcFOcgQEL9ApvoZEw4w0moADQANEACDH6ANEA/MgB+gJUIJ2BAQv0QcjPkAZagd7JL8jPkLWFgDL6UvQAHM7JyPQAz1AlyM+QPin6lhjLP1AH+gIU+lIS+lT0AAH6AhLOycjPhYhSQPpSUAP6As+Bc/oCcc8LZRLMyYAQ+wDIz48YAASCEKqHUCnPC/dwzwthEvpSAfoCyXD7AAIBIADUANUAsUE18DVxNXEF8PMzMD0NQx+lAx1DH6SDHUMdMf+lAx9AQx0VIw8BUBgED0Dm+hlltwVHAAcOHTH9Mf+gD6ANMP0w/SANGXXwdwVHAAcOEGlDAxA3/gMTQDf4AGMUKtfCWzzbDMhbpJfA+AB0PpI9AXIz4UIEvpSghAESdRnzwuOEss/Esof9ADJgED7AIAH3FcTVxBfDzOCAMn4NBKAQPQOb6ET8vQB1DH0BDHU1NECjlcw0NTU0QHQ03fTP9IA03fTd9H4I1AEoSOoFKAjtgj4IwHIy3fLP8oAEst3y3fJAdDTd9M/0gDTd9N30fgjUAShI6gUoCO2CPgjAcjLd8s/ygASy3fLd8ngMYADWAKzQ1NTRAdDTd9M/0gDTd9N30fgjUAShI6gUoCO2CPgjAcjLd8s/ygASy3fLd8kB0NN30z/SANN303fR+CNQBKEjqBSgI7YI+CMByMt3yz/KABLLd8t3yQIBIADZANoCASAA9wD4AgEgANsA3AIBIADrAOwCASAA3QDeAgEgAOcA6AIBIADfAOACASAA4wDkAgFmAOEA4gBFrcj2omhqahjo6GpqGOmDmPoCGPoCGOjoahj9KBjqGP0kGEAAUaBftRNDU1DHRINAx1NQx0wcx9AQx9AQx0dDUMfpQMdQx+kgx1DHXCx+AGmhx7UTQ1NQx0SDQMdQx1DHTBzH0BPQEMdFtIYBA9IZvpTKRAZ1SAm8CURKAQPR8b6Uy6DAxgIBIADlAOYAs63YdqJoampokOhqammD+gJ6AmjAgEO2tra2yXgGgDa2trbJeAYAB4iKB4cIiYcGiIkGhgiIhgWIiAWIZ4hfCFaITghFiD0INIgsCCOIGyKgNqghwIBEAfgJwABsqV+NCpsaW5rLmNoYWluLnRvbi5jY2lwLnBvb2wuQnVybk1pbnRUb2tlblBvb2yCLUwLjEuMIALKq0O1E0NTU0SHQ1NTTB/QE9ATRgQCHbW1tbZLwDQBtbW1tkvAMAA8RFg8OERUODREUDQwREwwLERILEK8QnhCNEHwQaxBaEEkQOEdgbVBlgQCIRRVQRAPwIwIBbgDpAOoArbAfO1E0NTU0SHQ1NTTB/QE9ATRgQCHbW1tbZLwDQBtbW1tkvAMAA8REw8OERIODRERDQwREAwQvxDeEM0QrBCbEIoQeRBoEFcQRhA1RDBtWoEAiALwHYAAtp1HaiaGpqGOjoahjqGOmD+gIY+gIY6MAGaRRBAFfkUBBCB935QkCASAA7QDuAK21L12omhqamiQ6GpqaYP6AnoCaMCAQ7a2trbJeAaANra2tsl4BgAHiImHhwiJBwaIiIaGCIgGCF+IbwhmiFYITYhFCDyINAgriCMIGqIYNq1AgEQBeBTACASAA7wDwAF+ycbtRNDU1DHRINAx1NQx0wcx9AQx9AQx0dDUMfpQMdQx+kgx1DHTHzH6UPQEMdGACASAA8QDyAgFiAPUA9gC4qoftRNDU1NEh0NTU0wf0BPQE0YEAh21tbW2S8A0AbW1tbZLwDAAPERcPDhEWDg0RFQ0MERQMCxETCxERERIREREQEREREAoREAoQnxCOEH0QbFVVbQaBAIgG8CoCASAA8wD0AGemO9qJoamoY6Ohqahjpg5j6Ahj6Ahjo6Gp9KBjqGP0kGOoY6Y+Y/SgY+gIY6Oh9JH0oGOjAAmlCwIDhQBLofu1E0NTUMdEg0DHU1DHTBzH0BDH0BDHR0NQx+lAx1DH6SDDHBYAT6B/tRNDU1DHRINAx1NQx0wcx9AQx9AQx0dDUMddM0PpI+lD6UPQE0YCASAA+QD6AgEgAPsA/ABbtH29qJoamoY6Ohqahjpg5j6Ahj6Ahjo6GoY/ShqGP0kGOoY6Y+Y/SgY+gIY6MAB9t9z9qJoamoY6JBoGOoY6hjpg5j6Ahj6AmjAIHoHN9DHCWmP6Y/9AH0AaYfph+kAaMCARUyYNra2tra2trhxQAJu0jb2omhqahjokGgY6hjqGOmDmPoCegIY6MEAZPwswCB6BzfQiXl6ahj6AmoY6hjotpDBg/pDN9LITwDqaKw3gSiJQYP6PjfS9AgRr4HACASAA/QD+AgFqAP8BAAA9shx7UTQ1NQx0dDUMdQx0wcx9AT0BDHRgED0Dm+hMYABfpV/aiaGpqGOiQaBjqGOoY6YOY+gJ6AhjowQBk/CzAIHoHN9CJeXpqegIY6hjqGOjAD2nA9qJoamoY6OhqGOppg5j6Ahj6Ahjo6HoCaID4A9n'); + static CodeCell = c.Cell.fromBase64('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'); static Errors = { 'Common_Error.CrossChainAddressOutOfRange': 5, From 4daf24d06664a87d5f4068eb40b387a9fc38e224 Mon Sep 17 00:00:00 2001 From: Kristijan Date: Mon, 14 Sep 2026 14:42:19 +0200 Subject: [PATCH 07/23] Route inbound ReleaseOrMint through Router as pool chokepoint Make the Router the single access point of every token pool for inbound release/mint, mirroring the outbound LockOrBurn flow and EVM's _onlyOffRamp. - OffRamp relays OffRamp_ReleaseOrMint to the Router as Router_RelayReleaseOrMint instead of calling the pool directly. The pool's reply (Finished/Failure) still goes straight to the executor via replyTo. - Router authenticates the registered OffRamp for the source lane, enforces its RMN policy, then dispatches TokenPool_ReleaseOrMint to the pool. - On relay rejection (cursed) or a pool bounce, the Router reports a Router_TokenPoolReleaseOrMintFailed to the owning OffRamp, which is the executor's only authority. The OffRamp forwards it to the executor through the existing mintOrReleaseFailed rail. - ReceiveExecutor storage is unchanged (no exclusive-router-read needed). Also fix stale pool unauthorized exit-code expectations (14910 -> 51710). --- .../contracts/ccip/offramp/contract.tolk | 52 +++-- .../contracts/ccip/offramp/messages.tolk | 3 +- contracts/contracts/ccip/router/contract.tolk | 28 ++- contracts/contracts/ccip/router/messages.tolk | 10 +- contracts/tests/ccip/offramp/OffRamp.Setup.ts | 2 +- .../ccip/offramp/OffRamp.execute.spec.ts | 43 +++- .../tests/ccip/pools/TokenPool.behavior.ts | 4 +- .../tests/ccip/router/Router.cursing.spec.ts | 4 +- contracts/wrappers/gen/ccip/OffRamp.ts | 201 +++++++++++++----- contracts/wrappers/gen/ccip/Router.ts | 12 +- 10 files changed, 275 insertions(+), 84 deletions(-) diff --git a/contracts/contracts/ccip/offramp/contract.tolk b/contracts/contracts/ccip/offramp/contract.tolk index 1be7c04c9..d1653c6c2 100644 --- a/contracts/contracts/ccip/offramp/contract.tolk +++ b/contracts/contracts/ccip/offramp/contract.tolk @@ -121,6 +121,12 @@ fun onInternalMessage(in:InMessage) { assertSenderIsTheRouter(st, msg.execId.getSourceChainSelector(), in.senderAddress); onBouncedCCIPReceive(msg); } + // Sender must be router + Router_TokenPoolReleaseOrMintFailed => { + val st = lazy Storage.load(); + assertSenderIsTheRouter(st, msg.sourceChainSelector, in.senderAddress); + onTokenPoolReleaseOrMintFailed(msg); + } // Sender must be ReceiveExecutor OffRamp_NotifySuccess => { val st = lazy Storage.load(); @@ -181,8 +187,8 @@ fun onBouncedMessage(in: InMessageBounced) { Router_RouteMessage => { onBouncedRouterRouteMessage(originalMessage, in.senderAddress) }, - TokenPool_ReleaseOrMint => { - onBouncedTokenPoolReleaseOrMint(originalMessage, rich.exitCode) + Router_RelayReleaseOrMint => { + onBouncedRouterRelayReleaseOrMint(originalMessage, rich.exitCode) }, } } @@ -240,11 +246,14 @@ fun onBouncedDeployableInitialize(msg: Deployable_Initialize, senderAddress: add }); } -// Handles bounced TokenPool_ReleaseOrMint messages. -// This can be the result of the rate limit being exceeded or the pool being misconfigured. -// Sends a OffRamp_ReleaseOrMintBounced message to the ReceiveExecutor to mark the execution as failed. -fun onBouncedTokenPoolReleaseOrMint(msg: TokenPool_ReleaseOrMint, exitCode: int32) { - mintOrReleaseFailed(msg.replyTo!, msg.queryId, ReleaseOrMintBounced { exitCode }); +// Handles bounced Router_RelayReleaseOrMint messages: the Router rejected the +// relay (e.g. this OffRamp is no longer registered, or the Router reverted). +// Sends a OffRamp_ReleaseOrMintBounced message to the ReceiveExecutor to mark +// the execution as failed. Pool bounces never reach the OffRamp: the Router +// holds the bounce and proxies failures to the executor as +// Router_TokenPoolReleaseOrMintFailed. +fun onBouncedRouterRelayReleaseOrMint(msg: Router_RelayReleaseOrMint, exitCode: int32) { + mintOrReleaseFailed(msg.replyTo, msg.queryID, ReleaseOrMintBounced { exitCode }); } // Handles bounced Router_RouteMessage messages. This should never happen; if @@ -465,23 +474,42 @@ fun mintOrReleaseFailed(receiveExecutor: address, queryID: uint64, reason: Relea receiveBounced.send(SEND_MODE_CARRY_ALL_REMAINING_MESSAGE_VALUE); } +// Handles a Router-reported release/mint failure (lane cursed, or the token +// pool bounced the relay). The Router is the pool's only authority, so it +// reports back to us and we fail the executor through the usual rail. +fun onTokenPoolReleaseOrMintFailed(msg: Router_TokenPoolReleaseOrMintFailed) { + mintOrReleaseFailed(msg.replyTo, msg.queryID, ReleaseOrMintBounced { exitCode: msg.exitCode }); +} + +// Relays a release/mint request to the token pool through the Router, which is +// the single access point of every token pool (mirrors EVM `_onlyOffRamp`, +// where the pool validates the caller against the Router). The Router +// authorizes this OffRamp for the source chain and enforces its RMN policy +// before dispatching `TokenPool_ReleaseOrMint` to the pool. +// +// The pool replies (`ReleaseOrMintFinished`/`ReleaseOrMintFailure`) directly to +// `sendExecutor` (carried as `replyTo`). Relay rejections and pool bounces are +// proxied by the Router as `Router_TokenPoolReleaseOrMintFailed` to the same +// address, so the executor sees a canonical failure either way. fun onReleaseOrMint(st: Storage, sendExecutor: address, msg: OffRamp_ReleaseOrMint) { if (msg.destGasAmount < MIN_TT_GASLIMIT) { return mintOrReleaseFailed(getReceiverExecutorDeployAddress(st, msg.execId).calculateAddress(), msg.queryId, NotEnoughDestGasAmountForTokenTransfer {}); } - val releaseOrMintMsg = createMessage({ + val relayMsg = createMessage({ bounce: BounceMode.RichBounce, value: 0, - dest: msg.tokenPool, - body: TokenPool_ReleaseOrMint { - queryId: msg.queryId, + dest: getRouterFromSelector(st, msg.execId.getSourceChainSelector()), + body: Router_RelayReleaseOrMint { + queryID: msg.queryId, + sourceChainSelector: msg.execId.getSourceChainSelector(), + tokenPool: msg.tokenPool, request: msg.request, requestedFinalityConfig: msg.requestedFinalityConfig, replyTo: sendExecutor, } }); - releaseOrMintMsg.send(SEND_MODE_CARRY_ALL_REMAINING_MESSAGE_VALUE); + relayMsg.send(SEND_MODE_CARRY_ALL_REMAINING_MESSAGE_VALUE); } // Sets a new OCR3 configuration for the contract. Only the contract owner can call this function. diff --git a/contracts/contracts/ccip/offramp/messages.tolk b/contracts/contracts/ccip/offramp/messages.tolk index 07cafdc88..acdebc5da 100644 --- a/contracts/contracts/ccip/offramp/messages.tolk +++ b/contracts/contracts/ccip/offramp/messages.tolk @@ -27,6 +27,7 @@ type OffRamp_InMessage = | OffRamp_UpdateSourceChainConfigs | OffRamp_CCIPReceiveConfirm | OffRamp_CCIPReceiveBounced + | Router_TokenPoolReleaseOrMintFailed | OffRamp_NotifyFailure | OffRamp_NotifySuccess | OffRamp_UpdateCursedSubjects @@ -39,7 +40,7 @@ type OffRamp_InMessage = type OffRamp_InMessageBounced = | ReceiveExecutor_InitExecute | Deployable_Initialize - | TokenPool_ReleaseOrMint + | Router_RelayReleaseOrMint | Router_RouteMessage; struct (0x9d431905) OffRamp_Commit { diff --git a/contracts/contracts/ccip/router/contract.tolk b/contracts/contracts/ccip/router/contract.tolk index 2a08045b4..547ddf914 100644 --- a/contracts/contracts/ccip/router/contract.tolk +++ b/contracts/contracts/ccip/router/contract.tolk @@ -196,6 +196,8 @@ fun onInternalMessage(in: InMessage) { assert(details.remoteChainSelector == msg.sourceChainSelector, Router_Error.SourceChainSelectorMismatch); if (isCursed(st, msg.sourceChainSelector)) { return sendReleaseOrMintRelayFailure( + expectedOffRamp, + msg.sourceChainSelector, msg.replyTo, msg.queryID, msg.tokenPool, @@ -267,7 +269,15 @@ fun onBouncedMessage(in: InMessageBounced) { } TokenPool_ReleaseOrMint => { if (richMsg.replyTo != null) { + // Recover the lane from the request the pool was asked to + // process, then route the failure back through its OffRamp. + val request = lazy richMsg.request.load(); + val details = lazy request.transfer.details.load(); + val st = lazy Storage.load(); + val offRamp = st.offRamps.mustGet(details.remoteChainSelector, Router_Error.SourceChainNotEnabled); sendReleaseOrMintRelayFailure( + offRamp, + details.remoteChainSelector, richMsg.replyTo!, richMsg.queryId, in.senderAddress, @@ -829,8 +839,14 @@ fun sendLockOrBurnRelayFailure( failed.send(SEND_MODE_CARRY_ALL_REMAINING_MESSAGE_VALUE); } +/// Reports an inbound release/mint failure to the OffRamp that owns the source +/// lane. The OffRamp is the ReceiveExecutor's sole authority, so the Router +/// never talks to the executor directly (mirrors EVM, where the failure rail +/// lives on the OffRamp). `replyTo` is the executor the OffRamp must fail. fun sendReleaseOrMintRelayFailure( - executor: address, + offRamp: address, + sourceChainSelector: uint64, + replyTo: address, queryID: uint64, tokenPool: address, exitCode: int32, @@ -838,8 +854,14 @@ fun sendReleaseOrMintRelayFailure( val failed = createMessage({ bounce: BounceMode.NoBounce, value: 0, - dest: executor, - body: Router_TokenPoolReleaseOrMintFailed { queryID, tokenPool, exitCode }, + dest: offRamp, + body: Router_TokenPoolReleaseOrMintFailed { + queryID, + sourceChainSelector, + replyTo, + tokenPool, + exitCode, + }, }); failed.send(SEND_MODE_CARRY_ALL_REMAINING_MESSAGE_VALUE); } diff --git a/contracts/contracts/ccip/router/messages.tolk b/contracts/contracts/ccip/router/messages.tolk index 053e4cdb5..9695f129e 100644 --- a/contracts/contracts/ccip/router/messages.tolk +++ b/contracts/contracts/ccip/router/messages.tolk @@ -200,10 +200,16 @@ struct (0xb76e3a84) Router_TokenPoolLockOrBurnFailed { exitCode: int32; } -/// Canonical Router failure returned when a ReleaseOrMint request bounced -/// before the token pool admitted it. +/// Canonical Router failure for an inbound release/mint that the Router could +/// not complete (lane cursed, or the pool bounced the relay). +/// +/// It is sent to the OffRamp that owns the source lane, which is the only +/// authority allowed to fail a ReceiveExecutor. The OffRamp authenticates the +/// Router by `sourceChainSelector` and forwards the failure to `replyTo`. struct (0xb980cb4e) Router_TokenPoolReleaseOrMintFailed { queryID: uint64; + sourceChainSelector: uint64; + replyTo: address; tokenPool: address; exitCode: int32; } diff --git a/contracts/tests/ccip/offramp/OffRamp.Setup.ts b/contracts/tests/ccip/offramp/OffRamp.Setup.ts index 52c5d4341..65655a14b 100644 --- a/contracts/tests/ccip/offramp/OffRamp.Setup.ts +++ b/contracts/tests/ccip/offramp/OffRamp.Setup.ts @@ -893,7 +893,7 @@ export class OffRampWithTokenPoolTestSetup extends OffRampTestSetup { router: this.router.address, rateLimitAdmin: this.deployer.address, feeAdmin: this.deployer.address, - allowedDepositNamespaces: new Map(), + allowedDepositNamespaces: new Set(), }), jettonClient: tp.JettonClient.create({ masterAddress: token, diff --git a/contracts/tests/ccip/offramp/OffRamp.execute.spec.ts b/contracts/tests/ccip/offramp/OffRamp.execute.spec.ts index c2424a04d..1d70110ed 100644 --- a/contracts/tests/ccip/offramp/OffRamp.execute.spec.ts +++ b/contracts/tests/ccip/offramp/OffRamp.execute.spec.ts @@ -17,6 +17,7 @@ import * as mr from '../../../wrappers/gen/ccip/MerkleRoot' import * as rx from '../../../wrappers/gen/ccip/ReceiveExecutor' import * as tr from '../../../wrappers/gen/ccip/TestReceiver' import * as of from '../../../wrappers/gen/ccip/OffRamp' +import * as rt from '../../../wrappers/gen/ccip/Router' import * as tp from '../../../wrappers/gen/ccip/pools/TokenPool' import * as trg from '../../../wrappers/gen/ccip/TokenAdminRegistryEntry' @@ -1851,7 +1852,7 @@ describe('OffRamp - Execute', () => { success: true, }) - // 3. ReceiveExecutor -> OffRamp (ReleaseOrMint) -> TokenPool + // 3. ReceiveExecutor -> OffRamp (ReleaseOrMint) -> Router (relay) -> TokenPool expect(result.transactions).toHaveTransaction({ from: executorAddress, to: setup.offRamp.address, @@ -1860,6 +1861,12 @@ describe('OffRamp - Execute', () => { }) expect(result.transactions).toHaveTransaction({ from: setup.offRamp.address, + to: setup.router.address, + op: rt.Router_RelayReleaseOrMint.PREFIX, + success: true, + }) + expect(result.transactions).toHaveTransaction({ + from: setup.router.address, to: setup.tokenPool.address, op: tp.TokenPool_ReleaseOrMint.PREFIX, success: true, @@ -1921,8 +1928,10 @@ describe('OffRamp - Execute', () => { const result = await setup.executeReport(report) // Token transfer should still complete and notify success. + // The Router is the pool's only inbound entrypoint, so the pool hop + // originates from the Router relay. expect(result.transactions).toHaveTransaction({ - from: setup.offRamp.address, + from: setup.router.address, to: setup.tokenPool.address, op: tp.TokenPool_ReleaseOrMint.PREFIX, success: true, @@ -2026,12 +2035,20 @@ describe('OffRamp - Execute', () => { const result = await setup.executeReport(report) // The token pool should reject the releaseOrMint (rate limit exceeded). + // The Router holds the pool bounce and reports it to the OffRamp, which + // is the executor's only authority and forwards the failure. expect(result.transactions).toHaveTransaction({ - from: setup.offRamp.address, + from: setup.router.address, to: setup.tokenPool.address, op: tp.TokenPool_ReleaseOrMint.PREFIX, success: false, }) + expect(result.transactions).toHaveTransaction({ + from: setup.router.address, + to: setup.offRamp.address, + op: rt.Router_TokenPoolReleaseOrMintFailed.PREFIX, + success: true, + }) expect(result.transactions).toHaveTransaction({ from: setup.offRamp.address, to: setup.receiveExecutorAddress(message), @@ -2065,6 +2082,7 @@ describe('OffRamp - Execute', () => { // First execution fails due to rate limit. const firstResult = await setup.executeReport(report) expect(firstResult.transactions).toHaveTransaction({ + from: setup.router.address, to: setup.tokenPool.address, op: tp.TokenPool_ReleaseOrMint.PREFIX, success: false, @@ -2145,7 +2163,7 @@ describe('OffRamp - Execute', () => { success: true, }) - // 3. ReceiveExecutor -> OffRamp (ReleaseOrMint) -> TokenPool + // 3. ReceiveExecutor -> OffRamp (ReleaseOrMint) -> Router (relay) -> TokenPool expect(result.transactions).toHaveTransaction({ from: executorAddress, to: setup.offRamp.address, @@ -2154,6 +2172,12 @@ describe('OffRamp - Execute', () => { }) expect(result.transactions).toHaveTransaction({ from: setup.offRamp.address, + to: setup.router.address, + op: rt.Router_RelayReleaseOrMint.PREFIX, + success: true, + }) + expect(result.transactions).toHaveTransaction({ + from: setup.router.address, to: setup.tokenPool.address, op: tp.TokenPool_ReleaseOrMint.PREFIX, success: true, @@ -2264,12 +2288,20 @@ describe('OffRamp - Execute', () => { const result = await setup.executeReport(report) // The token pool should reject the releaseOrMint (rate limit exceeded). + // The Router holds the pool bounce and reports it to the OffRamp, which + // is the executor's only authority and forwards the failure. expect(result.transactions).toHaveTransaction({ - from: setup.offRamp.address, + from: setup.router.address, to: setup.tokenPool.address, op: tp.TokenPool_ReleaseOrMint.PREFIX, success: false, }) + expect(result.transactions).toHaveTransaction({ + from: setup.router.address, + to: setup.offRamp.address, + op: rt.Router_TokenPoolReleaseOrMintFailed.PREFIX, + success: true, + }) expect(result.transactions).toHaveTransaction({ from: setup.offRamp.address, to: setup.receiveExecutorAddress(message), @@ -2304,6 +2336,7 @@ describe('OffRamp - Execute', () => { // First execution fails due to rate limit. const firstResult = await setup.executeReport(report) expect(firstResult.transactions).toHaveTransaction({ + from: setup.router.address, to: setup.tokenPool.address, op: tp.TokenPool_ReleaseOrMint.PREFIX, success: false, diff --git a/contracts/tests/ccip/pools/TokenPool.behavior.ts b/contracts/tests/ccip/pools/TokenPool.behavior.ts index da4649710..71985fd4e 100644 --- a/contracts/tests/ccip/pools/TokenPool.behavior.ts +++ b/contracts/tests/ccip/pools/TokenPool.behavior.ts @@ -95,7 +95,7 @@ export function runTokenPoolBehaviorTests( from: ctx.unauthorized.address, to: ctx.pool.address, success: false, - exitCode: 14910, // TokenPool_Error.Unauthorized + exitCode: 51710, // TokenPool_Error.Unauthorized }) }) @@ -117,7 +117,7 @@ export function runTokenPoolBehaviorTests( from: ctx.offRamp.address, to: ctx.pool.address, success: false, - exitCode: 14910, // TokenPool_Error.Unauthorized + exitCode: 51710, // TokenPool_Error.Unauthorized }) }) diff --git a/contracts/tests/ccip/router/Router.cursing.spec.ts b/contracts/tests/ccip/router/Router.cursing.spec.ts index 2aac01f89..ec1a9b532 100644 --- a/contracts/tests/ccip/router/Router.cursing.spec.ts +++ b/contracts/tests/ccip/router/Router.cursing.spec.ts @@ -170,7 +170,7 @@ describe('Router.cursing', () => { }) }) - it('rejects ReleaseOrMint through replyTo while the source lane is cursed', async () => { + it('rejects ReleaseOrMint back to the OffRamp while the source lane is cursed', async () => { const sourceChainSelector = ChainSelectors.testselectors.CHAINSEL_EVM_TEST_90000001 await router.sendRouterRMNRemoteCurse(deployer.getSender(), toNano('1'), { queryId: 20n, @@ -207,7 +207,7 @@ describe('Router.cursing', () => { }) expect(result.transactions).toHaveTransaction({ from: router.address, - to: sender.address, + to: offRamp.address, success: true, op: rt.Router_TokenPoolReleaseOrMintFailed.PREFIX, }) diff --git a/contracts/wrappers/gen/ccip/OffRamp.ts b/contracts/wrappers/gen/ccip/OffRamp.ts index a59b3a5b5..08ea1ffa0 100644 --- a/contracts/wrappers/gen/ccip/OffRamp.ts +++ b/contracts/wrappers/gen/ccip/OffRamp.ts @@ -1321,60 +1321,6 @@ export const Any2TVMMessage = { } } -/** - > struct (0x351f77e3) TokenPool_ReleaseOrMint { - > queryId: uint64 - > request: Cell - > requestedFinalityConfig: uint32 - > replyTo: address? - > } - */ -export interface TokenPool_ReleaseOrMint { - readonly $: 'TokenPool_ReleaseOrMint' - queryId: uint64 - request: TokenPool_ReleaseOrMintInV1 - requestedFinalityConfig: uint32 - replyTo: c.Address | null /* = null */ -} - -export const TokenPool_ReleaseOrMint = { - PREFIX: 0x351f77e3, - - create(args: { - queryId?: uint64 - request: TokenPool_ReleaseOrMintInV1 - requestedFinalityConfig: uint32 - replyTo?: c.Address | null /* = null */ - }): TokenPool_ReleaseOrMint { - return { - $: 'TokenPool_ReleaseOrMint', - replyTo: null, - ...args, - queryId: args.queryId ?? 0n - } - }, - fromSlice(s: c.Slice): TokenPool_ReleaseOrMint { - loadAndCheckPrefix32(s, 0x351f77e3, 'TokenPool_ReleaseOrMint'); - return { - $: 'TokenPool_ReleaseOrMint', - queryId: s.loadUintBig(64), - request: loadCellRef(s, TokenPool_ReleaseOrMintInV1.fromSlice), - requestedFinalityConfig: s.loadUintBig(32), - replyTo: s.loadMaybeAddress(), - } - }, - store(self: TokenPool_ReleaseOrMint, b: c.Builder): void { - b.storeUint(0x351f77e3, 32); - b.storeUint(self.queryId, 64); - storeCellRef(self.request, b, TokenPool_ReleaseOrMintInV1.store); - b.storeUint(self.requestedFinalityConfig, 32); - b.storeAddress(self.replyTo); - }, - toCell(self: TokenPool_ReleaseOrMint): c.Cell { - return makeCellFrom(self, TokenPool_ReleaseOrMint.store); - } -} - /** > type CrossChainAddress = slice */ @@ -2017,6 +1963,127 @@ export const Router_RouteMessage = { } } +/** + > struct (0xb19862a3) Router_RelayReleaseOrMint { + > queryID: uint64 + > sourceChainSelector: uint64 + > tokenPool: address + > request: Cell + > requestedFinalityConfig: uint32 + > replyTo: address + > } + */ +export interface Router_RelayReleaseOrMint { + readonly $: 'Router_RelayReleaseOrMint' + queryID: uint64 + sourceChainSelector: uint64 + tokenPool: c.Address + request: TokenPool_ReleaseOrMintInV1 + requestedFinalityConfig: uint32 + replyTo: c.Address +} + +export const Router_RelayReleaseOrMint = { + PREFIX: 0xb19862a3, + + create(args: { + queryID?: uint64 + sourceChainSelector: uint64 + tokenPool: c.Address + request: TokenPool_ReleaseOrMintInV1 + requestedFinalityConfig: uint32 + replyTo: c.Address + }): Router_RelayReleaseOrMint { + return { + $: 'Router_RelayReleaseOrMint', + ...args, + queryID: args.queryID ?? 0n + } + }, + fromSlice(s: c.Slice): Router_RelayReleaseOrMint { + loadAndCheckPrefix32(s, 0xb19862a3, 'Router_RelayReleaseOrMint'); + return { + $: 'Router_RelayReleaseOrMint', + queryID: s.loadUintBig(64), + sourceChainSelector: s.loadUintBig(64), + tokenPool: s.loadAddress(), + request: loadCellRef(s, TokenPool_ReleaseOrMintInV1.fromSlice), + requestedFinalityConfig: s.loadUintBig(32), + replyTo: s.loadAddress(), + } + }, + store(self: Router_RelayReleaseOrMint, b: c.Builder): void { + b.storeUint(0xb19862a3, 32); + b.storeUint(self.queryID, 64); + b.storeUint(self.sourceChainSelector, 64); + b.storeAddress(self.tokenPool); + storeCellRef(self.request, b, TokenPool_ReleaseOrMintInV1.store); + b.storeUint(self.requestedFinalityConfig, 32); + b.storeAddress(self.replyTo); + }, + toCell(self: Router_RelayReleaseOrMint): c.Cell { + return makeCellFrom(self, Router_RelayReleaseOrMint.store); + } +} + +/** + > struct (0xb980cb4e) Router_TokenPoolReleaseOrMintFailed { + > queryID: uint64 + > sourceChainSelector: uint64 + > replyTo: address + > tokenPool: address + > exitCode: int32 + > } + */ +export interface Router_TokenPoolReleaseOrMintFailed { + readonly $: 'Router_TokenPoolReleaseOrMintFailed' + queryID: uint64 + sourceChainSelector: uint64 + replyTo: c.Address + tokenPool: c.Address + exitCode: int32 +} + +export const Router_TokenPoolReleaseOrMintFailed = { + PREFIX: 0xb980cb4e, + + create(args: { + queryID?: uint64 + sourceChainSelector: uint64 + replyTo: c.Address + tokenPool: c.Address + exitCode: int32 + }): Router_TokenPoolReleaseOrMintFailed { + return { + $: 'Router_TokenPoolReleaseOrMintFailed', + ...args, + queryID: args.queryID ?? 0n + } + }, + fromSlice(s: c.Slice): Router_TokenPoolReleaseOrMintFailed { + loadAndCheckPrefix32(s, 0xb980cb4e, 'Router_TokenPoolReleaseOrMintFailed'); + return { + $: 'Router_TokenPoolReleaseOrMintFailed', + queryID: s.loadUintBig(64), + sourceChainSelector: s.loadUintBig(64), + replyTo: s.loadAddress(), + tokenPool: s.loadAddress(), + exitCode: s.loadIntBig(32), + } + }, + store(self: Router_TokenPoolReleaseOrMintFailed, b: c.Builder): void { + b.storeUint(0xb980cb4e, 32); + b.storeUint(self.queryID, 64); + b.storeUint(self.sourceChainSelector, 64); + b.storeAddress(self.replyTo); + b.storeAddress(self.tokenPool); + b.storeInt(self.exitCode, 32); + }, + toCell(self: Router_TokenPoolReleaseOrMintFailed): c.Cell { + return makeCellFrom(self, Router_TokenPoolReleaseOrMintFailed.store); + } +} + /** > struct (0x9d431905) OffRamp_Commit { > queryId: uint64 @@ -4217,7 +4284,7 @@ function calculateDeployedAddress(code: c.Cell, data: c.Cell, options: DeployedA } export class OffRamp implements c.Contract { - static CodeCell = c.Cell.fromBase64('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'); + static CodeCell = c.Cell.fromBase64('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'); static Errors = { 'MerkleMultiProof_Error.InvalidProofLeavesCannotBeEmpty': 12000, @@ -4391,6 +4458,16 @@ export class OffRamp implements c.Contract { return OffRamp_CCIPReceiveBounced.toCell(OffRamp_CCIPReceiveBounced.create(body)); } + static createCellOfRouterTokenPoolReleaseOrMintFailed(body: { + queryID?: uint64 + sourceChainSelector: uint64 + replyTo: c.Address + tokenPool: c.Address + exitCode: int32 + }) { + return Router_TokenPoolReleaseOrMintFailed.toCell(Router_TokenPoolReleaseOrMintFailed.create(body)); + } + static createCellOfOffRampNotifyFailure(body: { header: RampMessageHeader execId: ReceiveExecutorId @@ -4598,6 +4675,20 @@ export class OffRamp implements c.Contract { }); } + async sendRouterTokenPoolReleaseOrMintFailed(provider: ContractProvider, via: Sender, msgValue: coins, body: { + queryID?: uint64 + sourceChainSelector: uint64 + replyTo: c.Address + tokenPool: c.Address + exitCode: int32 + }, extraOptions?: ExtraSendOptions) { + return provider.internal(via, { + value: msgValue, + body: Router_TokenPoolReleaseOrMintFailed.toCell(Router_TokenPoolReleaseOrMintFailed.create(body)), + ...extraOptions + }); + } + async sendOffRampNotifyFailure(provider: ContractProvider, via: Sender, msgValue: coins, body: { header: RampMessageHeader execId: ReceiveExecutorId diff --git a/contracts/wrappers/gen/ccip/Router.ts b/contracts/wrappers/gen/ccip/Router.ts index 1b3890315..30d7dcd77 100644 --- a/contracts/wrappers/gen/ccip/Router.ts +++ b/contracts/wrappers/gen/ccip/Router.ts @@ -3225,6 +3225,8 @@ export const Router_TokenPoolLockOrBurnFailed = { /** > struct (0xb980cb4e) Router_TokenPoolReleaseOrMintFailed { > queryID: uint64 + > sourceChainSelector: uint64 + > replyTo: address > tokenPool: address > exitCode: int32 > } @@ -3232,6 +3234,8 @@ export const Router_TokenPoolLockOrBurnFailed = { export interface Router_TokenPoolReleaseOrMintFailed { readonly $: 'Router_TokenPoolReleaseOrMintFailed' queryID: uint64 + sourceChainSelector: uint64 + replyTo: c.Address tokenPool: c.Address exitCode: int32 } @@ -3241,6 +3245,8 @@ export const Router_TokenPoolReleaseOrMintFailed = { create(args: { queryID?: uint64 + sourceChainSelector: uint64 + replyTo: c.Address tokenPool: c.Address exitCode: int32 }): Router_TokenPoolReleaseOrMintFailed { @@ -3255,6 +3261,8 @@ export const Router_TokenPoolReleaseOrMintFailed = { return { $: 'Router_TokenPoolReleaseOrMintFailed', queryID: s.loadUintBig(64), + sourceChainSelector: s.loadUintBig(64), + replyTo: s.loadAddress(), tokenPool: s.loadAddress(), exitCode: s.loadIntBig(32), } @@ -3262,6 +3270,8 @@ export const Router_TokenPoolReleaseOrMintFailed = { store(self: Router_TokenPoolReleaseOrMintFailed, b: c.Builder): void { b.storeUint(0xb980cb4e, 32); b.storeUint(self.queryID, 64); + b.storeUint(self.sourceChainSelector, 64); + b.storeAddress(self.replyTo); b.storeAddress(self.tokenPool); b.storeInt(self.exitCode, 32); }, @@ -3655,7 +3665,7 @@ function calculateDeployedAddress(code: c.Cell, data: c.Cell, options: DeployedA } export class Router implements c.Contract { - static CodeCell = c.Cell.fromBase64('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'); + static CodeCell = c.Cell.fromBase64('te6ccgECXAEAEhsAART/APSkE/S88sgLAQIBYgIDAgLGICECASAEBQIBIAYHAgEgGBkCASAICQIBIA4PAgEgCgsAG7XFEEAb4ZQEEIH3flCQAgEgDA0ATbBX40GmxpbmsuY2hhaW4udG9uLmNjaXAuUm91dGVygi1MS42LjGIAB3r4R2omg2gOmPmP0kGP0oGP0kGPoCkEAgekM30shHDKkBfSRogWRln4l9KWSoAbeBKJDAIHo+N9L0L4HAAE2sXXaiaGmPmP0kGP0oGP0kGPoA+gLBAG+GrMAgegc30Il5en0kaMACAnEQEQIBIBITABWmO9qJoaY+Y/SQYQAJpQsCBHcAgbOtu1E0NMfMfpIMfpQMfpIMfQB9AHXTND6SDH6UDH0BPQEMdFtIYMG9IZvpTKRAZ1SAm8CURKDBvR8b6Uy6DAxgAgEgFBUAe67+dqJoNoDpj5j9JBj9KBj9JBj6APoCkEAgekM30shHDKkBfSRogWRln4l9KWSoAbeBKJDAIHo+N9L0L4HAAgFmFhcAG6OvtRNDTHzH6SDH6UDCAEeiG7UTQ0x8x+kgx+lAx+kgx9AWCAN8MWYBA9A5voRLy9PpI0YASbrejtRNDTHzH6SDH6UDH6SDH0AfQB10zQ+kgx+lD0BDH0BDHRgCASAaGwIDeOAcHQIBIB4fAA+jMghA7msoAgBHoeO1E0NMfMfpIMfpQMfpIMfQB9AHXTND6SPpQMfQEMfQEMdGAFGy4HtRNDTHzH6SDH6UDH6SDH0AfQB10zQ+kgx+lAx9AT0BDHRAfADs4ABfscn7UTQ0x8x+kgx+lAx+kgx9AVtIYBA9IZvpTKRAZ1SAm8CURKAQPR8b6Uy6DAxgAgHNIiMCA6PSWlsCASAkJQIBIFBRAgEgJicCASBNTgP3PiRkvAE4CDXLCPts6Ls4wLXLCGLtGysjlgxggkxLQCCCdkFwIIQBV1KgIIQBOM4gIILwU3AtgmgghAL68IAoKCgggDfFfiXWL7y9NM/0z/TByHBQfKFAaoC1xjU1PpQ10yCAN8WI9DHAPL0+JL4l/AG4NcsIm61VBTjAoCgpKgLfDT4J28QIW6RMZI1BOIDjqmCAN8OAfLyggDfDVEjvBLy9AFw+wKDBojIz4UIE/pScc8LbhLMyQH7AOCCAN8OIcIA8vSCAN8MUxO58vQCggDfDQShIrwT8vSAQIjIz4UIFPpSWPoCcc8LahLMyQH7AIExMBPQx7UTQ0x/6SPpQ+kj0BPQE10z4koIAwohRF8cF8vQH0z8x0wABltT6UIEAipRtbVhw4gHTAAGW1PpIgQCLlG1tWHDiAdMAAZfU+kgwgQCLlDBtbXDiBpI2NuMNA5IzM+MNkVvjDQbQ+kj6UPQE9AQx0W0pgED0hm+lkCssLS4AbDGCCUBvQIIQBV1KgIIJQG9AgglAb0C2CaCggglAb0CCCUBvQLYJoIIA3xX4l1i+8vTU+JLwBQT6idcnjmsx7UTQAfoA1PpIItAF0x8x+kgx+lAx+kgx9AUF1ywhi7RsrPK/0z8x1ws/+JKCAN8MUCeAQPQOb6EX8vQF+kjRBYIA3xIGxwUV8vTIz5J4hVeyUAP6AswSzsnIz4UIEvpScc8LbszJgED7AODXLCVg7ol04wKJ1ycwMTIzAKgn0JQgxwCzjisg10sBkTCbgTS8AcAB8vTXTNDi0z8obpYLgED0WzCaKMj6UkAMgED0Q+IK6DDIz48YAASCEH4k597PC/dwzwthGMwW+lTJcPsAEEUAwCTQlCDHALOOOCDXSwGRMJuBNLwBwAHy9NdM0OLTP4IA3w9TKIBA9A5voRLy9PpI0YIA3xBRF8cF8vQHgED0WzAG6DDIz48YAASCEFzZFvzPC/dwzwthFcwT+lLJcPsAEgCMIdCUIMcAs44gINdLAZEwm4E0vAHAAfL010zQ4tM/Isj6UkAFgED0QwPoMMjPjxgABIIQMEBnYc8L93DPC2ESzPpSyXD7AAFIiuhbA8j6UhL6VPQA9ADJBcjLHxT6UhL6VPpS9AAS9ADMye1ULwAqAfpI0chAE4EBC/RRMFEagED0fG+lAAgq+xG9ANQx7UTQAdP/1PpIItAF0x8x+kgx+lAx+kgx9AUF1ywhi7RsrPK/0z8x1ws/+JKCAN8MUCeAQPQOb6EX8vQF+kjRBYIA3xIGxwUV8vTIz5OwjxWKE8v/zBLOycjPhYgS+lJxzwtuzMmAQPsAAAj8acULAf6OfDHtRNAB1NO/+kj6ADAj0AXTHzH6SDH6UDH6SDH0BDH0BNdMBtP/MdcLPyCCAN8NA4BA9A5voRPy9AH6SNGCAN8O+JJYxwXy9IIA3xEG0PpIMfpQMfQE9AQx0QHwA7MV8vTIz4WI+lJQA/oCghBbS8emzwuKEsu/zMlx+wDgNAT0idcn4wLXLCDyrd+0jlsxggDfFfiXggkxLQC+8vTXC7/4ku1E0CLIy7/PUNcLPwHTHzH6SDH6UDH6SDH0AfQFggDfDVmAQPQOb6ES8vT6SNHIz4WI+lKCECj0Fm/PC44Sy7/6UsmAQPsA4NcsJ5nEAjTjAtcsIfip0Yw1Njc4AAgZ8AmPAf4x7UTQAdM/0z/XTAPTHzH6SDH6UDH6SDH0BfiSggDfDFEygED0Dm+hM1ry9PpI0QGCAN8SAscF8vQB0PpI+gD6SNdMbW2CEB3NZQADyPQAz1DIz5A+KfqWGMs/UAX6AhP6UhL6VBL0AAH6AhLOycjPhYgS+lLPhBBz+gJxzwtlOQH+Me1E0NMf+kj6UPpI9AT0BNdMINAx+kj6UPQE9ATR+JKCAMKIURXHBfL0CtM/MddM0JQgxwCzjjkg10sBkTCbgTS8AcAB8vTXTNDi03/IVCAkgwb0UzDIz48YAASCEMzoMmPPC/dwzwthEst/yXD7AAHoMALI+lL6VFIQ9ABSgDoE+OMC1ywgXK1SdI4oMdM/1wt/ggHrge1D2PiSyM+FCPpSghAiuoOzzwuOEss/ygDJgED7AODXLCV71NY04wLXLCeaH+DcjjIx7UTQ0x8x+kgw+JKCAMKIAscF8vTTP/pI+gDTAAGS+gCSbQHi1woAghA7msoAVUDwAeCJ1yc7PD0+AAzMyYBA+wAApvQAyQfIyx8W+lIU+lQS+lL0APQAEszJ7VQhgQEL9IJvpTKRAY4qIIIK+vCAyM+FCBL6UgH6AoIQTKG8s88LilIg9ADJcvsAIoEBC/R0b6Uy6F8DAf4x7UTQ0x/6SPpQ+kj0BPQE10wg0DH6SPpQ9AT0BNH4koIAwohRFccF8vQK0z8x10zQlCDHALOONyDXSwGRMJuBNLwBwAHy9NdM0OLTf1ITgwb0WzDIz48YAASCENnrg4XPC/dwzwthEst/yXD7AAHoMALI+lL6VFIQ9ABSgPQAPwCWMe1E0NYf+kj6UPpI9AT0BNdM0PpI+lD0BPQE0fiSEDREC/ACjiAByPpS+lT0ABf0AMkFyM4U+lIS+lT6UvQAEvQAzMntVOCED/LwAAgKqBHtBPaOXTHtRNDTHzH6SDD4koIAwogCxwXy9NM/MddMk/ED6ACT8QPpACDaASP7BCPQ7R7tU+1EQBPaIe1UIfkAAdoBAsjMy//OycjPjxgABIIQoztJjs8L93HPC2HMyXD7AODXLCMon8cM4wLXLCRXEoik4wLXLCN5aAb84wJAQUJDAKLJB8jLHxb6UhT6VBL6UvQA9AASzMntVCGBAQv0gm+lMpEBjiogggr68IDIz4UIEvpSAfoCghBMobyzzwuKUiD0AMly+wAigQEL9HRvpTLoXwMApjHtRNAB0z/T/9M/+kgwBNMfMfpIMfpQMfpIMfQF+JKCAN8MWoBA9A5voRLy9PpI0QGCAN8SAscF8vTIz4UIE/pSghB40PIezwuOyz/L/8mAQPsAAKgx7UTQAdM/0z/6SNcL/wTTHzH6SDH6UDH6SDH0BfiSggDfDFBCgED0Dm+hEvL0+kjRAoIA3xIDxwUS8vTIz4WI+lKCEFpF1DTPC47LP8v/yYBA+wAC/jHtRNAB0z/6SNT6SDAh0NP/MddM0AXTHzH6SDH6UDH6SDH0BPQEMddMBtcLP/iSIYIA3wwEgED0Dm+hFPL0AvpI0QKCAN8SA8cFEvL0BdD6SDH6UDH0BPQEMdFQBfAD4wJtyM+T6faREhTLP8zPkAAAAAIS9AAS+lTJyM+FiBJERQNwidcn4wLXLCObFoTk4wIw7UTQ1h/6SPpQ+JJDMCXwAp40AsjOEvpSEvpUzsntVOBfBIQPAccA8vRGR0gAQDDIz4UIE/pSghC3bjqEzwuOyz/6Us+QAAN8RsmAQPsAACT6Us+EEHP6AnHPC2XMyYBA+wAACLGYYqMC+DHtRNAB0z/TP/pI1NMf+kgwBtMfMfpIMfpQMfpIMfQEMfQE10wlggDfDQOAQPQOb6ET8vQB+kjRggDfDviSIscF8vQj0NP/MddM0PpIMdcLP4IA3xpRF7ry9AHQ+kgx+lAx9AT0BDHRJfAD4wIwM8jPhYgS+lLPhBBz+gJJSgH+MYIJMS0AggnZBcCCEAVdSoCCEATjOICCC8FNwLYJoIIQC+vCAKCgoIIA3xX4l1i+8vTTPzH6APpQ10zQ1ywhi7RsrPK/0z/TP9MHIcFB8oUBqgLXGNTU+lDXTCLQggDfEyHHALPy9CDXSwGRMJuBNLwBwAHy9NdM0OL6APpIMUsAWmwhyM+S5gMtOhTLPxLLPxP6UhL6Us+QAAN8RsnIz4UIEvpScc8LbszJgED7AAAughA1H3fjzwuFE8s/EszLH/pUyYBA+wAARAGCAN8YC7oa8vSCAN8UCccAGfL0+JcQaBBXEEYQNUQw8AYAAAGpO2i7fvXLCeQ2+0MjkTXLCfPFPJUlFtw2zHhggDCiiNus/L0IYIAwooExwUT8vQgbQPXCz+LAgHIyz8V+lIS+lLJyM+HIBTOcc8LYRPMyXD7AOMNf4E8AVwhbpJbcOCCaQAAAAAAAAAAAAAAAAAAASKDBvQOb6Exklt/4AGDBvQOb6ExgAGZsEtM/+kgwggDCiFE0xwUT8vSCAMKJUyPHBbPy9CGLAsjPhyDOcM8LYRLLPxL6Uslw+wACASBSUwH3TtRNDTHzH6SDH6UDH6SPQE9AHXTND6SDH6UDH0BPQEMdEq8AOCAN8RAbPy9CVukjUEkTHiUoCAQPQOb6GOIRAoXwjIz4WI+lKCEFpF1DTPC47LP4IA3wzPC//JgED7AOH6SNHIz5DF2jZWGss/GMs/JtdJIKk4AvJFqwKFkD9Qg1wsfghD////+uo7Z1ywn////9PK/1NMHMdcKHwHQ1ywn0+0iJI4y0z/UMdMfMfQB+lAwIG6SXwOOHviSyM+FCBL6UoIQt246hM8LjhLLP/pSyh/JgED7AOLg1ywhqPu/HOMC8j/g0x8x1ywi2l49NOMC1ywhR6CzfIFRVVgL3O1E0FMz0ALTHzH6SDH6UDH6SPQFA9csIYu0bKzyv9Y/0z/TByHBQfKFAaoC1xjU1PpQUlqAQPQOb6GOJV8KyM+TsI8VioIA3wzPC/8TzM7JyM+FiBL6UnHPC27MyYBA+wDhPG6UEGdfB+MNA/pI0cjPknCzMfoUzPpSzoFdYAODTP9TTHzH6UDAgbpJfBI5fAdDT/zHXTNDtRNAB+kgx1ws/AdMfMfpIMfpQMfpIMfQB9AUhggDfDQKAQPQOb6ES8vT6SNH4ksjPkuYDLToVyz8Syz8S+lIS+lISyh/JyM+FCBL6UnHPC27MyYBA+wDiAK7XC7/4ku1E0NMfMfpIMfpQMfpIMfQEMfQE1DHRIsjLv89Q1ws/ggDfDQKAQPQOb6ES8vT6SNGCCRKogMjPhYgS+lIB+gKCEC3PKkPPC4oSy7/6Uslw+wAAqo4j1wu/+JLI+lLLv8nIz48YAASCEFjk9mTPC/dxzwthzMlw+wDg1ywhbnlSHI4j1wu/+JLI+lLLv8nIz48YAASCEFjk9mTPC/dxzwthzMlw+wDg8j8AUDbIz5DF2jZWFM4Syz8h10kgqTgC8kWrAiDBQfKFzwsHzswSzPpUzskAJMnIz4WIEvpScc8LbszJgED7AABeIMFB8oXPCwcWzhTMEsz6VMzJyM+FiBT6UoIQ3PmTws8LjhPMEvpSAfoCyYBA+wAAHyBTbwBi1MS42LjCMcF8vSAADyLUxLjYuMYg'); static Errors = { 'Common_Error.CrossChainAddressOutOfRange': 5, From f15f1525c00d7aa4d7c5bccc0c90651fd74de697 Mon Sep 17 00:00:00 2001 From: Kristijan Date: Mon, 14 Sep 2026 15:16:45 +0200 Subject: [PATCH 08/23] Tighten chokepoint comments and add relay failure-path coverage - Fix stale comment on the OffRamp bounce handler (failure is reported to the OffRamp, not proxied to the executor). - Trim verbose comments on the relay/failure helpers. - Add tests: OffRamp rejects Router_TokenPoolReleaseOrMintFailed from a non-router sender; Router rejects a relay from an unregistered OffRamp and one whose request selector mismatches the source chain. --- .../contracts/ccip/offramp/contract.tolk | 28 +++----- contracts/contracts/ccip/router/contract.tolk | 11 ++- .../ccip/offramp/OffRamp.execute.spec.ts | 23 +++++++ .../tests/ccip/router/Router.cursing.spec.ts | 69 +++++++++++++++++++ 4 files changed, 106 insertions(+), 25 deletions(-) diff --git a/contracts/contracts/ccip/offramp/contract.tolk b/contracts/contracts/ccip/offramp/contract.tolk index d1653c6c2..6589a0d93 100644 --- a/contracts/contracts/ccip/offramp/contract.tolk +++ b/contracts/contracts/ccip/offramp/contract.tolk @@ -246,12 +246,9 @@ fun onBouncedDeployableInitialize(msg: Deployable_Initialize, senderAddress: add }); } -// Handles bounced Router_RelayReleaseOrMint messages: the Router rejected the -// relay (e.g. this OffRamp is no longer registered, or the Router reverted). -// Sends a OffRamp_ReleaseOrMintBounced message to the ReceiveExecutor to mark -// the execution as failed. Pool bounces never reach the OffRamp: the Router -// holds the bounce and proxies failures to the executor as -// Router_TokenPoolReleaseOrMintFailed. +// Handles a bounced Router_RelayReleaseOrMint: the Router rejected the relay +// (e.g. this OffRamp is no longer registered, or it reverted). Fails the +// executor through the usual rail. fun onBouncedRouterRelayReleaseOrMint(msg: Router_RelayReleaseOrMint, exitCode: int32) { mintOrReleaseFailed(msg.replyTo, msg.queryID, ReleaseOrMintBounced { exitCode }); } @@ -474,23 +471,16 @@ fun mintOrReleaseFailed(receiveExecutor: address, queryID: uint64, reason: Relea receiveBounced.send(SEND_MODE_CARRY_ALL_REMAINING_MESSAGE_VALUE); } -// Handles a Router-reported release/mint failure (lane cursed, or the token -// pool bounced the relay). The Router is the pool's only authority, so it -// reports back to us and we fail the executor through the usual rail. +// Fails the executor after the Router reported a release/mint failure (lane +// cursed, or the pool bounced the relay). fun onTokenPoolReleaseOrMintFailed(msg: Router_TokenPoolReleaseOrMintFailed) { mintOrReleaseFailed(msg.replyTo, msg.queryID, ReleaseOrMintBounced { exitCode: msg.exitCode }); } -// Relays a release/mint request to the token pool through the Router, which is -// the single access point of every token pool (mirrors EVM `_onlyOffRamp`, -// where the pool validates the caller against the Router). The Router -// authorizes this OffRamp for the source chain and enforces its RMN policy -// before dispatching `TokenPool_ReleaseOrMint` to the pool. -// -// The pool replies (`ReleaseOrMintFinished`/`ReleaseOrMintFailure`) directly to -// `sendExecutor` (carried as `replyTo`). Relay rejections and pool bounces are -// proxied by the Router as `Router_TokenPoolReleaseOrMintFailed` to the same -// address, so the executor sees a canonical failure either way. +// Relays a release/mint request through the Router, the single access point of +// every pool (mirrors EVM `_onlyOffRamp`). Pool replies go straight to +// `sendExecutor`; relay rejections and pool bounces come back to us as +// Router_TokenPoolReleaseOrMintFailed. fun onReleaseOrMint(st: Storage, sendExecutor: address, msg: OffRamp_ReleaseOrMint) { if (msg.destGasAmount < MIN_TT_GASLIMIT) { return mintOrReleaseFailed(getReceiverExecutorDeployAddress(st, msg.execId).calculateAddress(), msg.queryId, NotEnoughDestGasAmountForTokenTransfer {}); diff --git a/contracts/contracts/ccip/router/contract.tolk b/contracts/contracts/ccip/router/contract.tolk index 547ddf914..73f2f7862 100644 --- a/contracts/contracts/ccip/router/contract.tolk +++ b/contracts/contracts/ccip/router/contract.tolk @@ -269,8 +269,8 @@ fun onBouncedMessage(in: InMessageBounced) { } TokenPool_ReleaseOrMint => { if (richMsg.replyTo != null) { - // Recover the lane from the request the pool was asked to - // process, then route the failure back through its OffRamp. + // Recover the lane from the request and route the failure + // back through its OffRamp. val request = lazy richMsg.request.load(); val details = lazy request.transfer.details.load(); val st = lazy Storage.load(); @@ -839,10 +839,9 @@ fun sendLockOrBurnRelayFailure( failed.send(SEND_MODE_CARRY_ALL_REMAINING_MESSAGE_VALUE); } -/// Reports an inbound release/mint failure to the OffRamp that owns the source -/// lane. The OffRamp is the ReceiveExecutor's sole authority, so the Router -/// never talks to the executor directly (mirrors EVM, where the failure rail -/// lives on the OffRamp). `replyTo` is the executor the OffRamp must fail. +/// Reports an inbound release/mint failure to the OffRamp that owns the lane. +/// The OffRamp is the executor's sole authority (mirrors EVM), so the Router +/// never talks to the executor directly. `replyTo` is the executor to fail. fun sendReleaseOrMintRelayFailure( offRamp: address, sourceChainSelector: uint64, diff --git a/contracts/tests/ccip/offramp/OffRamp.execute.spec.ts b/contracts/tests/ccip/offramp/OffRamp.execute.spec.ts index 1d70110ed..c63cdf728 100644 --- a/contracts/tests/ccip/offramp/OffRamp.execute.spec.ts +++ b/contracts/tests/ccip/offramp/OffRamp.execute.spec.ts @@ -1919,6 +1919,29 @@ describe('OffRamp - Execute', () => { // 2. verify the receiver can withdraw the tokens from the escrow account. }) + it('rejects a Router_TokenPoolReleaseOrMintFailed from a non-router sender', async () => { + await setup.setupSourceChainConfig() + + const result = await setup.offRamp.sendRouterTokenPoolReleaseOrMintFailed( + setup.deployer.getSender(), + toNano('0.5'), + { + queryID: 1n, + sourceChainSelector: setup.SOURCE_CHAIN_SELECTOR, + replyTo: setup.deployer.address, + tokenPool: setup.tokenPool.address, + exitCode: 0n, + }, + ) + + expect(result.transactions).toHaveTransaction({ + from: setup.deployer.address, + to: setup.offRamp.address, + success: false, + exitCode: of.OffRamp.Errors['OffRamp_Error.Unauthorized'], + }) + }) + it('executes a token transfer to a non-contract receiver', async () => { const stranger = await blockchain.treasury('stranger') const message = setup.createTestMessageWithToken({ receiverAddress: stranger.address }) diff --git a/contracts/tests/ccip/router/Router.cursing.spec.ts b/contracts/tests/ccip/router/Router.cursing.spec.ts index ec1a9b532..2699112e1 100644 --- a/contracts/tests/ccip/router/Router.cursing.spec.ts +++ b/contracts/tests/ccip/router/Router.cursing.spec.ts @@ -217,6 +217,75 @@ describe('Router.cursing', () => { }) }) + it('rejects a ReleaseOrMint relay from an unregistered OffRamp', async () => { + const sourceChainSelector = ChainSelectors.testselectors.CHAINSEL_EVM_TEST_90000001 + + const result = await router.sendRouterRelayReleaseOrMint(sender.getSender(), toNano('1'), { + queryID: 30n, + sourceChainSelector, + tokenPool: deployer.address, + request: rt.TokenPool_ReleaseOrMintInV1.create({ + transfer: rt.TokenPool_Transfer.create({ + id: 30n, + details: rt.TokenPool_TransferDetails.create({ + originalSender: EVM_ADDRESS, + remoteChainSelector: sourceChainSelector, + receiver: sender.address, + amount: 1n, + localToken: sender.address, + }), + }), + sourcePoolAddress: EVM_ADDRESS, + sourcePoolData: null, + offchainTokenData: null, + }), + requestedFinalityConfig: 0n, + replyTo: sender.address, + }) + + expect(result.transactions).toHaveTransaction({ + from: sender.address, + to: router.address, + success: false, + exitCode: rt.Router.Errors['Router_Error.SenderIsNotOffRamp'], + }) + }) + + it('rejects a ReleaseOrMint relay whose request selector mismatches the source chain', async () => { + const sourceChainSelector = ChainSelectors.testselectors.CHAINSEL_EVM_TEST_90000001 + + const result = await router.sendRouterRelayReleaseOrMint(offRamp.getSender(), toNano('1'), { + queryID: 31n, + sourceChainSelector, + tokenPool: deployer.address, + request: rt.TokenPool_ReleaseOrMintInV1.create({ + transfer: rt.TokenPool_Transfer.create({ + id: 31n, + details: rt.TokenPool_TransferDetails.create({ + // Mismatched remote chain selector. + originalSender: EVM_ADDRESS, + remoteChainSelector: sourceChainSelector + 1n, + receiver: sender.address, + amount: 1n, + localToken: sender.address, + }), + }), + sourcePoolAddress: EVM_ADDRESS, + sourcePoolData: null, + offchainTokenData: null, + }), + requestedFinalityConfig: 0n, + replyTo: sender.address, + }) + + expect(result.transactions).toHaveTransaction({ + from: offRamp.address, + to: router.address, + success: false, + exitCode: rt.Router.Errors['Router_Error.SourceChainSelectorMismatch'], + }) + }) + it('router respect global cursing', async () => { // Curse all lanes { From 3870497995d867659021cc96fb43bd308a46903f Mon Sep 17 00:00:00 2001 From: Kristijan Date: Tue, 15 Sep 2026 10:31:27 +0200 Subject: [PATCH 09/23] Sync Go bindings and deployment with Router-only pool ABI Mirror the feat/tp-only-router contract changes in the hand-maintained Go bindings and the TON CCIP deployment sequences: - tokenpool: replace MirroredPolicy with LocalPolicy (pool-local RMN cursed-subjects only); ramp access is no longer pool state because the Router is the pool's sole entrypoint (onlyRouter). - tokenpool: model allowedDepositNamespaces as a unit-value set (map) via *cell.Dictionary, matching the Tolk contract. - tokenpool: drop the removed UpdateRampAccess / RampAccessUpdatesApplied surfaces and the GetOnRamp/GetOffRamp/GetMirroredPolicy readers, and nil-check getRMNProxy's optional address. - Correct four pre-existing opcode drifts (SetDeployableCode, DeployableCodeSet, SetAllowedDepositNamespaces, AllowedDepositNamespacesSet) verified against the Tolk message prefixes. - deployment/1_6_0: stop writing ramp access on the pool; the OffRamp is registered in the Router's offRamps map by the lane's ApplyRampUpdates. - token-pools IMPLEMENTATION doc: describe the Router chokepoint and local RMN policy instead of the mirrored onRamp/offRamp maps. --- deployment/ccip/1_6_0/sequences/tokens.go | 88 +++---------------- .../ccip/token-pools/IMPLEMENTATION.md | 14 +-- .../bindings/tokenpool/burnmint/reader.go | 3 - .../bindings/tokenpool/lockrelease/reader.go | 3 - .../tokenpool/lockreleaselockbox/reader.go | 3 - pkg/ccip/bindings/tokenpool/reader.go | 78 +++------------- pkg/ccip/bindings/tokenpool/types.go | 69 +++++---------- 7 files changed, 53 insertions(+), 205 deletions(-) diff --git a/deployment/ccip/1_6_0/sequences/tokens.go b/deployment/ccip/1_6_0/sequences/tokens.go index f80d3bab6..669c0215c 100644 --- a/deployment/ccip/1_6_0/sequences/tokens.go +++ b/deployment/ccip/1_6_0/sequences/tokens.go @@ -399,10 +399,11 @@ func (a *TonTokenAdapter) DeployTokenPoolForToken() *cldf_ops.Sequence[tokensapi }, RMNProxy: owner, DynamicConfig: tokenpool.DynamicConfig{ - Router: &routerAddr, - RateLimitAdmin: rateLimitAdmin, - FeeAdmin: feeAdmin, - AllowedDepositNamespaces: tlbe.NewEmptyDict[uint32, bool](), + Router: &routerAddr, + RateLimitAdmin: rateLimitAdmin, + FeeAdmin: feeAdmin, + // Unit-value dict (map); nil serializes as an empty map. + AllowedDepositNamespaces: nil, }, JettonClient: tokenpool.JettonClient{ MasterAddress: tokenAddr, @@ -411,11 +412,9 @@ func (a *TonTokenAdapter) DeployTokenPoolForToken() *cldf_ops.Sequence[tokensapi AllowedFinalityConfig: allowedFinality, AdvancedPoolHooks: nil, }, - MirroredPolicy: tokenpool.MirroredPolicy{ - // nil dicts serialize as an empty map (a single "no entries" bit), matching - // the Tolk contract's createEmptyMap() default. - OnRamps: nil, - OffRamps: nil, + LocalPolicy: tokenpool.LocalPolicy{ + // nil dict serializes as an empty map (a single "no entries" bit), + // matching the Tolk contract's createEmptyMap() default. CursedSubjects: tokenpool.CursedSubjects{Data: nil}, }, TokenDecimals: defaultJettonDecimals, @@ -510,9 +509,9 @@ func (a *TonTokenAdapter) ConfigureTokenForTransfersSequence() *cldf_ops.Sequenc return sequences.OnChainOutput{}, fmt.Errorf("retrieve Deployable code for TokenAdminRegistry entry: %w", err) } - // The OffRamp always comes from the datastore: it is the contract that sends - // TokenPool_ReleaseOrMint to the pool, so it must be registered as the pool's - // trusted offRamp (see applyRampAccessUpdates below). + // The OffRamp is registered in the Router's offRamps map by the lane's + // ApplyRampUpdates sequence; the Router forwards ReleaseOrMint to the pool, + // so the pool itself no longer tracks per-lane ramps. stateCCIP, loadErr := tonstate.LoadCCIPOnChainStateUsingDataStore(input.ExistingDataStore, input.ChainSelector) if loadErr != nil { return sequences.OnChainOutput{}, fmt.Errorf("failed to load TON CCIP state for chain %d: %w", input.ChainSelector, loadErr) @@ -529,14 +528,6 @@ func (a *TonTokenAdapter) ConfigureTokenForTransfersSequence() *cldf_ops.Sequenc registryAddr = &r } - var offRampAddr *address.Address - if !stateCCIP.OffRamp.IsAddrNone() { - o := stateCCIP.OffRamp - offRampAddr = &o - } else if len(input.RemoteChains) > 0 { - return sequences.OnChainOutput{}, fmt.Errorf("no OffRamp address found in the datastore for chain %d: the token pool would reject inbound ReleaseOrMint with TokenPool_Error.Unauthorized", input.ChainSelector) - } - body := codec.MustWrapMessage[any](bindings.TypeTokenAdminRegistry, tokenadminregistry.RegisterToken{ TokenAddress: tokenAddr, TokenInfo: tokenadminregistryentry.TokenInfo{ @@ -593,14 +584,6 @@ func (a *TonTokenAdapter) ConfigureTokenForTransfersSequence() *cldf_ops.Sequenc return sequences.OnChainOutput{}, fmt.Errorf("failed to configure remote chains on token pool at %s: %w", poolAddr.String(), err) } - // Register the Router as the pool's trusted onRamp and the OffRamp as its trusted - // offRamp for every remote chain being wired up. - // TODO This should be changed in the contracts flow so that the onramp is the one calling instead of the Router - routerAddr := stateCCIP.Router - if err := applyRampAccessUpdates(b, dp, poolAddr, &routerAddr, offRampAddr, input.RemoteChains); err != nil { - return sequences.OnChainOutput{}, fmt.Errorf("failed to configure ramp access on token pool at %s: %w", poolAddr.String(), err) - } - return sequences.OnChainOutput{}, nil }, ) @@ -706,55 +689,6 @@ func applyRemoteChainUpdates( return err } -// applyRampAccessUpdates registers onRamp/offRamp as the trusted local ramps for every -// remote chain in remoteChains, via TokenPool_UpdateRampAccess. It is a no-op when no -// remote chains are provided. Without this, the pool's mirroredPolicy.onRamps/offRamps -// maps stay empty and TokenPool.ensureOutboundAccess/ensureInboundAccess (entrypoint.tolk) -// reject LockOrBurn/ReleaseOrMint with TokenPool_Error.Unauthorized. -func applyRampAccessUpdates( - b cldf_ops.Bundle, - dp *dep.DependencyProvider, - poolAddr *address.Address, - onRamp *address.Address, - offRamp *address.Address, - remoteChains map[uint64]tokensapi.RemoteChainConfig[[]byte, string], -) error { - if len(remoteChains) == 0 { - return nil - } - - updates := make(common.SnakedCell[tokenpool.RampUpdate], 0, len(remoteChains)) - for remoteSelector := range remoteChains { - updates = append(updates, tokenpool.RampUpdate{ - RemoteChainSelector: remoteSelector, - OnRamp: onRamp, - OffRamp: offRamp, - }) - } - - queryID, err := ton_tvm.RandomQueryID() - if err != nil { - return fmt.Errorf("failed to generate query id for ramp access update: %w", err) - } - - body := codec.MustWrapMessage[any](bindings.TypeLockReleaseTokenPool, tokenpool.UpdateRampAccess{ - QueryID: queryID, - Updates: updates, - }) - - _, err = cldf_ops.ExecuteOperation(b, opston.SendMessages, dp, opston.SendMessagesInput{ - Messages: []opston.InternalMessage[any]{ - { - Bounce: true, - DstAddr: poolAddr, - Amount: tlb.MustFromTON("0.1"), - Body: body, - }, - }, - }) - return err -} - // disabledRateLimitConfigPair returns a fully-disabled rate limiter pair. func disabledRateLimitConfigPair() tokenpool.RateLimitConfigPair { disabled := tokenpool.RateLimitConfig{ diff --git a/docs/contracts/overview/ccip/token-pools/IMPLEMENTATION.md b/docs/contracts/overview/ccip/token-pools/IMPLEMENTATION.md index 45de0d1f2..3921680c9 100644 --- a/docs/contracts/overview/ccip/token-pools/IMPLEMENTATION.md +++ b/docs/contracts/overview/ccip/token-pools/IMPLEMENTATION.md @@ -48,11 +48,15 @@ contract Storage ──load──▶ TokenPool{ data, context: Storage ### 3.1 Deliberate divergences from EVM (correct for TVM) -1. **Mirrored policy, not synchronous calls.** EVM calls `Router`/`RMN` inline. - TON cannot return synchronously, so the pool keeps **local mirrors** of - onRamp/offRamp authorization and RMN cursed-subjects, pushed asynchronously by - trusted senders (analogous to `OffRamp_UpdateCursedSubjects`). Read on the hot - path; never queried live. (`TokenPool_MirroredPolicy` in `types.tolk`.) +1. **Router chokepoint, local RMN policy.** EVM calls `Router`/`RMN` inline; on TON + the `Router` is the pool's **sole** entrypoint (`TokenPool.onlyRouter`) for both + directions — outbound `LockOrBurn` and inbound `ReleaseOrMint` (the latter relayed + by the Router via `RelayReleaseOrMint`, which also routes pool rejections to the + OffRamp's failure rail). This keeps pool decommission O(1): revoking the Router's + deployable code disables every pool without touching the OffRamp's allowed list. + The pool keeps only a **local** mirror of RMN cursed-subjects, pushed asynchronously + by the RMN proxy (`TokenPool_LocalPolicy` in `types.tolk`). Read on the hot path; + never queried live. 2. **Per-operation async state machines.** Each cross-chain op is keyed by `queryId` in a pending map; the pool replies only after positive confirmation (`ReturnExcessesBack` / lockbox callbacks). "Confirmation-before-reply." diff --git a/pkg/ccip/bindings/tokenpool/burnmint/reader.go b/pkg/ccip/bindings/tokenpool/burnmint/reader.go index 07b1790c9..822977b5a 100644 --- a/pkg/ccip/bindings/tokenpool/burnmint/reader.go +++ b/pkg/ccip/bindings/tokenpool/burnmint/reader.go @@ -20,8 +20,6 @@ var ( GetTokenDecimals = tokenpool.GetTokenDecimals GetIsSupportedChain = tokenpool.GetIsSupportedChain GetSupportedChains = tokenpool.GetSupportedChains - GetOnRamp = tokenpool.GetOnRamp - GetOffRamp = tokenpool.GetOffRamp GetRMNProxy = tokenpool.GetRMNProxy GetVerifyNotCursed = tokenpool.GetVerifyNotCursed GetDynamicConfig = tokenpool.GetDynamicConfig @@ -34,7 +32,6 @@ var ( GetCurrentRateLimiterState = tokenpool.GetCurrentRateLimiterState GetCursedSubjects = tokenpool.GetCursedSubjects GetAdminConfig = tokenpool.GetAdminConfig - GetMirroredPolicy = tokenpool.GetMirroredPolicy GetRemoteChainConfig = tokenpool.GetRemoteChainConfig GetFee = tokenpool.GetFee GetCCVAmount = tokenpool.GetCCVAmount diff --git a/pkg/ccip/bindings/tokenpool/lockrelease/reader.go b/pkg/ccip/bindings/tokenpool/lockrelease/reader.go index 5485cb797..dd8bd3161 100644 --- a/pkg/ccip/bindings/tokenpool/lockrelease/reader.go +++ b/pkg/ccip/bindings/tokenpool/lockrelease/reader.go @@ -57,8 +57,6 @@ var ( GetTokenDecimals = tokenpool.GetTokenDecimals GetIsSupportedChain = tokenpool.GetIsSupportedChain GetSupportedChains = tokenpool.GetSupportedChains - GetOnRamp = tokenpool.GetOnRamp - GetOffRamp = tokenpool.GetOffRamp GetRMNProxy = tokenpool.GetRMNProxy GetVerifyNotCursed = tokenpool.GetVerifyNotCursed GetDynamicConfig = tokenpool.GetDynamicConfig @@ -71,7 +69,6 @@ var ( GetCurrentRateLimiterState = tokenpool.GetCurrentRateLimiterState GetCursedSubjects = tokenpool.GetCursedSubjects GetAdminConfig = tokenpool.GetAdminConfig - GetMirroredPolicy = tokenpool.GetMirroredPolicy GetRemoteChainConfig = tokenpool.GetRemoteChainConfig GetFee = tokenpool.GetFee GetCCVAmount = tokenpool.GetCCVAmount diff --git a/pkg/ccip/bindings/tokenpool/lockreleaselockbox/reader.go b/pkg/ccip/bindings/tokenpool/lockreleaselockbox/reader.go index 35503caeb..e7d718676 100644 --- a/pkg/ccip/bindings/tokenpool/lockreleaselockbox/reader.go +++ b/pkg/ccip/bindings/tokenpool/lockreleaselockbox/reader.go @@ -47,8 +47,6 @@ var ( GetTokenDecimals = tokenpool.GetTokenDecimals GetIsSupportedChain = tokenpool.GetIsSupportedChain GetSupportedChains = tokenpool.GetSupportedChains - GetOnRamp = tokenpool.GetOnRamp - GetOffRamp = tokenpool.GetOffRamp GetRMNProxy = tokenpool.GetRMNProxy GetVerifyNotCursed = tokenpool.GetVerifyNotCursed GetDynamicConfig = tokenpool.GetDynamicConfig @@ -61,7 +59,6 @@ var ( GetCurrentRateLimiterState = tokenpool.GetCurrentRateLimiterState GetCursedSubjects = tokenpool.GetCursedSubjects GetAdminConfig = tokenpool.GetAdminConfig - GetMirroredPolicy = tokenpool.GetMirroredPolicy GetRemoteChainConfig = tokenpool.GetRemoteChainConfig GetFee = tokenpool.GetFee GetCCVAmount = tokenpool.GetCCVAmount diff --git a/pkg/ccip/bindings/tokenpool/reader.go b/pkg/ccip/bindings/tokenpool/reader.go index ce6b466f9..7f062ccb8 100644 --- a/pkg/ccip/bindings/tokenpool/reader.go +++ b/pkg/ccip/bindings/tokenpool/reader.go @@ -14,7 +14,6 @@ import ( "github.com/smartcontractkit/chainlink-ton/cciplib/ccip/bindings/common" "github.com/smartcontractkit/chainlink-ton/cciplib/ccip/bindings/ownable2step" "github.com/smartcontractkit/chainlink-ton/cciplib/ton/parser" - "github.com/smartcontractkit/chainlink-ton/cciplib/ton/tlbe" "github.com/smartcontractkit/chainlink-ton/cciplib/ton/tvm" ) @@ -88,54 +87,19 @@ var GetSupportedChains = tvm.NewNoArgsGetter(tvm.NoArgsOpts[[]uint64]{ }), }) -// GetOnRamp gets the onRamp address for a given remote chain selector. +// GetRMNProxy gets the RMN proxy address, or nil when proxy updates are disabled. // -// On-chain: get fun onRamp(remoteChainSelector: uint64): address? -var GetOnRamp = tvm.Getter[uint64, *address.Address]{ - Name: "onRamp", - Decoder: tvm.NewResultDecoder(func(r *ton.ExecutionResult) (*address.Address, error) { - isNil, err := r.IsNil(0) - if err != nil { - return nil, fmt.Errorf("error checking IsNil(0) - onRamp: %w", err) - } - if isNil { - return nil, nil - } - addrSlice, err := r.Slice(0) - if err != nil { - return nil, fmt.Errorf("error getting Slice(0) - onRamp: %w", err) - } - return addrSlice.LoadAddr() - }), -} - -// GetOffRamp gets the offRamp address for a given remote chain selector. -// -// On-chain: get fun offRamp(remoteChainSelector: uint64): address? -var GetOffRamp = tvm.Getter[uint64, *address.Address]{ - Name: "offRamp", +// On-chain: get fun getRMNProxy(): address? +var GetRMNProxy = tvm.NewNoArgsGetter(tvm.NoArgsOpts[*address.Address]{ + Name: "getRMNProxy", Decoder: tvm.NewResultDecoder(func(r *ton.ExecutionResult) (*address.Address, error) { isNil, err := r.IsNil(0) if err != nil { - return nil, fmt.Errorf("error checking IsNil(0) - offRamp: %w", err) + return nil, fmt.Errorf("error checking IsNil(0) - getRMNProxy: %w", err) } if isNil { return nil, nil } - addrSlice, err := r.Slice(0) - if err != nil { - return nil, fmt.Errorf("error getting Slice(0) - offRamp: %w", err) - } - return addrSlice.LoadAddr() - }), -} - -// GetRMNProxy gets the RMN proxy address. -// -// On-chain: get fun getRMNProxy(): address -var GetRMNProxy = tvm.NewNoArgsGetter(tvm.NoArgsOpts[*address.Address]{ - Name: "getRMNProxy", - Decoder: tvm.NewResultDecoder(func(r *ton.ExecutionResult) (*address.Address, error) { addrSlice, err := r.Slice(0) if err != nil { return nil, fmt.Errorf("error getting Slice(0) - getRMNProxy: %w", err) @@ -212,20 +176,20 @@ var GetDynamicConfig = tvm.NewNoArgsGetter(tvm.NoArgsOpts[DynamicConfig]{ cfg.FeeAdmin = addr } - // Decode the allowedDepositNamespaces dictionary (map). + // Decode the allowedDepositNamespaces dictionary (map - a unit + // value set; presence of a key means the namespace is allowed). dictCell, err := r.Cell(3) //nolint:mnd // index 3 for the 4th return value (allowedDepositNamespaces) if err != nil { return cfg, fmt.Errorf("error getting Cell(3) - allowedDepositNamespaces: %w", err) } if dictCell == nil { - cfg.AllowedDepositNamespaces = tlbe.NewEmptyDict[uint32, bool]() + cfg.AllowedDepositNamespaces = cell.NewDict(32) } else { dict := dictCell.AsDict(32) // uint32 keys - depositNamespaces, err := tlbe.NewDictFromDictionary[uint32, bool](dict) - if err != nil { - return cfg, fmt.Errorf("error decoding allowedDepositNamespaces dict: %w", err) + if dict == nil { + dict = cell.NewDict(32) } - cfg.AllowedDepositNamespaces = depositNamespaces + cfg.AllowedDepositNamespaces = dict } return cfg, nil @@ -440,26 +404,6 @@ var GetAdminConfig = tvm.NewNoArgsGetter(tvm.NoArgsOpts[AdminConfig]{ }), }) -// GetMirroredPolicy gets the mirrored policy (onRamps, offRamps, cursedSubjects). -// -// On-chain: fun TokenPool.getMirroredPolicy(self): TokenPool_MirroredPolicy -var GetMirroredPolicy = tvm.NewNoArgsGetter(tvm.NoArgsOpts[MirroredPolicy]{ - Name: "getMirroredPolicy", - Decoder: tvm.NewResultDecoder(func(r *ton.ExecutionResult) (MirroredPolicy, error) { - c, err := r.Cell(0) - if err != nil { - return MirroredPolicy{}, fmt.Errorf("error getting Cell(0) - mirroredPolicy: %w", err) - } - - var mp MirroredPolicy - if err := tlb.LoadFromCell(&mp, c.BeginParse()); err != nil { - return MirroredPolicy{}, fmt.Errorf("error decoding MirroredPolicy: %w", err) - } - - return mp, nil - }), -}) - // GetRemoteChainConfig gets the remote chain config for a given chain selector. // // On-chain: fun TokenPool.getRemoteChainConfig(self, remoteChainSelector: uint64): TokenPool_RemoteChainConfig? diff --git a/pkg/ccip/bindings/tokenpool/types.go b/pkg/ccip/bindings/tokenpool/types.go index 3046950c0..6b57f64a3 100644 --- a/pkg/ccip/bindings/tokenpool/types.go +++ b/pkg/ccip/bindings/tokenpool/types.go @@ -47,23 +47,28 @@ const ( // --- Data types (no opcodes) --- // DynamicConfig holds the router and admin addresses for the pool. +// +// AllowedDepositNamespaces is a unit-value set (map on-chain), so it +// is modelled as a raw *cell.Dictionary like CursedSubjects below. type DynamicConfig struct { - Router *address.Address `tlb:"addr"` - RateLimitAdmin *address.Address `tlb:"addr"` - FeeAdmin *address.Address `tlb:"addr"` - AllowedDepositNamespaces *tlbe.Dict[uint32, bool] `tlb:"."` + Router *address.Address `tlb:"addr"` + RateLimitAdmin *address.Address `tlb:"addr"` + FeeAdmin *address.Address `tlb:"addr"` + AllowedDepositNamespaces *cell.Dictionary `tlb:"dict 32"` } -// MirroredPolicy holds on/off ramp addresses and cursed subjects. +// LocalPolicy holds the pool's independently managed RMN policy. It is +// intentionally not a mirror of the Router's cursed subjects: the pool owner may +// configure a distinct RMN proxy, or disable proxy updates by setting it to +// addr_none. Ramp access is no longer pool state: the Router is the only entry +// point of every pool (TokenPool.onlyRouter). // // Dict fields use *cell.Dictionary rather than *tlbe.Dict: tonutils-go's tlb // encoder (used to build init data for contract deploys, see // deployment/utils/operation/deploy_ton_contract.go) type-asserts "dict N" // fields directly to *cell.Dictionary and panics on any other type. -type MirroredPolicy struct { - OnRamps *cell.Dictionary `tlb:"dict 64"` - OffRamps *cell.Dictionary `tlb:"dict 64"` - CursedSubjects CursedSubjects `tlb:"."` +type LocalPolicy struct { + CursedSubjects CursedSubjects `tlb:"."` } // CursedSubjects represents the set of cursed subjects (uint128 keys with empty values). @@ -71,13 +76,6 @@ type CursedSubjects struct { Data *cell.Dictionary `tlb:"dict 128"` } -// RampUpdate represents a single ramp access update for a remote chain. -type RampUpdate struct { - RemoteChainSelector uint64 `tlb:"## 64"` - OnRamp *address.Address `tlb:"addr"` - OffRamp *address.Address `tlb:"addr"` -} - // RateLimitConfig represents a rate limiter configuration. type RateLimitConfig struct { IsEnabled bool `tlb:"bool"` @@ -260,11 +258,11 @@ type AdminConfig struct { } // Storage represents the TokenPool_Data storage layout shared by every TokenPool -// implementation (Mock, BurnMint, LockRelease, ...), each of which wraps it as +// implementation (BurnMint, LockRelease, ...), each of which wraps it as // `poolData: Cell` alongside its own pool-specific fields. type Storage struct { AdminConfig AdminConfig `tlb:"^"` - MirroredPolicy MirroredPolicy `tlb:"^"` + LocalPolicy LocalPolicy `tlb:"^"` TokenDecimals uint8 `tlb:"## 8"` RemoteChainConfigs *cell.Dictionary `tlb:"dict 64"` TokenTransferFeeConfigs *cell.Dictionary `tlb:"dict 64"` @@ -321,16 +319,16 @@ type SetAdvancedPoolHooks struct { // SetDeployableCode sets the Compiled Deployable code used to derive source-chain deposit accounts. type SetDeployableCode struct { - _ tlb.Magic `tlb:"#6c2a91e4" json:"-"` //nolint:revive // (opcode) should stay uninitialized + _ tlb.Magic `tlb:"#3868e309" json:"-"` //nolint:revive // (opcode) should stay uninitialized QueryID uint64 `tlb:"## 64"` DeployableCode *cell.Cell `tlb:"maybe ^"` } // SetAllowedDepositNamespaces sets the Deployables namespaces the pool accepts as deposit sources. type SetAllowedDepositNamespaces struct { - _ tlb.Magic `tlb:"#1f8e33c2" json:"-"` //nolint:revive // (opcode) should stay uninitialized - QueryID uint64 `tlb:"## 64"` - AllowedDepositNamespaces *tlbe.Dict[uint32, bool] `tlb:"."` + _ tlb.Magic `tlb:"#84384142" json:"-"` //nolint:revive // (opcode) should stay uninitialized + QueryID uint64 `tlb:"## 64"` + AllowedDepositNamespaces *cell.Dictionary `tlb:"dict 32"` } // SetRateLimitConfig sets the rate limit configurations. @@ -348,13 +346,6 @@ type ApplyTokenTransferFeeConfigUpdates struct { DisableChainSelectors common.SnakedCell[ChainSelector] `tlb:"^"` } -// UpdateRampAccess updates ramp access for chains. -type UpdateRampAccess struct { - _ tlb.Magic `tlb:"#e30764be" json:"-"` //nolint:revive // (opcode) should stay uninitialized - QueryID uint64 `tlb:"## 64"` - Updates common.SnakedCell[RampUpdate] `tlb:"^"` -} - // SetRMNProxy sets the RMN proxy address. type SetRMNProxy struct { _ tlb.Magic `tlb:"#9929b642" json:"-"` //nolint:revive // (opcode) should stay uninitialized @@ -624,12 +615,6 @@ type ChainUpdatesApplied struct { QueryID uint64 `tlb:"## 64"` } -// RampAccessUpdatesApplied is replied on UpdateRampAccess to confirm the tx and return excess. -type RampAccessUpdatesApplied struct { - _ tlb.Magic `tlb:"#d7f5c563" json:"-"` //nolint:revive // (opcode) should stay uninitialized - QueryID uint64 `tlb:"## 64"` -} - // FeeConfigApplied is replied on ApplyTokenTransferFeeConfigUpdates to confirm the tx // and return excess. type FeeConfigApplied struct { @@ -660,14 +645,14 @@ type AdvancedPoolHooksSet struct { // DeployableCodeSet confirms the deployable code was set. type DeployableCodeSet struct { - _ tlb.Magic `tlb:"#09d4a7b1" json:"-"` //nolint:revive // (opcode) should stay uninitialized + _ tlb.Magic `tlb:"#89d602e5" json:"-"` //nolint:revive // (opcode) should stay uninitialized QueryID uint64 `tlb:"## 64"` DeployableCode *cell.Cell `tlb:"maybe ^"` } // AllowedDepositNamespacesSet confirms the allowed deposit namespaces were set. type AllowedDepositNamespacesSet struct { - _ tlb.Magic `tlb:"#7a53c9f4" json:"-"` //nolint:revive // (opcode) should stay uninitialized + _ tlb.Magic `tlb:"#c1ffe3a6" json:"-"` //nolint:revive // (opcode) should stay uninitialized QueryID uint64 `tlb:"## 64"` } @@ -728,13 +713,6 @@ type RateLimitConfigured struct { Args RateLimitConfigArgs `tlb:"."` } -// RampAccessUpdated is emitted when ramp access is updated. -type RampAccessUpdated struct { - RemoteChainSelector uint64 `tlb:"## 64"` - OnRamp *address.Address `tlb:"addr"` - OffRamp *address.Address `tlb:"addr"` -} - // OutboundRateLimitConsumed is emitted when outbound rate-limit capacity is consumed. type OutboundRateLimitConsumed struct { RemoteChainSelector uint64 `tlb:"## 64"` @@ -820,7 +798,6 @@ var TLBs = tvm.MustNewTLBMap([]any{ SetAllowedDepositNamespaces{}, SetRateLimitConfig{}, ApplyTokenTransferFeeConfigUpdates{}, - UpdateRampAccess{}, SetRMNProxy{}, SetCursedSubjects{}, JettonWithdrawableWithdraw{}, @@ -854,7 +831,6 @@ var TLBs = tvm.MustNewTLBMap([]any{ DeployableCodeSet{}, AllowedDepositNamespacesSet{}, ChainUpdatesApplied{}, - RampAccessUpdatesApplied{}, FeeConfigApplied{}, // AdvancedPoolHooks outgoing (sent from TokenPool to hooks contract) // GetCCVs (registered above) is reused for the pool→hooks hop. @@ -871,7 +847,6 @@ const ( TopicRemotePoolAdded = "TokenPool_RemotePoolAdded" TopicRemotePoolRemoved = "TokenPool_RemotePoolRemoved" TopicDynamicConfigSet = "TokenPool_DynamicConfigSet" - TopicRampAccessUpdated = "TokenPool_RampAccessUpdated" TopicFinalityConfigSet = "TokenPool_FinalityConfigSet" TopicRateLimitConfigured = "TokenPool_RateLimitConfigured" TopicOutboundRateLimitConsumed = "TokenPool_OutboundRateLimitConsumed" From 5e4464190e8a5989e5f53d5860d61ba66eed7d16 Mon Sep 17 00:00:00 2001 From: Kristijan Date: Tue, 15 Sep 2026 10:36:21 +0200 Subject: [PATCH 10/23] Remove resurrected MockTokenPool fixture The MockTokenPool test contract and its generated wrapper were deleted on main in "[NONEVM-5813] Delete mock Token Pool contract (#840)" but came back through the rebase onto feat/tp-only-router. Nothing references them (no test, script, or manifest entry), and the contract merely re-exported the real pool lib. Drop the Tolk contract and the generated wrapper again so the branch does not reintroduce a fixture main intentionally removed. --- .../ccip/test/tokenPool/contract.tolk | 60 - contracts/wrappers/gen/ccip/MockTokenPool.ts | 5196 ----------------- 2 files changed, 5256 deletions(-) delete mode 100644 contracts/contracts/ccip/test/tokenPool/contract.tolk delete mode 100644 contracts/wrappers/gen/ccip/MockTokenPool.ts diff --git a/contracts/contracts/ccip/test/tokenPool/contract.tolk b/contracts/contracts/ccip/test/tokenPool/contract.tolk deleted file mode 100644 index e8023baca..000000000 --- a/contracts/contracts/ccip/test/tokenPool/contract.tolk +++ /dev/null @@ -1,60 +0,0 @@ -import "../../pools/lib/token_pool/entrypoint" -import "../../pools/lib/token_pool/messages" - - -contract MockTokenPool { - author: "SmartContract Chainlink Limited SEZC" - version: "1.6.1" - description: "link.chain.ton.ccip.test.TokenPool" - storage: Storage - incomingMessages: TokenPool_InMessage -} - -const CONTRACT_VERSION = "0.0.1".literalSlice(); - -struct Storage { - poolData: Cell -} - -fun Storage.load(): Storage { - return Storage.fromCell(contract.getData()); -} - -fun Storage.store(self) { - contract.setData(self.toCell()); -} - -fun loadPool(st: Storage): TokenPool { - return TokenPool { - data: st.poolData.load(), - context: st, - hooks: TokenPool_Hooks { - ensureNotCursed: null, - onLockOrBurn: null, - validateLockOrBurn: null, - preflightCheck: null, - onLockOrBurnTransfer: null, - onLockOrBurnTransferContinue: null, - onReleaseOrMint: null, - validateReleaseOrMint: null, - postflightCheck: null, - onReleaseOrMintContinue: null, - onWithdrawFeeTokens: null, - }, - }; -} - -fun onInternalMessage(in: InMessage) { - var st = Storage.load(); - var pool = loadPool(st); - val handled = pool.onInternalMessage(in.senderAddress, in.valueCoins, in.body); - if (handled) { - st = pool.context != null ? pool.context! : st; - st.poolData = pool.data.toCell(); - st.store(); - return; - } - - assert(in.body.isEmpty()) throw 0xFFFF; -} - diff --git a/contracts/wrappers/gen/ccip/MockTokenPool.ts b/contracts/wrappers/gen/ccip/MockTokenPool.ts deleted file mode 100644 index 4dfcba9a8..000000000 --- a/contracts/wrappers/gen/ccip/MockTokenPool.ts +++ /dev/null @@ -1,5196 +0,0 @@ -// AUTO-GENERATED, do not edit -// It's a TypeScript wrapper for a MockTokenPool contract in Tolk. -/* eslint-disable */ - -import * as c from '@ton/core'; -import { beginCell, ContractProvider, Sender, SendMode } from '@ton/core'; - -// ———————————————————————————————————————————— -// predefined types and functions -// - -type RemainingBitsAndRefs = c.Slice - -type array = T[] - -type StoreCallback = (obj: T, b: c.Builder) => void -type LoadCallback = (s: c.Slice) => T - - -function makeCellFrom(self: T, storeFn_T: StoreCallback): c.Cell { - let b = beginCell(); - storeFn_T(self, b); - return b.endCell(); -} - -function loadAndCheckPrefix32(s: c.Slice, expected: number, structName: string): void { - let prefix = s.loadUint(32); - if (prefix !== expected) { - throw new Error(`Incorrect prefix for '${structName}': expected 0x${expected.toString(16).padStart(8, '0')}, got 0x${prefix.toString(16).padStart(8, '0')}`); - } -} - -function lookupPrefix(s: c.Slice, expected: number, prefixLen: number): boolean { - return s.remainingBits >= prefixLen && s.preloadUint(prefixLen) === expected; -} - -function throwNonePrefixMatch(fieldPath: string): never { - throw new Error(`Incorrect prefix for '${fieldPath}': none of variants matched`); -} - -function storeCellRef(value: T, b: c.Builder, storeFn_T: StoreCallback): void { - let b_ref = c.beginCell(); - storeFn_T(value, b_ref); - b.storeRef(b_ref.endCell()); -} - -function loadCellRef(s: c.Slice, loadFn_T: LoadCallback): T { - let s_ref = s.loadRef().beginParse(); - return loadFn_T(s_ref); -} - -function dictToMap(d: c.Dictionary): Map { - const map = new Map(); - for (const [k, v] of d) { - map.set(k, v); - } - return map; -} - -function mapToDict(m: Map, keySerializer: c.DictionaryKey, valueSerializer: c.DictionaryValue): c.Dictionary { - const d = c.Dictionary.empty(keySerializer, valueSerializer); - for (const [k, v] of m) { - d.set(k, v); - } - return d; -} - - -function dictToSet(d: c.Dictionary): Set { - const set = new Set(); - for (const k of d.keys()) { - set.add(k); - } - return set; -} - -function setToDict(s: Set, keySerializer: c.DictionaryKey, valueSerializer: c.DictionaryValue<[]>): c.Dictionary { - const d = c.Dictionary.empty(keySerializer, valueSerializer); - for (const k of s) { - d.set(k, []); - } - return d; -} - - -function storeTolkRemaining(v: RemainingBitsAndRefs, b: c.Builder): void { - b.storeSlice(v); -} - -function loadTolkRemaining(s: c.Slice): RemainingBitsAndRefs { - let rest = s.clone(); - s.loadBits(s.remainingBits); - while (s.remainingRefs) { - s.loadRef(); - } - return rest; -} - -function storeTolkNullable(v: T | null, b: c.Builder, storeFn_T: StoreCallback): void { - if (v === null) { - b.storeUint(0, 1); - } else { - b.storeUint(1, 1); - storeFn_T(v, b); - } -} - -function storeArrayOf(v: array, b: c.Builder, storeFn_T: StoreCallback): void { - // the compiler stores array in chunks; in TypeScript, for simplicity, store "1 elem = 1 ref" - let tail = null as c.Cell | null; - for (let i = 0; i < v.length; ++i) { - let chunkB = beginCell().storeMaybeRef(tail); - storeFn_T(v[v.length - 1 - i], chunkB); - tail = chunkB.endCell(); - } - b.storeUint(v.length, 8); - b.storeMaybeRef(tail); -} - -function loadArrayOf(s: c.Slice, loadFn_T: LoadCallback): array { - let len = s.loadUint(8); - let head = s.loadMaybeRef(); - let outArr = [] as array; - while (head != null) { - let s = head.beginParse(); - head = s.loadMaybeRef(); - while (s.remainingBits || s.remainingRefs) { - outArr.push(loadFn_T(s)); - } - } - if (len !== outArr.length) { - throw new Error(`mismatch array binary data: expected ${len} elements, got ${outArr.length}`); - } - return outArr; -} - -function createDictionaryValue(loadFn_V: LoadCallback, storeFn_V: StoreCallback): c.DictionaryValue { - return { - serialize(self: V, b: c.Builder) { - storeFn_V(self, b); - }, - parse(s: c.Slice): V { - const value = loadFn_V(s); - s.endParse(); - return value; - } - } -} - -// ———————————————————————————————————————————— -// parse get methods result from a TVM stack -// - -class StackReader { - constructor(private tuple: c.TupleItem[]) { - } - - static fromGetMethod(expectedN: number, getMethodResult: { stack: c.TupleReader }): StackReader { - let tuple = [] as c.TupleItem[]; - while (getMethodResult.stack.remaining) { - tuple.push(getMethodResult.stack.pop()); - } - if (tuple.length !== expectedN) { - throw new Error(`expected ${expectedN} stack width, got ${tuple.length}`); - } - return new StackReader(tuple); - } - - private popExpecting(itemType: string): ItemT { - const item = this.tuple.shift(); - if (item?.type === itemType) { - return item as ItemT; - } - throw new Error(`not '${itemType}' on a stack`); - } - - private popCellLike(): c.Cell { - const item = this.tuple.shift(); - if (item && (item.type === 'cell' || item.type === 'slice' || item.type === 'builder')) { - return item.cell; - } - throw new Error(`not cell/slice on a stack`); - } - - readBigInt(): bigint { - return this.popExpecting('int').value; - } - - readBoolean(): boolean { - return this.popExpecting('int').value !== 0n; - } - - readCell(): c.Cell { - return this.popCellLike(); - } - - readSlice(): c.Slice { - return this.popCellLike().beginParse(); - } -} - -// ———————————————————————————————————————————— -// custom packToBuilder and unpackFromSlice -// - -type CustomPackToBuilderFn = (self: T, b: c.Builder) => void -type CustomUnpackFromSliceFn = (s: c.Slice) => T - -let customSerializersRegistry: Map | null, CustomUnpackFromSliceFn | null]> = new Map; - -function ensureCustomSerializerRegistered(typeName: string) { - if (!customSerializersRegistry.has(typeName)) { - throw new Error(`Custom packToBuilder/unpackFromSlice was not registered for type 'MockTokenPool.${typeName}'.\n(in Tolk code, they have custom logic \`fun ${typeName}__packToBuilder\`)\nSteps to fix:\n1) in your code, create and implement\n > function ${typeName}__packToBuilder(self: ${typeName}, b: Builder): void { ... }\n > function ${typeName}__unpackFromSlice(s: Slice): ${typeName} { ... }\n2) register them in advance by calling\n > MockTokenPool.registerCustomPackUnpack('${typeName}', ${typeName}__packToBuilder, ${typeName}__unpackFromSlice);`); - } -} - -function invokeCustomPackToBuilder(typeName: string, self: T, b: c.Builder) { - ensureCustomSerializerRegistered(typeName); - customSerializersRegistry.get(typeName)![0]!(self, b); -} - -function invokeCustomUnpackFromSlice(typeName: string, s: c.Slice): T { - ensureCustomSerializerRegistered(typeName); - return customSerializersRegistry.get(typeName)![1]!(s); -} - -// ———————————————————————————————————————————— -// auto-generated serializers to/from cells -// - -type coins = bigint - -type uint8 = bigint -type uint16 = bigint -type uint32 = bigint -type uint64 = bigint -type uint120 = bigint -type uint128 = bigint -type uint256 = bigint - -/** - > struct Storage { - > poolData: Cell - > } - */ -export interface Storage { - readonly $: 'Storage' - poolData: TokenPool_Data -} - -export const Storage = { - create(args: { - poolData: TokenPool_Data - }): Storage { - return { - $: 'Storage', - ...args - } - }, - fromSlice(s: c.Slice): Storage { - return { - $: 'Storage', - poolData: loadCellRef(s, TokenPool_Data.fromSlice), - } - }, - store(self: Storage, b: c.Builder): void { - storeCellRef(self.poolData, b, TokenPool_Data.store); - }, - toCell(self: Storage): c.Cell { - return makeCellFrom(self, Storage.store); - } -} - -/** - > struct TokenPool_AdminConfig { - > ownable: Cell - > rmnProxy: address? - > dynamicConfig: Cell - > jettonClient: JettonClient - > allowedFinalityConfig: uint32 - > advancedPoolHooks: address? - > deployableCode: cell? - > } - */ -export interface TokenPool_AdminConfig { - readonly $: 'TokenPool_AdminConfig' - ownable: Ownable2Step - rmnProxy: c.Address | null - dynamicConfig: TokenPool_DynamicConfig - jettonClient: JettonClient - allowedFinalityConfig: uint32 /* = 0 as uint32 */ - advancedPoolHooks: c.Address | null /* = null */ - deployableCode: c.Cell | null /* = null */ -} - -export const TokenPool_AdminConfig = { - create(args: { - ownable: Ownable2Step - rmnProxy: c.Address | null - dynamicConfig: TokenPool_DynamicConfig - jettonClient: JettonClient - allowedFinalityConfig?: uint32 /* = 0 as uint32 */ - advancedPoolHooks?: c.Address | null /* = null */ - deployableCode?: c.Cell | null /* = null */ - }): TokenPool_AdminConfig { - return { - $: 'TokenPool_AdminConfig', - allowedFinalityConfig: 0n, - advancedPoolHooks: null, - deployableCode: null, - ...args - } - }, - fromSlice(s: c.Slice): TokenPool_AdminConfig { - return { - $: 'TokenPool_AdminConfig', - ownable: loadCellRef(s, Ownable2Step.fromSlice), - rmnProxy: s.loadMaybeAddress(), - dynamicConfig: loadCellRef(s, TokenPool_DynamicConfig.fromSlice), - jettonClient: JettonClient.fromSlice(s), - allowedFinalityConfig: s.loadUintBig(32), - advancedPoolHooks: s.loadMaybeAddress(), - deployableCode: s.loadBoolean() ? s.loadRef() : null, - } - }, - store(self: TokenPool_AdminConfig, b: c.Builder): void { - storeCellRef(self.ownable, b, Ownable2Step.store); - b.storeAddress(self.rmnProxy); - storeCellRef(self.dynamicConfig, b, TokenPool_DynamicConfig.store); - JettonClient.store(self.jettonClient, b); - b.storeUint(self.allowedFinalityConfig, 32); - b.storeAddress(self.advancedPoolHooks); - storeTolkNullable(self.deployableCode, b, - (v,b) => b.storeRef(v) - ); - }, - toCell(self: TokenPool_AdminConfig): c.Cell { - return makeCellFrom(self, TokenPool_AdminConfig.store); - } -} - -/** - > struct TokenPool_Data { - > adminConfig: Cell - > localPolicy: Cell - > tokenDecimals: uint8 - > remoteChainConfigs: map - > tokenTransferFeeConfigs: map - > } - */ -export interface TokenPool_Data { - readonly $: 'TokenPool_Data' - adminConfig: TokenPool_AdminConfig - localPolicy: TokenPool_LocalPolicy - tokenDecimals: uint8 - remoteChainConfigs: Map /* = [] as map */ - tokenTransferFeeConfigs: Map /* = [] as map */ -} - -export const TokenPool_Data = { - create(args: { - adminConfig: TokenPool_AdminConfig - localPolicy: TokenPool_LocalPolicy - tokenDecimals: uint8 - remoteChainConfigs: Map /* = [] as map */ - tokenTransferFeeConfigs: Map /* = [] as map */ - }): TokenPool_Data { - return { - $: 'TokenPool_Data', - ...args - } - }, - fromSlice(s: c.Slice): TokenPool_Data { - return { - $: 'TokenPool_Data', - adminConfig: loadCellRef(s, TokenPool_AdminConfig.fromSlice), - localPolicy: loadCellRef(s, TokenPool_LocalPolicy.fromSlice), - tokenDecimals: s.loadUintBig(8), - remoteChainConfigs: dictToMap(c.Dictionary.load(c.Dictionary.Keys.BigUint(64), createDictionaryValue(TokenPool_RemoteChainConfig.fromSlice, TokenPool_RemoteChainConfig.store), s)), - tokenTransferFeeConfigs: dictToMap(c.Dictionary.load(c.Dictionary.Keys.BigUint(64), createDictionaryValue(TokenPool_TokenTransferFeeConfig.fromSlice, TokenPool_TokenTransferFeeConfig.store), s)), - } - }, - store(self: TokenPool_Data, b: c.Builder): void { - storeCellRef(self.adminConfig, b, TokenPool_AdminConfig.store); - storeCellRef(self.localPolicy, b, TokenPool_LocalPolicy.store); - b.storeUint(self.tokenDecimals, 8); - b.storeDict(mapToDict(self.remoteChainConfigs, c.Dictionary.Keys.BigUint(64), createDictionaryValue(TokenPool_RemoteChainConfig.fromSlice, TokenPool_RemoteChainConfig.store)), c.Dictionary.Keys.BigUint(64), createDictionaryValue(TokenPool_RemoteChainConfig.fromSlice, TokenPool_RemoteChainConfig.store)); - b.storeDict(mapToDict(self.tokenTransferFeeConfigs, c.Dictionary.Keys.BigUint(64), createDictionaryValue(TokenPool_TokenTransferFeeConfig.fromSlice, TokenPool_TokenTransferFeeConfig.store)), c.Dictionary.Keys.BigUint(64), createDictionaryValue(TokenPool_TokenTransferFeeConfig.fromSlice, TokenPool_TokenTransferFeeConfig.store)); - }, - toCell(self: TokenPool_Data): c.Cell { - return makeCellFrom(self, TokenPool_Data.store); - } -} - -/** - > struct (0x56f73d37) TokenPool_ApplyChainUpdates { - > queryId: uint64 - > remoteChainSelectorsToRemove: SnakedCell - > chainsToAdd: SnakedCell - > } - */ -export interface TokenPool_ApplyChainUpdates { - readonly $: 'TokenPool_ApplyChainUpdates' - queryId: uint64 - remoteChainSelectorsToRemove: SnakedCell - chainsToAdd: SnakedCell -} - -export const TokenPool_ApplyChainUpdates = { - PREFIX: 0x56f73d37, - - create(args: { - queryId?: uint64 - remoteChainSelectorsToRemove: SnakedCell - chainsToAdd: SnakedCell - }): TokenPool_ApplyChainUpdates { - return { - $: 'TokenPool_ApplyChainUpdates', - ...args, - queryId: args.queryId ?? 0n - } - }, - fromSlice(s: c.Slice): TokenPool_ApplyChainUpdates { - loadAndCheckPrefix32(s, 0x56f73d37, 'TokenPool_ApplyChainUpdates'); - return { - $: 'TokenPool_ApplyChainUpdates', - queryId: s.loadUintBig(64), - remoteChainSelectorsToRemove: loadSnakedCellOf(s, (s) => s.loadUintBig(64)), - chainsToAdd: loadSnakedCellOf(s, TokenPool_ChainUpdate.fromSlice), - } - }, - store(self: TokenPool_ApplyChainUpdates, b: c.Builder): void { - b.storeUint(0x56f73d37, 32); - b.storeUint(self.queryId, 64); - storeSnakedCellOf(self.remoteChainSelectorsToRemove, b, (v, b) => b.storeUint(v, 64)); - storeSnakedCellOf(self.chainsToAdd, b, TokenPool_ChainUpdate.store); - }, - toCell(self: TokenPool_ApplyChainUpdates): c.Cell { - return makeCellFrom(self, TokenPool_ApplyChainUpdates.store); - } -} - -/** - > struct (0x17c242dc) TokenPool_AddRemotePool { - > queryId: uint64 - > remoteChainSelector: uint64 - > remotePoolAddress: Cell - > } - */ -export interface TokenPool_AddRemotePool { - readonly $: 'TokenPool_AddRemotePool' - queryId: uint64 - remoteChainSelector: uint64 - remotePoolAddress: CrossChainAddress -} - -export const TokenPool_AddRemotePool = { - PREFIX: 0x17c242dc, - - create(args: { - queryId?: uint64 - remoteChainSelector: uint64 - remotePoolAddress: CrossChainAddress - }): TokenPool_AddRemotePool { - return { - $: 'TokenPool_AddRemotePool', - ...args, - queryId: args.queryId ?? 0n - } - }, - fromSlice(s: c.Slice): TokenPool_AddRemotePool { - loadAndCheckPrefix32(s, 0x17c242dc, 'TokenPool_AddRemotePool'); - return { - $: 'TokenPool_AddRemotePool', - queryId: s.loadUintBig(64), - remoteChainSelector: s.loadUintBig(64), - remotePoolAddress: loadCellRef(s, CrossChainAddress.fromSlice), - } - }, - store(self: TokenPool_AddRemotePool, b: c.Builder): void { - b.storeUint(0x17c242dc, 32); - b.storeUint(self.queryId, 64); - b.storeUint(self.remoteChainSelector, 64); - storeCellRef(self.remotePoolAddress, b, CrossChainAddress.store); - }, - toCell(self: TokenPool_AddRemotePool): c.Cell { - return makeCellFrom(self, TokenPool_AddRemotePool.store); - } -} - -/** - > struct (0x426b8cc4) TokenPool_RemoveRemotePool { - > queryId: uint64 - > remoteChainSelector: uint64 - > remotePoolAddress: Cell - > } - */ -export interface TokenPool_RemoveRemotePool { - readonly $: 'TokenPool_RemoveRemotePool' - queryId: uint64 - remoteChainSelector: uint64 - remotePoolAddress: CrossChainAddress -} - -export const TokenPool_RemoveRemotePool = { - PREFIX: 0x426b8cc4, - - create(args: { - queryId?: uint64 - remoteChainSelector: uint64 - remotePoolAddress: CrossChainAddress - }): TokenPool_RemoveRemotePool { - return { - $: 'TokenPool_RemoveRemotePool', - ...args, - queryId: args.queryId ?? 0n - } - }, - fromSlice(s: c.Slice): TokenPool_RemoveRemotePool { - loadAndCheckPrefix32(s, 0x426b8cc4, 'TokenPool_RemoveRemotePool'); - return { - $: 'TokenPool_RemoveRemotePool', - queryId: s.loadUintBig(64), - remoteChainSelector: s.loadUintBig(64), - remotePoolAddress: loadCellRef(s, CrossChainAddress.fromSlice), - } - }, - store(self: TokenPool_RemoveRemotePool, b: c.Builder): void { - b.storeUint(0x426b8cc4, 32); - b.storeUint(self.queryId, 64); - b.storeUint(self.remoteChainSelector, 64); - storeCellRef(self.remotePoolAddress, b, CrossChainAddress.store); - }, - toCell(self: TokenPool_RemoveRemotePool): c.Cell { - return makeCellFrom(self, TokenPool_RemoveRemotePool.store); - } -} - -/** - > struct (0xd7712810) TokenPool_SetDynamicConfig { - > queryId: uint64 - > router: address - > rateLimitAdmin: address? - > feeAdmin: address? - > } - */ -export interface TokenPool_SetDynamicConfig { - readonly $: 'TokenPool_SetDynamicConfig' - queryId: uint64 - router: c.Address - rateLimitAdmin: c.Address | null /* = null */ - feeAdmin: c.Address | null /* = null */ -} - -export const TokenPool_SetDynamicConfig = { - PREFIX: 0xd7712810, - - create(args: { - queryId?: uint64 - router: c.Address - rateLimitAdmin?: c.Address | null /* = null */ - feeAdmin?: c.Address | null /* = null */ - }): TokenPool_SetDynamicConfig { - return { - $: 'TokenPool_SetDynamicConfig', - rateLimitAdmin: null, - feeAdmin: null, - ...args, - queryId: args.queryId ?? 0n - } - }, - fromSlice(s: c.Slice): TokenPool_SetDynamicConfig { - loadAndCheckPrefix32(s, 0xd7712810, 'TokenPool_SetDynamicConfig'); - return { - $: 'TokenPool_SetDynamicConfig', - queryId: s.loadUintBig(64), - router: s.loadAddress(), - rateLimitAdmin: s.loadMaybeAddress(), - feeAdmin: s.loadMaybeAddress(), - } - }, - store(self: TokenPool_SetDynamicConfig, b: c.Builder): void { - b.storeUint(0xd7712810, 32); - b.storeUint(self.queryId, 64); - b.storeAddress(self.router); - b.storeAddress(self.rateLimitAdmin); - b.storeAddress(self.feeAdmin); - }, - toCell(self: TokenPool_SetDynamicConfig): c.Cell { - return makeCellFrom(self, TokenPool_SetDynamicConfig.store); - } -} - -/** - > struct (0x3c50a39b) TokenPool_SetAllowedFinalityConfig { - > queryId: uint64 - > allowedFinalityConfig: uint32 - > } - */ -export interface TokenPool_SetAllowedFinalityConfig { - readonly $: 'TokenPool_SetAllowedFinalityConfig' - queryId: uint64 - allowedFinalityConfig: uint32 -} - -export const TokenPool_SetAllowedFinalityConfig = { - PREFIX: 0x3c50a39b, - - create(args: { - queryId?: uint64 - allowedFinalityConfig: uint32 - }): TokenPool_SetAllowedFinalityConfig { - return { - $: 'TokenPool_SetAllowedFinalityConfig', - ...args, - queryId: args.queryId ?? 0n - } - }, - fromSlice(s: c.Slice): TokenPool_SetAllowedFinalityConfig { - loadAndCheckPrefix32(s, 0x3c50a39b, 'TokenPool_SetAllowedFinalityConfig'); - return { - $: 'TokenPool_SetAllowedFinalityConfig', - queryId: s.loadUintBig(64), - allowedFinalityConfig: s.loadUintBig(32), - } - }, - store(self: TokenPool_SetAllowedFinalityConfig, b: c.Builder): void { - b.storeUint(0x3c50a39b, 32); - b.storeUint(self.queryId, 64); - b.storeUint(self.allowedFinalityConfig, 32); - }, - toCell(self: TokenPool_SetAllowedFinalityConfig): c.Cell { - return makeCellFrom(self, TokenPool_SetAllowedFinalityConfig.store); - } -} - -/** - > struct (0x3f5c9f57) TokenPool_SetAdvancedPoolHooks { - > queryId: uint64 - > advancedPoolHooks: address? - > } - */ -export interface TokenPool_SetAdvancedPoolHooks { - readonly $: 'TokenPool_SetAdvancedPoolHooks' - queryId: uint64 - advancedPoolHooks: c.Address | null -} - -export const TokenPool_SetAdvancedPoolHooks = { - PREFIX: 0x3f5c9f57, - - create(args: { - queryId?: uint64 - advancedPoolHooks: c.Address | null - }): TokenPool_SetAdvancedPoolHooks { - return { - $: 'TokenPool_SetAdvancedPoolHooks', - ...args, - queryId: args.queryId ?? 0n - } - }, - fromSlice(s: c.Slice): TokenPool_SetAdvancedPoolHooks { - loadAndCheckPrefix32(s, 0x3f5c9f57, 'TokenPool_SetAdvancedPoolHooks'); - return { - $: 'TokenPool_SetAdvancedPoolHooks', - queryId: s.loadUintBig(64), - advancedPoolHooks: s.loadMaybeAddress(), - } - }, - store(self: TokenPool_SetAdvancedPoolHooks, b: c.Builder): void { - b.storeUint(0x3f5c9f57, 32); - b.storeUint(self.queryId, 64); - b.storeAddress(self.advancedPoolHooks); - }, - toCell(self: TokenPool_SetAdvancedPoolHooks): c.Cell { - return makeCellFrom(self, TokenPool_SetAdvancedPoolHooks.store); - } -} - -/** - > struct (0x3868e309) TokenPool_SetDeployableCode { - > queryId: uint64 - > deployableCode: cell? - > } - */ -export interface TokenPool_SetDeployableCode { - readonly $: 'TokenPool_SetDeployableCode' - queryId: uint64 - deployableCode: c.Cell | null -} - -export const TokenPool_SetDeployableCode = { - PREFIX: 0x3868e309, - - create(args: { - queryId?: uint64 - deployableCode: c.Cell | null - }): TokenPool_SetDeployableCode { - return { - $: 'TokenPool_SetDeployableCode', - ...args, - queryId: args.queryId ?? 0n - } - }, - fromSlice(s: c.Slice): TokenPool_SetDeployableCode { - loadAndCheckPrefix32(s, 0x3868e309, 'TokenPool_SetDeployableCode'); - return { - $: 'TokenPool_SetDeployableCode', - queryId: s.loadUintBig(64), - deployableCode: s.loadBoolean() ? s.loadRef() : null, - } - }, - store(self: TokenPool_SetDeployableCode, b: c.Builder): void { - b.storeUint(0x3868e309, 32); - b.storeUint(self.queryId, 64); - storeTolkNullable(self.deployableCode, b, - (v,b) => b.storeRef(v) - ); - }, - toCell(self: TokenPool_SetDeployableCode): c.Cell { - return makeCellFrom(self, TokenPool_SetDeployableCode.store); - } -} - -/** - > struct (0x89d602e5) TokenPool_DeployableCodeSet { - > queryId: uint64 - > deployableCode: cell? - > } - */ -export interface TokenPool_DeployableCodeSet { - readonly $: 'TokenPool_DeployableCodeSet' - queryId: uint64 - deployableCode: c.Cell | null -} - -export const TokenPool_DeployableCodeSet = { - PREFIX: 0x89d602e5, - - create(args: { - queryId?: uint64 - deployableCode: c.Cell | null - }): TokenPool_DeployableCodeSet { - return { - $: 'TokenPool_DeployableCodeSet', - ...args, - queryId: args.queryId ?? 0n - } - }, - fromSlice(s: c.Slice): TokenPool_DeployableCodeSet { - loadAndCheckPrefix32(s, 0x89d602e5, 'TokenPool_DeployableCodeSet'); - return { - $: 'TokenPool_DeployableCodeSet', - queryId: s.loadUintBig(64), - deployableCode: s.loadBoolean() ? s.loadRef() : null, - } - }, - store(self: TokenPool_DeployableCodeSet, b: c.Builder): void { - b.storeUint(0x89d602e5, 32); - b.storeUint(self.queryId, 64); - storeTolkNullable(self.deployableCode, b, - (v,b) => b.storeRef(v) - ); - }, - toCell(self: TokenPool_DeployableCodeSet): c.Cell { - return makeCellFrom(self, TokenPool_DeployableCodeSet.store); - } -} - -/** - > struct (0x84384142) TokenPool_SetAllowedDepositNamespaces { - > queryId: uint64 - > allowedDepositNamespaces: map - > } - */ -export interface TokenPool_SetAllowedDepositNamespaces { - readonly $: 'TokenPool_SetAllowedDepositNamespaces' - queryId: uint64 - allowedDepositNamespaces: Set -} - -export const TokenPool_SetAllowedDepositNamespaces = { - PREFIX: 0x84384142, - - create(args: { - queryId?: uint64 - allowedDepositNamespaces: Set - }): TokenPool_SetAllowedDepositNamespaces { - return { - $: 'TokenPool_SetAllowedDepositNamespaces', - ...args, - queryId: args.queryId ?? 0n - } - }, - fromSlice(s: c.Slice): TokenPool_SetAllowedDepositNamespaces { - loadAndCheckPrefix32(s, 0x84384142, 'TokenPool_SetAllowedDepositNamespaces'); - return { - $: 'TokenPool_SetAllowedDepositNamespaces', - queryId: s.loadUintBig(64), - allowedDepositNamespaces: dictToSet(c.Dictionary.load(c.Dictionary.Keys.BigUint(32), createDictionaryValue<[]>( - (s) => [], - (v,b) => { {} } - ), s)), - } - }, - store(self: TokenPool_SetAllowedDepositNamespaces, b: c.Builder): void { - b.storeUint(0x84384142, 32); - b.storeUint(self.queryId, 64); - b.storeDict(setToDict(self.allowedDepositNamespaces, c.Dictionary.Keys.BigUint(32), createDictionaryValue<[]>( - (s) => [], - (v,b) => { {} } - )), c.Dictionary.Keys.BigUint(32), createDictionaryValue<[]>( - (s) => [], - (v,b) => { {} } - )); - }, - toCell(self: TokenPool_SetAllowedDepositNamespaces): c.Cell { - return makeCellFrom(self, TokenPool_SetAllowedDepositNamespaces.store); - } -} - -/** - > struct (0xc1ffe3a6) TokenPool_AllowedDepositNamespacesSet { - > queryId: uint64 - > } - */ -export interface TokenPool_AllowedDepositNamespacesSet { - readonly $: 'TokenPool_AllowedDepositNamespacesSet' - queryId: uint64 -} - -export const TokenPool_AllowedDepositNamespacesSet = { - PREFIX: 0xc1ffe3a6, - - create(args: { - queryId?: uint64 - }): TokenPool_AllowedDepositNamespacesSet { - return { - $: 'TokenPool_AllowedDepositNamespacesSet', - ...args, - queryId: args.queryId ?? 0n - } - }, - fromSlice(s: c.Slice): TokenPool_AllowedDepositNamespacesSet { - loadAndCheckPrefix32(s, 0xc1ffe3a6, 'TokenPool_AllowedDepositNamespacesSet'); - return { - $: 'TokenPool_AllowedDepositNamespacesSet', - queryId: s.loadUintBig(64), - } - }, - store(self: TokenPool_AllowedDepositNamespacesSet, b: c.Builder): void { - b.storeUint(0xc1ffe3a6, 32); - b.storeUint(self.queryId, 64); - }, - toCell(self: TokenPool_AllowedDepositNamespacesSet): c.Cell { - return makeCellFrom(self, TokenPool_AllowedDepositNamespacesSet.store); - } -} - -/** - > struct (0x4fe2d26c) TokenPool_SetRateLimitConfig { - > queryId: uint64 - > updates: SnakedCell - > } - */ -export interface TokenPool_SetRateLimitConfig { - readonly $: 'TokenPool_SetRateLimitConfig' - queryId: uint64 - updates: SnakedCell -} - -export const TokenPool_SetRateLimitConfig = { - PREFIX: 0x4fe2d26c, - - create(args: { - queryId?: uint64 - updates: SnakedCell - }): TokenPool_SetRateLimitConfig { - return { - $: 'TokenPool_SetRateLimitConfig', - ...args, - queryId: args.queryId ?? 0n - } - }, - fromSlice(s: c.Slice): TokenPool_SetRateLimitConfig { - loadAndCheckPrefix32(s, 0x4fe2d26c, 'TokenPool_SetRateLimitConfig'); - return { - $: 'TokenPool_SetRateLimitConfig', - queryId: s.loadUintBig(64), - updates: loadSnakedCellOf(s, TokenPool_RateLimitConfigArgs.fromSlice), - } - }, - store(self: TokenPool_SetRateLimitConfig, b: c.Builder): void { - b.storeUint(0x4fe2d26c, 32); - b.storeUint(self.queryId, 64); - storeSnakedCellOf(self.updates, b, TokenPool_RateLimitConfigArgs.store); - }, - toCell(self: TokenPool_SetRateLimitConfig): c.Cell { - return makeCellFrom(self, TokenPool_SetRateLimitConfig.store); - } -} - -/** - > struct (0x30a1d1f7) TokenPool_ApplyTokenTransferFeeConfigUpdates { - > queryId: uint64 - > updates: SnakedCell - > disableChainSelectors: SnakedCell - > } - */ -export interface TokenPool_ApplyTokenTransferFeeConfigUpdates { - readonly $: 'TokenPool_ApplyTokenTransferFeeConfigUpdates' - queryId: uint64 - updates: SnakedCell - disableChainSelectors: SnakedCell -} - -export const TokenPool_ApplyTokenTransferFeeConfigUpdates = { - PREFIX: 0x30a1d1f7, - - create(args: { - queryId?: uint64 - updates: SnakedCell - disableChainSelectors: SnakedCell - }): TokenPool_ApplyTokenTransferFeeConfigUpdates { - return { - $: 'TokenPool_ApplyTokenTransferFeeConfigUpdates', - ...args, - queryId: args.queryId ?? 0n - } - }, - fromSlice(s: c.Slice): TokenPool_ApplyTokenTransferFeeConfigUpdates { - loadAndCheckPrefix32(s, 0x30a1d1f7, 'TokenPool_ApplyTokenTransferFeeConfigUpdates'); - return { - $: 'TokenPool_ApplyTokenTransferFeeConfigUpdates', - queryId: s.loadUintBig(64), - updates: loadSnakedCellOf(s, TokenPool_TokenTransferFeeConfigArgs.fromSlice), - disableChainSelectors: loadSnakedCellOf(s, (s) => s.loadUintBig(64)), - } - }, - store(self: TokenPool_ApplyTokenTransferFeeConfigUpdates, b: c.Builder): void { - b.storeUint(0x30a1d1f7, 32); - b.storeUint(self.queryId, 64); - storeSnakedCellOf(self.updates, b, TokenPool_TokenTransferFeeConfigArgs.store); - storeSnakedCellOf(self.disableChainSelectors, b, (v, b) => b.storeUint(v, 64)); - }, - toCell(self: TokenPool_ApplyTokenTransferFeeConfigUpdates): c.Cell { - return makeCellFrom(self, TokenPool_ApplyTokenTransferFeeConfigUpdates.store); - } -} - -/** - > struct (0x9929b642) TokenPool_SetRMNProxy { - > queryId: uint64 - > rmnProxy: address? - > } - */ -export interface TokenPool_SetRMNProxy { - readonly $: 'TokenPool_SetRMNProxy' - queryId: uint64 - rmnProxy: c.Address | null -} - -export const TokenPool_SetRMNProxy = { - PREFIX: 0x9929b642, - - create(args: { - queryId?: uint64 - rmnProxy: c.Address | null - }): TokenPool_SetRMNProxy { - return { - $: 'TokenPool_SetRMNProxy', - ...args, - queryId: args.queryId ?? 0n - } - }, - fromSlice(s: c.Slice): TokenPool_SetRMNProxy { - loadAndCheckPrefix32(s, 0x9929b642, 'TokenPool_SetRMNProxy'); - return { - $: 'TokenPool_SetRMNProxy', - queryId: s.loadUintBig(64), - rmnProxy: s.loadMaybeAddress(), - } - }, - store(self: TokenPool_SetRMNProxy, b: c.Builder): void { - b.storeUint(0x9929b642, 32); - b.storeUint(self.queryId, 64); - b.storeAddress(self.rmnProxy); - }, - toCell(self: TokenPool_SetRMNProxy): c.Cell { - return makeCellFrom(self, TokenPool_SetRMNProxy.store); - } -} - -/** - > struct (0x9da4da09) TokenPool_SetCursedSubjects { - > queryId: uint64 - > cursedSubjects: CursedSubjects - > } - */ -export interface TokenPool_SetCursedSubjects { - readonly $: 'TokenPool_SetCursedSubjects' - queryId: uint64 - cursedSubjects: CursedSubjects -} - -export const TokenPool_SetCursedSubjects = { - PREFIX: 0x9da4da09, - - create(args: { - queryId?: uint64 - cursedSubjects: CursedSubjects - }): TokenPool_SetCursedSubjects { - return { - $: 'TokenPool_SetCursedSubjects', - ...args, - queryId: args.queryId ?? 0n - } - }, - fromSlice(s: c.Slice): TokenPool_SetCursedSubjects { - loadAndCheckPrefix32(s, 0x9da4da09, 'TokenPool_SetCursedSubjects'); - return { - $: 'TokenPool_SetCursedSubjects', - queryId: s.loadUintBig(64), - cursedSubjects: CursedSubjects.fromSlice(s), - } - }, - store(self: TokenPool_SetCursedSubjects, b: c.Builder): void { - b.storeUint(0x9da4da09, 32); - b.storeUint(self.queryId, 64); - CursedSubjects.store(self.cursedSubjects, b); - }, - toCell(self: TokenPool_SetCursedSubjects): c.Cell { - return makeCellFrom(self, TokenPool_SetCursedSubjects.store); - } -} - -/** - > struct (0xfa7da444) TokenPool_LockOrBurn { - > queryId: uint64 - > request: Cell - > requestedFinalityConfig: uint32 - > tokenArgs: cell? - > replyTo: address? - > } - */ -export interface TokenPool_LockOrBurn { - readonly $: 'TokenPool_LockOrBurn' - queryId: uint64 - request: TokenPool_LockOrBurnInV1 - requestedFinalityConfig: uint32 - tokenArgs: c.Cell | null - replyTo: c.Address | null -} - -export const TokenPool_LockOrBurn = { - PREFIX: 0xfa7da444, - - create(args: { - queryId?: uint64 - request: TokenPool_LockOrBurnInV1 - requestedFinalityConfig: uint32 - tokenArgs: c.Cell | null - replyTo: c.Address | null - }): TokenPool_LockOrBurn { - return { - $: 'TokenPool_LockOrBurn', - ...args, - queryId: args.queryId ?? 0n - } - }, - fromSlice(s: c.Slice): TokenPool_LockOrBurn { - loadAndCheckPrefix32(s, 0xfa7da444, 'TokenPool_LockOrBurn'); - return { - $: 'TokenPool_LockOrBurn', - queryId: s.loadUintBig(64), - request: loadCellRef(s, TokenPool_LockOrBurnInV1.fromSlice), - requestedFinalityConfig: s.loadUintBig(32), - tokenArgs: s.loadBoolean() ? s.loadRef() : null, - replyTo: s.loadMaybeAddress(), - } - }, - store(self: TokenPool_LockOrBurn, b: c.Builder): void { - b.storeUint(0xfa7da444, 32); - b.storeUint(self.queryId, 64); - storeCellRef(self.request, b, TokenPool_LockOrBurnInV1.store); - b.storeUint(self.requestedFinalityConfig, 32); - storeTolkNullable(self.tokenArgs, b, - (v,b) => b.storeRef(v) - ); - b.storeAddress(self.replyTo); - }, - toCell(self: TokenPool_LockOrBurn): c.Cell { - return makeCellFrom(self, TokenPool_LockOrBurn.store); - } -} - -/** - > struct TokenPool_LockOrBurnForwardPayload { - > originalSender: address - > requestMsg: Cell - > prepared: Cell - > } - */ -export interface TokenPool_LockOrBurnForwardPayload { - readonly $: 'TokenPool_LockOrBurnForwardPayload' - originalSender: c.Address - requestMsg: TokenPool_LockOrBurn - prepared: TokenPool_LockOrBurnPrepared -} - -export const TokenPool_LockOrBurnForwardPayload = { - create(args: { - originalSender: c.Address - requestMsg: TokenPool_LockOrBurn - prepared: TokenPool_LockOrBurnPrepared - }): TokenPool_LockOrBurnForwardPayload { - return { - $: 'TokenPool_LockOrBurnForwardPayload', - ...args - } - }, - fromSlice(s: c.Slice): TokenPool_LockOrBurnForwardPayload { - return { - $: 'TokenPool_LockOrBurnForwardPayload', - originalSender: s.loadAddress(), - requestMsg: loadCellRef(s, TokenPool_LockOrBurn.fromSlice), - prepared: loadCellRef(s, TokenPool_LockOrBurnPrepared.fromSlice), - } - }, - store(self: TokenPool_LockOrBurnForwardPayload, b: c.Builder): void { - b.storeAddress(self.originalSender); - storeCellRef(self.requestMsg, b, TokenPool_LockOrBurn.store); - storeCellRef(self.prepared, b, TokenPool_LockOrBurnPrepared.store); - }, - toCell(self: TokenPool_LockOrBurnForwardPayload): c.Cell { - return makeCellFrom(self, TokenPool_LockOrBurnForwardPayload.store); - } -} - -/** - > struct (0x351f77e3) TokenPool_ReleaseOrMint { - > queryId: uint64 - > request: Cell - > requestedFinalityConfig: uint32 - > replyTo: address? - > } - */ -export interface TokenPool_ReleaseOrMint { - readonly $: 'TokenPool_ReleaseOrMint' - queryId: uint64 - request: TokenPool_ReleaseOrMintInV1 - requestedFinalityConfig: uint32 - replyTo: c.Address | null /* = null */ -} - -export const TokenPool_ReleaseOrMint = { - PREFIX: 0x351f77e3, - - create(args: { - queryId?: uint64 - request: TokenPool_ReleaseOrMintInV1 - requestedFinalityConfig: uint32 - replyTo?: c.Address | null /* = null */ - }): TokenPool_ReleaseOrMint { - return { - $: 'TokenPool_ReleaseOrMint', - replyTo: null, - ...args, - queryId: args.queryId ?? 0n - } - }, - fromSlice(s: c.Slice): TokenPool_ReleaseOrMint { - loadAndCheckPrefix32(s, 0x351f77e3, 'TokenPool_ReleaseOrMint'); - return { - $: 'TokenPool_ReleaseOrMint', - queryId: s.loadUintBig(64), - request: loadCellRef(s, TokenPool_ReleaseOrMintInV1.fromSlice), - requestedFinalityConfig: s.loadUintBig(32), - replyTo: s.loadMaybeAddress(), - } - }, - store(self: TokenPool_ReleaseOrMint, b: c.Builder): void { - b.storeUint(0x351f77e3, 32); - b.storeUint(self.queryId, 64); - storeCellRef(self.request, b, TokenPool_ReleaseOrMintInV1.store); - b.storeUint(self.requestedFinalityConfig, 32); - b.storeAddress(self.replyTo); - }, - toCell(self: TokenPool_ReleaseOrMint): c.Cell { - return makeCellFrom(self, TokenPool_ReleaseOrMint.store); - } -} - -/** - > struct (0x08f2ffb7) TokenPool_PreflightCheckFinished { - > queryId: uint64 - > forwardPayload: Cell - > } - */ -export interface TokenPool_PreflightCheckFinished { - readonly $: 'TokenPool_PreflightCheckFinished' - queryId: uint64 - forwardPayload: TokenPool_LockOrBurnForwardPayload -} - -export const TokenPool_PreflightCheckFinished = { - PREFIX: 0x08f2ffb7, - - create(args: { - queryId?: uint64 - forwardPayload: TokenPool_LockOrBurnForwardPayload - }): TokenPool_PreflightCheckFinished { - return { - $: 'TokenPool_PreflightCheckFinished', - ...args, - queryId: args.queryId ?? 0n - } - }, - fromSlice(s: c.Slice): TokenPool_PreflightCheckFinished { - loadAndCheckPrefix32(s, 0x08f2ffb7, 'TokenPool_PreflightCheckFinished'); - return { - $: 'TokenPool_PreflightCheckFinished', - queryId: s.loadUintBig(64), - forwardPayload: loadCellRef(s, TokenPool_LockOrBurnForwardPayload.fromSlice), - } - }, - store(self: TokenPool_PreflightCheckFinished, b: c.Builder): void { - b.storeUint(0x08f2ffb7, 32); - b.storeUint(self.queryId, 64); - storeCellRef(self.forwardPayload, b, TokenPool_LockOrBurnForwardPayload.store); - }, - toCell(self: TokenPool_PreflightCheckFinished): c.Cell { - return makeCellFrom(self, TokenPool_PreflightCheckFinished.store); - } -} - -/** - > struct (0xa6dfa623) TokenPool_PreflightCheckFailed { - > queryId: uint64 - > forwardPayload: Cell - > } - */ -export interface TokenPool_PreflightCheckFailed { - readonly $: 'TokenPool_PreflightCheckFailed' - queryId: uint64 - forwardPayload: TokenPool_LockOrBurnForwardPayload -} - -export const TokenPool_PreflightCheckFailed = { - PREFIX: 0xa6dfa623, - - create(args: { - queryId?: uint64 - forwardPayload: TokenPool_LockOrBurnForwardPayload - }): TokenPool_PreflightCheckFailed { - return { - $: 'TokenPool_PreflightCheckFailed', - ...args, - queryId: args.queryId ?? 0n - } - }, - fromSlice(s: c.Slice): TokenPool_PreflightCheckFailed { - loadAndCheckPrefix32(s, 0xa6dfa623, 'TokenPool_PreflightCheckFailed'); - return { - $: 'TokenPool_PreflightCheckFailed', - queryId: s.loadUintBig(64), - forwardPayload: loadCellRef(s, TokenPool_LockOrBurnForwardPayload.fromSlice), - } - }, - store(self: TokenPool_PreflightCheckFailed, b: c.Builder): void { - b.storeUint(0xa6dfa623, 32); - b.storeUint(self.queryId, 64); - storeCellRef(self.forwardPayload, b, TokenPool_LockOrBurnForwardPayload.store); - }, - toCell(self: TokenPool_PreflightCheckFailed): c.Cell { - return makeCellFrom(self, TokenPool_PreflightCheckFailed.store); - } -} - -/** - > struct TokenPool_ReleaseOrMintForwardPayload { - > originalSender: address - > requestMsg: Cell - > prepared: Cell - > } - */ -export interface TokenPool_ReleaseOrMintForwardPayload { - readonly $: 'TokenPool_ReleaseOrMintForwardPayload' - originalSender: c.Address - requestMsg: TokenPool_ReleaseOrMint - prepared: TokenPool_ReleaseOrMintPrepared -} - -export const TokenPool_ReleaseOrMintForwardPayload = { - create(args: { - originalSender: c.Address - requestMsg: TokenPool_ReleaseOrMint - prepared: TokenPool_ReleaseOrMintPrepared - }): TokenPool_ReleaseOrMintForwardPayload { - return { - $: 'TokenPool_ReleaseOrMintForwardPayload', - ...args - } - }, - fromSlice(s: c.Slice): TokenPool_ReleaseOrMintForwardPayload { - return { - $: 'TokenPool_ReleaseOrMintForwardPayload', - originalSender: s.loadAddress(), - requestMsg: loadCellRef(s, TokenPool_ReleaseOrMint.fromSlice), - prepared: loadCellRef(s, TokenPool_ReleaseOrMintPrepared.fromSlice), - } - }, - store(self: TokenPool_ReleaseOrMintForwardPayload, b: c.Builder): void { - b.storeAddress(self.originalSender); - storeCellRef(self.requestMsg, b, TokenPool_ReleaseOrMint.store); - storeCellRef(self.prepared, b, TokenPool_ReleaseOrMintPrepared.store); - }, - toCell(self: TokenPool_ReleaseOrMintForwardPayload): c.Cell { - return makeCellFrom(self, TokenPool_ReleaseOrMintForwardPayload.store); - } -} - -/** - > struct (0x9e2a6b66) TokenPool_PostflightCheckFinished { - > queryId: uint64 - > forwardPayload: Cell - > } - */ -export interface TokenPool_PostflightCheckFinished { - readonly $: 'TokenPool_PostflightCheckFinished' - queryId: uint64 - forwardPayload: TokenPool_ReleaseOrMintForwardPayload -} - -export const TokenPool_PostflightCheckFinished = { - PREFIX: 0x9e2a6b66, - - create(args: { - queryId?: uint64 - forwardPayload: TokenPool_ReleaseOrMintForwardPayload - }): TokenPool_PostflightCheckFinished { - return { - $: 'TokenPool_PostflightCheckFinished', - ...args, - queryId: args.queryId ?? 0n - } - }, - fromSlice(s: c.Slice): TokenPool_PostflightCheckFinished { - loadAndCheckPrefix32(s, 0x9e2a6b66, 'TokenPool_PostflightCheckFinished'); - return { - $: 'TokenPool_PostflightCheckFinished', - queryId: s.loadUintBig(64), - forwardPayload: loadCellRef(s, TokenPool_ReleaseOrMintForwardPayload.fromSlice), - } - }, - store(self: TokenPool_PostflightCheckFinished, b: c.Builder): void { - b.storeUint(0x9e2a6b66, 32); - b.storeUint(self.queryId, 64); - storeCellRef(self.forwardPayload, b, TokenPool_ReleaseOrMintForwardPayload.store); - }, - toCell(self: TokenPool_PostflightCheckFinished): c.Cell { - return makeCellFrom(self, TokenPool_PostflightCheckFinished.store); - } -} - -/** - > struct (0x21e71d87) TokenPool_PostflightCheckFailed { - > queryId: uint64 - > forwardPayload: Cell - > } - */ -export interface TokenPool_PostflightCheckFailed { - readonly $: 'TokenPool_PostflightCheckFailed' - queryId: uint64 - forwardPayload: TokenPool_ReleaseOrMintForwardPayload -} - -export const TokenPool_PostflightCheckFailed = { - PREFIX: 0x21e71d87, - - create(args: { - queryId?: uint64 - forwardPayload: TokenPool_ReleaseOrMintForwardPayload - }): TokenPool_PostflightCheckFailed { - return { - $: 'TokenPool_PostflightCheckFailed', - ...args, - queryId: args.queryId ?? 0n - } - }, - fromSlice(s: c.Slice): TokenPool_PostflightCheckFailed { - loadAndCheckPrefix32(s, 0x21e71d87, 'TokenPool_PostflightCheckFailed'); - return { - $: 'TokenPool_PostflightCheckFailed', - queryId: s.loadUintBig(64), - forwardPayload: loadCellRef(s, TokenPool_ReleaseOrMintForwardPayload.fromSlice), - } - }, - store(self: TokenPool_PostflightCheckFailed, b: c.Builder): void { - b.storeUint(0x21e71d87, 32); - b.storeUint(self.queryId, 64); - storeCellRef(self.forwardPayload, b, TokenPool_ReleaseOrMintForwardPayload.store); - }, - toCell(self: TokenPool_PostflightCheckFailed): c.Cell { - return makeCellFrom(self, TokenPool_PostflightCheckFailed.store); - } -} - -/** - > struct (0x4129d109) TokenPool_PreflightCheck { - > queryId: uint64 - > request: Cell - > requestedFinalityConfig: uint32 - > tokenArgs: cell? - > amountPostFee: coins - > replyTo: address - > replyPayload: cell? - > } - */ -export interface TokenPool_PreflightCheck { - readonly $: 'TokenPool_PreflightCheck' - queryId: uint64 - request: TokenPool_LockOrBurnInV1 - requestedFinalityConfig: uint32 - tokenArgs: c.Cell | null - amountPostFee: coins - replyTo: c.Address - replyPayload: c.Cell | null -} - -export const TokenPool_PreflightCheck = { - PREFIX: 0x4129d109, - - create(args: { - queryId?: uint64 - request: TokenPool_LockOrBurnInV1 - requestedFinalityConfig: uint32 - tokenArgs: c.Cell | null - amountPostFee: coins - replyTo: c.Address - replyPayload: c.Cell | null - }): TokenPool_PreflightCheck { - return { - $: 'TokenPool_PreflightCheck', - ...args, - queryId: args.queryId ?? 0n - } - }, - fromSlice(s: c.Slice): TokenPool_PreflightCheck { - loadAndCheckPrefix32(s, 0x4129d109, 'TokenPool_PreflightCheck'); - return { - $: 'TokenPool_PreflightCheck', - queryId: s.loadUintBig(64), - request: loadCellRef(s, TokenPool_LockOrBurnInV1.fromSlice), - requestedFinalityConfig: s.loadUintBig(32), - tokenArgs: s.loadBoolean() ? s.loadRef() : null, - amountPostFee: s.loadCoins(), - replyTo: s.loadAddress(), - replyPayload: s.loadBoolean() ? s.loadRef() : null, - } - }, - store(self: TokenPool_PreflightCheck, b: c.Builder): void { - b.storeUint(0x4129d109, 32); - b.storeUint(self.queryId, 64); - storeCellRef(self.request, b, TokenPool_LockOrBurnInV1.store); - b.storeUint(self.requestedFinalityConfig, 32); - storeTolkNullable(self.tokenArgs, b, - (v,b) => b.storeRef(v) - ); - b.storeCoins(self.amountPostFee); - b.storeAddress(self.replyTo); - storeTolkNullable(self.replyPayload, b, - (v,b) => b.storeRef(v) - ); - }, - toCell(self: TokenPool_PreflightCheck): c.Cell { - return makeCellFrom(self, TokenPool_PreflightCheck.store); - } -} - -/** - > struct (0x703c2b58) TokenPool_PostflightCheck { - > queryId: uint64 - > request: Cell - > localAmount: coins - > requestedFinalityConfig: uint32 - > replyTo: address - > replyPayload: cell? - > } - */ -export interface TokenPool_PostflightCheck { - readonly $: 'TokenPool_PostflightCheck' - queryId: uint64 - request: TokenPool_ReleaseOrMintInV1 - localAmount: coins - requestedFinalityConfig: uint32 - replyTo: c.Address - replyPayload: c.Cell | null -} - -export const TokenPool_PostflightCheck = { - PREFIX: 0x703c2b58, - - create(args: { - queryId?: uint64 - request: TokenPool_ReleaseOrMintInV1 - localAmount: coins - requestedFinalityConfig: uint32 - replyTo: c.Address - replyPayload: c.Cell | null - }): TokenPool_PostflightCheck { - return { - $: 'TokenPool_PostflightCheck', - ...args, - queryId: args.queryId ?? 0n - } - }, - fromSlice(s: c.Slice): TokenPool_PostflightCheck { - loadAndCheckPrefix32(s, 0x703c2b58, 'TokenPool_PostflightCheck'); - return { - $: 'TokenPool_PostflightCheck', - queryId: s.loadUintBig(64), - request: loadCellRef(s, TokenPool_ReleaseOrMintInV1.fromSlice), - localAmount: s.loadCoins(), - requestedFinalityConfig: s.loadUintBig(32), - replyTo: s.loadAddress(), - replyPayload: s.loadBoolean() ? s.loadRef() : null, - } - }, - store(self: TokenPool_PostflightCheck, b: c.Builder): void { - b.storeUint(0x703c2b58, 32); - b.storeUint(self.queryId, 64); - storeCellRef(self.request, b, TokenPool_ReleaseOrMintInV1.store); - b.storeCoins(self.localAmount); - b.storeUint(self.requestedFinalityConfig, 32); - b.storeAddress(self.replyTo); - storeTolkNullable(self.replyPayload, b, - (v,b) => b.storeRef(v) - ); - }, - toCell(self: TokenPool_PostflightCheck): c.Cell { - return makeCellFrom(self, TokenPool_PostflightCheck.store); - } -} - -/** - > struct (0xc5476d2b) TokenPool_GetCCVs { - > queryId: uint64 - > localToken: address - > remoteChainSelector: uint64 - > amount: coins - > requestedFinalityConfig: uint32 - > direction: uint8 - > extraData: cell? - > replyTo: address - > forwardPayload: cell? - > } - */ -export interface TokenPool_GetCCVs { - readonly $: 'TokenPool_GetCCVs' - queryId: uint64 - localToken: c.Address - remoteChainSelector: uint64 - amount: coins - requestedFinalityConfig: uint32 - direction: uint8 - extraData: c.Cell | null - replyTo: c.Address - forwardPayload: c.Cell | null -} - -export const TokenPool_GetCCVs = { - PREFIX: 0xc5476d2b, - - create(args: { - queryId?: uint64 - localToken: c.Address - remoteChainSelector: uint64 - amount: coins - requestedFinalityConfig: uint32 - direction: uint8 - extraData: c.Cell | null - replyTo: c.Address - forwardPayload: c.Cell | null - }): TokenPool_GetCCVs { - return { - $: 'TokenPool_GetCCVs', - ...args, - queryId: args.queryId ?? 0n - } - }, - fromSlice(s: c.Slice): TokenPool_GetCCVs { - loadAndCheckPrefix32(s, 0xc5476d2b, 'TokenPool_GetCCVs'); - return { - $: 'TokenPool_GetCCVs', - queryId: s.loadUintBig(64), - localToken: s.loadAddress(), - remoteChainSelector: s.loadUintBig(64), - amount: s.loadCoins(), - requestedFinalityConfig: s.loadUintBig(32), - direction: s.loadUintBig(8), - extraData: s.loadBoolean() ? s.loadRef() : null, - replyTo: s.loadAddress(), - forwardPayload: s.loadBoolean() ? s.loadRef() : null, - } - }, - store(self: TokenPool_GetCCVs, b: c.Builder): void { - b.storeUint(0xc5476d2b, 32); - b.storeUint(self.queryId, 64); - b.storeAddress(self.localToken); - b.storeUint(self.remoteChainSelector, 64); - b.storeCoins(self.amount); - b.storeUint(self.requestedFinalityConfig, 32); - b.storeUint(self.direction, 8); - storeTolkNullable(self.extraData, b, - (v,b) => b.storeRef(v) - ); - b.storeAddress(self.replyTo); - storeTolkNullable(self.forwardPayload, b, - (v,b) => b.storeRef(v) - ); - }, - toCell(self: TokenPool_GetCCVs): c.Cell { - return makeCellFrom(self, TokenPool_GetCCVs.store); - } -} - -/** - > struct (0xd22944d5) TokenPool_GetCCVsAndFees { - > queryId: uint64 - > localToken: address - > remoteChainSelector: uint64 - > amount: coins - > requestedFinalityConfig: uint32 - > direction: uint8 - > extraData: cell? - > forwardPayload: cell? - > } - */ -export interface TokenPool_GetCCVsAndFees { - readonly $: 'TokenPool_GetCCVsAndFees' - queryId: uint64 - localToken: c.Address - remoteChainSelector: uint64 - amount: coins - requestedFinalityConfig: uint32 - direction: uint8 - extraData: c.Cell | null - forwardPayload: c.Cell | null -} - -export const TokenPool_GetCCVsAndFees = { - PREFIX: 0xd22944d5, - - create(args: { - queryId?: uint64 - localToken: c.Address - remoteChainSelector: uint64 - amount: coins - requestedFinalityConfig: uint32 - direction: uint8 - extraData: c.Cell | null - forwardPayload: c.Cell | null - }): TokenPool_GetCCVsAndFees { - return { - $: 'TokenPool_GetCCVsAndFees', - ...args, - queryId: args.queryId ?? 0n - } - }, - fromSlice(s: c.Slice): TokenPool_GetCCVsAndFees { - loadAndCheckPrefix32(s, 0xd22944d5, 'TokenPool_GetCCVsAndFees'); - return { - $: 'TokenPool_GetCCVsAndFees', - queryId: s.loadUintBig(64), - localToken: s.loadAddress(), - remoteChainSelector: s.loadUintBig(64), - amount: s.loadCoins(), - requestedFinalityConfig: s.loadUintBig(32), - direction: s.loadUintBig(8), - extraData: s.loadBoolean() ? s.loadRef() : null, - forwardPayload: s.loadBoolean() ? s.loadRef() : null, - } - }, - store(self: TokenPool_GetCCVsAndFees, b: c.Builder): void { - b.storeUint(0xd22944d5, 32); - b.storeUint(self.queryId, 64); - b.storeAddress(self.localToken); - b.storeUint(self.remoteChainSelector, 64); - b.storeCoins(self.amount); - b.storeUint(self.requestedFinalityConfig, 32); - b.storeUint(self.direction, 8); - storeTolkNullable(self.extraData, b, - (v,b) => b.storeRef(v) - ); - storeTolkNullable(self.forwardPayload, b, - (v,b) => b.storeRef(v) - ); - }, - toCell(self: TokenPool_GetCCVsAndFees): c.Cell { - return makeCellFrom(self, TokenPool_GetCCVsAndFees.store); - } -} - -/** - > struct (0x30612b17) TokenPool_QueryCCVsReply { - > queryId: uint64 - > requiredCCVs: SnakedCell
- > replyPayload: cell? - > } - */ -export interface TokenPool_QueryCCVsReply { - readonly $: 'TokenPool_QueryCCVsReply' - queryId: uint64 - requiredCCVs: SnakedCell - replyPayload: c.Cell | null -} - -export const TokenPool_QueryCCVsReply = { - PREFIX: 0x30612b17, - - create(args: { - queryId?: uint64 - requiredCCVs: SnakedCell - replyPayload: c.Cell | null - }): TokenPool_QueryCCVsReply { - return { - $: 'TokenPool_QueryCCVsReply', - ...args, - queryId: args.queryId ?? 0n - } - }, - fromSlice(s: c.Slice): TokenPool_QueryCCVsReply { - loadAndCheckPrefix32(s, 0x30612b17, 'TokenPool_QueryCCVsReply'); - return { - $: 'TokenPool_QueryCCVsReply', - queryId: s.loadUintBig(64), - requiredCCVs: loadSnakedCellOf(s, (s) => s.loadAddress()), - replyPayload: s.loadBoolean() ? s.loadRef() : null, - } - }, - store(self: TokenPool_QueryCCVsReply, b: c.Builder): void { - b.storeUint(0x30612b17, 32); - b.storeUint(self.queryId, 64); - storeSnakedCellOf(self.requiredCCVs, b, (v, b) => b.storeAddress(v)); - storeTolkNullable(self.replyPayload, b, - (v,b) => b.storeRef(v) - ); - }, - toCell(self: TokenPool_QueryCCVsReply): c.Cell { - return makeCellFrom(self, TokenPool_QueryCCVsReply.store); - } -} - -/** - > struct (0xe7a35041) TokenPool_LockOrBurnWithdraw { - > queryId: uint64 - > forwardPayload: TokenPool_LockOrBurnForwardPayload - > } - */ -export interface TokenPool_LockOrBurnWithdraw { - readonly $: 'TokenPool_LockOrBurnWithdraw' - queryId: uint64 - forwardPayload: TokenPool_LockOrBurnForwardPayload -} - -export const TokenPool_LockOrBurnWithdraw = { - PREFIX: 0xe7a35041, - - create(args: { - queryId?: uint64 - forwardPayload: TokenPool_LockOrBurnForwardPayload - }): TokenPool_LockOrBurnWithdraw { - return { - $: 'TokenPool_LockOrBurnWithdraw', - ...args, - queryId: args.queryId ?? 0n - } - }, - fromSlice(s: c.Slice): TokenPool_LockOrBurnWithdraw { - loadAndCheckPrefix32(s, 0xe7a35041, 'TokenPool_LockOrBurnWithdraw'); - return { - $: 'TokenPool_LockOrBurnWithdraw', - queryId: s.loadUintBig(64), - forwardPayload: TokenPool_LockOrBurnForwardPayload.fromSlice(s), - } - }, - store(self: TokenPool_LockOrBurnWithdraw, b: c.Builder): void { - b.storeUint(0xe7a35041, 32); - b.storeUint(self.queryId, 64); - TokenPool_LockOrBurnForwardPayload.store(self.forwardPayload, b); - }, - toCell(self: TokenPool_LockOrBurnWithdraw): c.Cell { - return makeCellFrom(self, TokenPool_LockOrBurnWithdraw.store); - } -} - -/** - > struct (0xf432a4e3) TokenPool_LockOrBurnFinished { - > queryId: uint64 - > out: Cell - > destTokenAmount: coins - > } - */ -export interface TokenPool_LockOrBurnFinished { - readonly $: 'TokenPool_LockOrBurnFinished' - queryId: uint64 - out: TokenPool_LockOrBurnOutV1 - destTokenAmount: coins -} - -export const TokenPool_LockOrBurnFinished = { - PREFIX: 0xf432a4e3, - - create(args: { - queryId?: uint64 - out: TokenPool_LockOrBurnOutV1 - destTokenAmount: coins - }): TokenPool_LockOrBurnFinished { - return { - $: 'TokenPool_LockOrBurnFinished', - ...args, - queryId: args.queryId ?? 0n - } - }, - fromSlice(s: c.Slice): TokenPool_LockOrBurnFinished { - loadAndCheckPrefix32(s, 0xf432a4e3, 'TokenPool_LockOrBurnFinished'); - return { - $: 'TokenPool_LockOrBurnFinished', - queryId: s.loadUintBig(64), - out: loadCellRef(s, TokenPool_LockOrBurnOutV1.fromSlice), - destTokenAmount: s.loadCoins(), - } - }, - store(self: TokenPool_LockOrBurnFinished, b: c.Builder): void { - b.storeUint(0xf432a4e3, 32); - b.storeUint(self.queryId, 64); - storeCellRef(self.out, b, TokenPool_LockOrBurnOutV1.store); - b.storeCoins(self.destTokenAmount); - }, - toCell(self: TokenPool_LockOrBurnFinished): c.Cell { - return makeCellFrom(self, TokenPool_LockOrBurnFinished.store); - } -} - -/** - > struct (0x3476ea72) TokenPool_LockOrBurnFailure { - > queryId: uint64 - > errorCode: uint16 - > } - */ -export interface TokenPool_LockOrBurnFailure { - readonly $: 'TokenPool_LockOrBurnFailure' - queryId: uint64 - errorCode: uint16 -} - -export const TokenPool_LockOrBurnFailure = { - PREFIX: 0x3476ea72, - - create(args: { - queryId?: uint64 - errorCode: uint16 - }): TokenPool_LockOrBurnFailure { - return { - $: 'TokenPool_LockOrBurnFailure', - ...args, - queryId: args.queryId ?? 0n - } - }, - fromSlice(s: c.Slice): TokenPool_LockOrBurnFailure { - loadAndCheckPrefix32(s, 0x3476ea72, 'TokenPool_LockOrBurnFailure'); - return { - $: 'TokenPool_LockOrBurnFailure', - queryId: s.loadUintBig(64), - errorCode: s.loadUintBig(16), - } - }, - store(self: TokenPool_LockOrBurnFailure, b: c.Builder): void { - b.storeUint(0x3476ea72, 32); - b.storeUint(self.queryId, 64); - b.storeUint(self.errorCode, 16); - }, - toCell(self: TokenPool_LockOrBurnFailure): c.Cell { - return makeCellFrom(self, TokenPool_LockOrBurnFailure.store); - } -} - -/** - > struct (0xe0e882f5) TokenPool_ReleaseOrMintFinished { - > queryId: uint64 - > out: Cell - > } - */ -export interface TokenPool_ReleaseOrMintFinished { - readonly $: 'TokenPool_ReleaseOrMintFinished' - queryId: uint64 - out: TokenPool_ReleaseOrMintOutV1 -} - -export const TokenPool_ReleaseOrMintFinished = { - PREFIX: 0xe0e882f5, - - create(args: { - queryId?: uint64 - out: TokenPool_ReleaseOrMintOutV1 - }): TokenPool_ReleaseOrMintFinished { - return { - $: 'TokenPool_ReleaseOrMintFinished', - ...args, - queryId: args.queryId ?? 0n - } - }, - fromSlice(s: c.Slice): TokenPool_ReleaseOrMintFinished { - loadAndCheckPrefix32(s, 0xe0e882f5, 'TokenPool_ReleaseOrMintFinished'); - return { - $: 'TokenPool_ReleaseOrMintFinished', - queryId: s.loadUintBig(64), - out: loadCellRef(s, TokenPool_ReleaseOrMintOutV1.fromSlice), - } - }, - store(self: TokenPool_ReleaseOrMintFinished, b: c.Builder): void { - b.storeUint(0xe0e882f5, 32); - b.storeUint(self.queryId, 64); - storeCellRef(self.out, b, TokenPool_ReleaseOrMintOutV1.store); - }, - toCell(self: TokenPool_ReleaseOrMintFinished): c.Cell { - return makeCellFrom(self, TokenPool_ReleaseOrMintFinished.store); - } -} - -/** - > struct (0xef0cb36e) TokenPool_ReleaseOrMintFailure { - > queryId: uint64 - > errorCode: uint16 - > } - */ -export interface TokenPool_ReleaseOrMintFailure { - readonly $: 'TokenPool_ReleaseOrMintFailure' - queryId: uint64 - errorCode: uint16 -} - -export const TokenPool_ReleaseOrMintFailure = { - PREFIX: 0xef0cb36e, - - create(args: { - queryId?: uint64 - errorCode: uint16 - }): TokenPool_ReleaseOrMintFailure { - return { - $: 'TokenPool_ReleaseOrMintFailure', - ...args, - queryId: args.queryId ?? 0n - } - }, - fromSlice(s: c.Slice): TokenPool_ReleaseOrMintFailure { - loadAndCheckPrefix32(s, 0xef0cb36e, 'TokenPool_ReleaseOrMintFailure'); - return { - $: 'TokenPool_ReleaseOrMintFailure', - queryId: s.loadUintBig(64), - errorCode: s.loadUintBig(16), - } - }, - store(self: TokenPool_ReleaseOrMintFailure, b: c.Builder): void { - b.storeUint(0xef0cb36e, 32); - b.storeUint(self.queryId, 64); - b.storeUint(self.errorCode, 16); - }, - toCell(self: TokenPool_ReleaseOrMintFailure): c.Cell { - return makeCellFrom(self, TokenPool_ReleaseOrMintFailure.store); - } -} - -/** - > struct (0x12cc4985) TokenPool_RemotePoolAddedNotification { - > queryId: uint64 - > remoteChainSelector: uint64 - > remotePoolAddress: Cell - > } - */ -export interface TokenPool_RemotePoolAddedNotification { - readonly $: 'TokenPool_RemotePoolAddedNotification' - queryId: uint64 - remoteChainSelector: uint64 - remotePoolAddress: CrossChainAddress -} - -export const TokenPool_RemotePoolAddedNotification = { - PREFIX: 0x12cc4985, - - create(args: { - queryId?: uint64 - remoteChainSelector: uint64 - remotePoolAddress: CrossChainAddress - }): TokenPool_RemotePoolAddedNotification { - return { - $: 'TokenPool_RemotePoolAddedNotification', - ...args, - queryId: args.queryId ?? 0n - } - }, - fromSlice(s: c.Slice): TokenPool_RemotePoolAddedNotification { - loadAndCheckPrefix32(s, 0x12cc4985, 'TokenPool_RemotePoolAddedNotification'); - return { - $: 'TokenPool_RemotePoolAddedNotification', - queryId: s.loadUintBig(64), - remoteChainSelector: s.loadUintBig(64), - remotePoolAddress: loadCellRef(s, CrossChainAddress.fromSlice), - } - }, - store(self: TokenPool_RemotePoolAddedNotification, b: c.Builder): void { - b.storeUint(0x12cc4985, 32); - b.storeUint(self.queryId, 64); - b.storeUint(self.remoteChainSelector, 64); - storeCellRef(self.remotePoolAddress, b, CrossChainAddress.store); - }, - toCell(self: TokenPool_RemotePoolAddedNotification): c.Cell { - return makeCellFrom(self, TokenPool_RemotePoolAddedNotification.store); - } -} - -/** - > struct (0xe17bf3cc) TokenPool_RemotePoolRemovedNotification { - > queryId: uint64 - > remoteChainSelector: uint64 - > remotePoolAddress: Cell - > } - */ -export interface TokenPool_RemotePoolRemovedNotification { - readonly $: 'TokenPool_RemotePoolRemovedNotification' - queryId: uint64 - remoteChainSelector: uint64 - remotePoolAddress: CrossChainAddress -} - -export const TokenPool_RemotePoolRemovedNotification = { - PREFIX: 0xe17bf3cc, - - create(args: { - queryId?: uint64 - remoteChainSelector: uint64 - remotePoolAddress: CrossChainAddress - }): TokenPool_RemotePoolRemovedNotification { - return { - $: 'TokenPool_RemotePoolRemovedNotification', - ...args, - queryId: args.queryId ?? 0n - } - }, - fromSlice(s: c.Slice): TokenPool_RemotePoolRemovedNotification { - loadAndCheckPrefix32(s, 0xe17bf3cc, 'TokenPool_RemotePoolRemovedNotification'); - return { - $: 'TokenPool_RemotePoolRemovedNotification', - queryId: s.loadUintBig(64), - remoteChainSelector: s.loadUintBig(64), - remotePoolAddress: loadCellRef(s, CrossChainAddress.fromSlice), - } - }, - store(self: TokenPool_RemotePoolRemovedNotification, b: c.Builder): void { - b.storeUint(0xe17bf3cc, 32); - b.storeUint(self.queryId, 64); - b.storeUint(self.remoteChainSelector, 64); - storeCellRef(self.remotePoolAddress, b, CrossChainAddress.store); - }, - toCell(self: TokenPool_RemotePoolRemovedNotification): c.Cell { - return makeCellFrom(self, TokenPool_RemotePoolRemovedNotification.store); - } -} - -/** - > struct (0x426a713b) TokenPool_FinalityConfigSet { - > queryId: uint64 - > allowedFinalityConfig: uint32 - > } - */ -export interface TokenPool_FinalityConfigSet { - readonly $: 'TokenPool_FinalityConfigSet' - queryId: uint64 - allowedFinalityConfig: uint32 -} - -export const TokenPool_FinalityConfigSet = { - PREFIX: 0x426a713b, - - create(args: { - queryId?: uint64 - allowedFinalityConfig: uint32 - }): TokenPool_FinalityConfigSet { - return { - $: 'TokenPool_FinalityConfigSet', - ...args, - queryId: args.queryId ?? 0n - } - }, - fromSlice(s: c.Slice): TokenPool_FinalityConfigSet { - loadAndCheckPrefix32(s, 0x426a713b, 'TokenPool_FinalityConfigSet'); - return { - $: 'TokenPool_FinalityConfigSet', - queryId: s.loadUintBig(64), - allowedFinalityConfig: s.loadUintBig(32), - } - }, - store(self: TokenPool_FinalityConfigSet, b: c.Builder): void { - b.storeUint(0x426a713b, 32); - b.storeUint(self.queryId, 64); - b.storeUint(self.allowedFinalityConfig, 32); - }, - toCell(self: TokenPool_FinalityConfigSet): c.Cell { - return makeCellFrom(self, TokenPool_FinalityConfigSet.store); - } -} - -/** - > struct (0xb735e30c) TokenPool_DynamicConfigSet { - > queryId: uint64 - > router: address - > rateLimitAdmin: address? - > feeAdmin: address? - > } - */ -export interface TokenPool_DynamicConfigSet { - readonly $: 'TokenPool_DynamicConfigSet' - queryId: uint64 - router: c.Address - rateLimitAdmin: c.Address | null - feeAdmin: c.Address | null -} - -export const TokenPool_DynamicConfigSet = { - PREFIX: 0xb735e30c, - - create(args: { - queryId?: uint64 - router: c.Address - rateLimitAdmin: c.Address | null - feeAdmin: c.Address | null - }): TokenPool_DynamicConfigSet { - return { - $: 'TokenPool_DynamicConfigSet', - ...args, - queryId: args.queryId ?? 0n - } - }, - fromSlice(s: c.Slice): TokenPool_DynamicConfigSet { - loadAndCheckPrefix32(s, 0xb735e30c, 'TokenPool_DynamicConfigSet'); - return { - $: 'TokenPool_DynamicConfigSet', - queryId: s.loadUintBig(64), - router: s.loadAddress(), - rateLimitAdmin: s.loadMaybeAddress(), - feeAdmin: s.loadMaybeAddress(), - } - }, - store(self: TokenPool_DynamicConfigSet, b: c.Builder): void { - b.storeUint(0xb735e30c, 32); - b.storeUint(self.queryId, 64); - b.storeAddress(self.router); - b.storeAddress(self.rateLimitAdmin); - b.storeAddress(self.feeAdmin); - }, - toCell(self: TokenPool_DynamicConfigSet): c.Cell { - return makeCellFrom(self, TokenPool_DynamicConfigSet.store); - } -} - -/** - > struct (0xdd7b0c71) TokenPool_RateLimitConfiguredNotification { - > queryId: uint64 - > } - */ -export interface TokenPool_RateLimitConfiguredNotification { - readonly $: 'TokenPool_RateLimitConfiguredNotification' - queryId: uint64 -} - -export const TokenPool_RateLimitConfiguredNotification = { - PREFIX: 0xdd7b0c71, - - create(args: { - queryId?: uint64 - }): TokenPool_RateLimitConfiguredNotification { - return { - $: 'TokenPool_RateLimitConfiguredNotification', - ...args, - queryId: args.queryId ?? 0n - } - }, - fromSlice(s: c.Slice): TokenPool_RateLimitConfiguredNotification { - loadAndCheckPrefix32(s, 0xdd7b0c71, 'TokenPool_RateLimitConfiguredNotification'); - return { - $: 'TokenPool_RateLimitConfiguredNotification', - queryId: s.loadUintBig(64), - } - }, - store(self: TokenPool_RateLimitConfiguredNotification, b: c.Builder): void { - b.storeUint(0xdd7b0c71, 32); - b.storeUint(self.queryId, 64); - }, - toCell(self: TokenPool_RateLimitConfiguredNotification): c.Cell { - return makeCellFrom(self, TokenPool_RateLimitConfiguredNotification.store); - } -} - -/** - > struct (0xe5d08b2e) TokenPool_RMNProxySet { - > queryId: uint64 - > rmnProxy: address? - > } - */ -export interface TokenPool_RMNProxySet { - readonly $: 'TokenPool_RMNProxySet' - queryId: uint64 - rmnProxy: c.Address | null -} - -export const TokenPool_RMNProxySet = { - PREFIX: 0xe5d08b2e, - - create(args: { - queryId?: uint64 - rmnProxy: c.Address | null - }): TokenPool_RMNProxySet { - return { - $: 'TokenPool_RMNProxySet', - ...args, - queryId: args.queryId ?? 0n - } - }, - fromSlice(s: c.Slice): TokenPool_RMNProxySet { - loadAndCheckPrefix32(s, 0xe5d08b2e, 'TokenPool_RMNProxySet'); - return { - $: 'TokenPool_RMNProxySet', - queryId: s.loadUintBig(64), - rmnProxy: s.loadMaybeAddress(), - } - }, - store(self: TokenPool_RMNProxySet, b: c.Builder): void { - b.storeUint(0xe5d08b2e, 32); - b.storeUint(self.queryId, 64); - b.storeAddress(self.rmnProxy); - }, - toCell(self: TokenPool_RMNProxySet): c.Cell { - return makeCellFrom(self, TokenPool_RMNProxySet.store); - } -} - -/** - > struct (0x15800161) TokenPool_CursedSubjectsSet { - > queryId: uint64 - > cursedSubjects: CursedSubjects - > } - */ -export interface TokenPool_CursedSubjectsSet { - readonly $: 'TokenPool_CursedSubjectsSet' - queryId: uint64 - cursedSubjects: CursedSubjects -} - -export const TokenPool_CursedSubjectsSet = { - PREFIX: 0x15800161, - - create(args: { - queryId?: uint64 - cursedSubjects: CursedSubjects - }): TokenPool_CursedSubjectsSet { - return { - $: 'TokenPool_CursedSubjectsSet', - ...args, - queryId: args.queryId ?? 0n - } - }, - fromSlice(s: c.Slice): TokenPool_CursedSubjectsSet { - loadAndCheckPrefix32(s, 0x15800161, 'TokenPool_CursedSubjectsSet'); - return { - $: 'TokenPool_CursedSubjectsSet', - queryId: s.loadUintBig(64), - cursedSubjects: CursedSubjects.fromSlice(s), - } - }, - store(self: TokenPool_CursedSubjectsSet, b: c.Builder): void { - b.storeUint(0x15800161, 32); - b.storeUint(self.queryId, 64); - CursedSubjects.store(self.cursedSubjects, b); - }, - toCell(self: TokenPool_CursedSubjectsSet): c.Cell { - return makeCellFrom(self, TokenPool_CursedSubjectsSet.store); - } -} - -/** - > struct (0xad7833d7) TokenPool_ChainUpdatesApplied { - > queryId: uint64 - > } - */ -export interface TokenPool_ChainUpdatesApplied { - readonly $: 'TokenPool_ChainUpdatesApplied' - queryId: uint64 -} - -export const TokenPool_ChainUpdatesApplied = { - PREFIX: 0xad7833d7, - - create(args: { - queryId?: uint64 - }): TokenPool_ChainUpdatesApplied { - return { - $: 'TokenPool_ChainUpdatesApplied', - ...args, - queryId: args.queryId ?? 0n - } - }, - fromSlice(s: c.Slice): TokenPool_ChainUpdatesApplied { - loadAndCheckPrefix32(s, 0xad7833d7, 'TokenPool_ChainUpdatesApplied'); - return { - $: 'TokenPool_ChainUpdatesApplied', - queryId: s.loadUintBig(64), - } - }, - store(self: TokenPool_ChainUpdatesApplied, b: c.Builder): void { - b.storeUint(0xad7833d7, 32); - b.storeUint(self.queryId, 64); - }, - toCell(self: TokenPool_ChainUpdatesApplied): c.Cell { - return makeCellFrom(self, TokenPool_ChainUpdatesApplied.store); - } -} - -/** - > struct (0x28cbcc64) TokenPool_FeeConfigApplied { - > queryId: uint64 - > } - */ -export interface TokenPool_FeeConfigApplied { - readonly $: 'TokenPool_FeeConfigApplied' - queryId: uint64 -} - -export const TokenPool_FeeConfigApplied = { - PREFIX: 0x28cbcc64, - - create(args: { - queryId?: uint64 - }): TokenPool_FeeConfigApplied { - return { - $: 'TokenPool_FeeConfigApplied', - ...args, - queryId: args.queryId ?? 0n - } - }, - fromSlice(s: c.Slice): TokenPool_FeeConfigApplied { - loadAndCheckPrefix32(s, 0x28cbcc64, 'TokenPool_FeeConfigApplied'); - return { - $: 'TokenPool_FeeConfigApplied', - queryId: s.loadUintBig(64), - } - }, - store(self: TokenPool_FeeConfigApplied, b: c.Builder): void { - b.storeUint(0x28cbcc64, 32); - b.storeUint(self.queryId, 64); - }, - toCell(self: TokenPool_FeeConfigApplied): c.Cell { - return makeCellFrom(self, TokenPool_FeeConfigApplied.store); - } -} - -/** - > struct (0x3c869d80) TokenPool_AdvancedPoolHooksSet { - > queryId: uint64 - > advancedPoolHooks: address? - > } - */ -export interface TokenPool_AdvancedPoolHooksSet { - readonly $: 'TokenPool_AdvancedPoolHooksSet' - queryId: uint64 - advancedPoolHooks: c.Address | null -} - -export const TokenPool_AdvancedPoolHooksSet = { - PREFIX: 0x3c869d80, - - create(args: { - queryId?: uint64 - advancedPoolHooks: c.Address | null - }): TokenPool_AdvancedPoolHooksSet { - return { - $: 'TokenPool_AdvancedPoolHooksSet', - ...args, - queryId: args.queryId ?? 0n - } - }, - fromSlice(s: c.Slice): TokenPool_AdvancedPoolHooksSet { - loadAndCheckPrefix32(s, 0x3c869d80, 'TokenPool_AdvancedPoolHooksSet'); - return { - $: 'TokenPool_AdvancedPoolHooksSet', - queryId: s.loadUintBig(64), - advancedPoolHooks: s.loadMaybeAddress(), - } - }, - store(self: TokenPool_AdvancedPoolHooksSet, b: c.Builder): void { - b.storeUint(0x3c869d80, 32); - b.storeUint(self.queryId, 64); - b.storeAddress(self.advancedPoolHooks); - }, - toCell(self: TokenPool_AdvancedPoolHooksSet): c.Cell { - return makeCellFrom(self, TokenPool_AdvancedPoolHooksSet.store); - } -} - -/** - > type SnakedCell = cell - */ -export type SnakedCell = T[] - -function storeSnakedCellOf(v: SnakedCell, b: c.Builder, storeFn_T: StoreCallback): void { - if (v.length === 0) { - b.storeRef(c.Cell.EMPTY); - return; - } - const cells: c.Builder[] = []; - let builder = c.beginCell(); - for (const value of v) { - let itemB = c.beginCell(); - storeFn_T(value, itemB); - if (builder.availableBits < itemB.bits || builder.availableRefs <= 1) { - cells.push(builder); - builder = c.beginCell(); - } - builder.storeBuilder(itemB); - } - cells.push(builder); - let current = cells[cells.length - 1].endCell(); - for (let i = cells.length - 2; i >= 0; i--) { - cells[i].storeRef(current); - current = cells[i].endCell(); - } - b.storeRef(current); -} - -function loadSnakedCellOf(s: c.Slice, loadFn_T: LoadCallback): SnakedCell { - let outArr = [] as T[]; - let head = s.loadRef().beginParse(); - while (head.remainingBits > 0 || head.remainingRefs > 0) { - if (head.remainingBits > 0) { - outArr.push(loadFn_T(head)); - } - if (head.remainingRefs > 0) { - head = head.loadRef().beginParse(); - } else { - break; - } - } - return outArr; -} - - -/** - > type ForwardPayloadRemainder = RemainingBitsAndRefs - */ -export type ForwardPayloadRemainder = RemainingBitsAndRefs - -export const ForwardPayloadRemainder = { - fromSlice(s: c.Slice): ForwardPayloadRemainder { - return loadTolkRemaining(s); - }, - store(self: ForwardPayloadRemainder, b: c.Builder): void { - storeTolkRemaining(self, b); - }, - toCell(self: ForwardPayloadRemainder): c.Cell { - return makeCellFrom(self, ForwardPayloadRemainder.store); - } -} - -/** - > struct (0x0f8a7ea5) AskToTransfer { - > queryId: uint64 - > jettonAmount: coins - > transferRecipient: address - > sendExcessesTo: address? - > customPayload: cell? - > forwardTonAmount: coins - > forwardPayload: ForwardPayloadRemainder - > } - */ -export interface AskToTransfer { - readonly $: 'AskToTransfer' - queryId: uint64 - jettonAmount: coins - transferRecipient: c.Address - sendExcessesTo: c.Address | null - customPayload: c.Cell | null - forwardTonAmount: coins - forwardPayload: ForwardPayloadRemainder -} - -export const AskToTransfer = { - PREFIX: 0x0f8a7ea5, - - create(args: { - queryId?: uint64 - jettonAmount: coins - transferRecipient: c.Address - sendExcessesTo: c.Address | null - customPayload: c.Cell | null - forwardTonAmount: coins - forwardPayload: ForwardPayloadRemainder - }): AskToTransfer { - return { - $: 'AskToTransfer', - ...args, - queryId: args.queryId ?? 0n - } - }, - fromSlice(s: c.Slice): AskToTransfer { - loadAndCheckPrefix32(s, 0x0f8a7ea5, 'AskToTransfer'); - return { - $: 'AskToTransfer', - queryId: s.loadUintBig(64), - jettonAmount: s.loadCoins(), - transferRecipient: s.loadAddress(), - sendExcessesTo: s.loadMaybeAddress(), - customPayload: s.loadBoolean() ? s.loadRef() : null, - forwardTonAmount: s.loadCoins(), - forwardPayload: ForwardPayloadRemainder.fromSlice(s), - } - }, - store(self: AskToTransfer, b: c.Builder): void { - b.storeUint(0x0f8a7ea5, 32); - b.storeUint(self.queryId, 64); - b.storeCoins(self.jettonAmount); - b.storeAddress(self.transferRecipient); - b.storeAddress(self.sendExcessesTo); - storeTolkNullable(self.customPayload, b, - (v,b) => b.storeRef(v) - ); - b.storeCoins(self.forwardTonAmount); - ForwardPayloadRemainder.store(self.forwardPayload, b); - }, - toCell(self: AskToTransfer): c.Cell { - return makeCellFrom(self, AskToTransfer.store); - } -} - -/** - > struct (0x7362d09c) TransferNotificationForRecipient { - > queryId: uint64 - > jettonAmount: coins - > transferInitiator: address? - > forwardPayload: ForwardPayloadRemainder - > } - */ -export interface TransferNotificationForRecipient { - readonly $: 'TransferNotificationForRecipient' - queryId: uint64 - jettonAmount: coins - transferInitiator: c.Address | null - forwardPayload: ForwardPayloadRemainder -} - -export const TransferNotificationForRecipient = { - PREFIX: 0x7362d09c, - - create(args: { - queryId?: uint64 - jettonAmount: coins - transferInitiator: c.Address | null - forwardPayload: ForwardPayloadRemainder - }): TransferNotificationForRecipient { - return { - $: 'TransferNotificationForRecipient', - ...args, - queryId: args.queryId ?? 0n - } - }, - fromSlice(s: c.Slice): TransferNotificationForRecipient { - loadAndCheckPrefix32(s, 0x7362d09c, 'TransferNotificationForRecipient'); - return { - $: 'TransferNotificationForRecipient', - queryId: s.loadUintBig(64), - jettonAmount: s.loadCoins(), - transferInitiator: s.loadMaybeAddress(), - forwardPayload: ForwardPayloadRemainder.fromSlice(s), - } - }, - store(self: TransferNotificationForRecipient, b: c.Builder): void { - b.storeUint(0x7362d09c, 32); - b.storeUint(self.queryId, 64); - b.storeCoins(self.jettonAmount); - b.storeAddress(self.transferInitiator); - ForwardPayloadRemainder.store(self.forwardPayload, b); - }, - toCell(self: TransferNotificationForRecipient): c.Cell { - return makeCellFrom(self, TransferNotificationForRecipient.store); - } -} - -/** - > struct JettonClient { - > masterAddress: address - > jettonWalletCode: cell - > } - */ -export interface JettonClient { - readonly $: 'JettonClient' - masterAddress: c.Address - jettonWalletCode: c.Cell -} - -export const JettonClient = { - create(args: { - masterAddress: c.Address - jettonWalletCode: c.Cell - }): JettonClient { - return { - $: 'JettonClient', - ...args - } - }, - fromSlice(s: c.Slice): JettonClient { - return { - $: 'JettonClient', - masterAddress: s.loadAddress(), - jettonWalletCode: s.loadRef(), - } - }, - store(self: JettonClient, b: c.Builder): void { - b.storeAddress(self.masterAddress); - b.storeRef(self.jettonWalletCode); - }, - toCell(self: JettonClient): c.Cell { - return makeCellFrom(self, JettonClient.store); - } -} - -/** - > struct Ownable2Step { - > owner: address - > pendingOwner: address? - > } - */ -export interface Ownable2Step { - readonly $: 'Ownable2Step' - owner: c.Address - pendingOwner: c.Address | null /* = null */ -} - -export const Ownable2Step = { - create(args: { - owner: c.Address - pendingOwner?: c.Address | null /* = null */ - }): Ownable2Step { - return { - $: 'Ownable2Step', - pendingOwner: null, - ...args - } - }, - fromSlice(s: c.Slice): Ownable2Step { - return { - $: 'Ownable2Step', - owner: s.loadAddress(), - pendingOwner: s.loadMaybeAddress(), - } - }, - store(self: Ownable2Step, b: c.Builder): void { - b.storeAddress(self.owner); - b.storeAddress(self.pendingOwner); - }, - toCell(self: Ownable2Step): c.Cell { - return makeCellFrom(self, Ownable2Step.store); - } -} - -/** - > struct Ownable2Step_OwnershipTransferRequested { - > queryId: uint64 - > newOwner: address - > } - */ -export interface Ownable2Step_OwnershipTransferRequested { - readonly $: 'Ownable2Step_OwnershipTransferRequested' - queryId: uint64 - newOwner: c.Address -} - -export const Ownable2Step_OwnershipTransferRequested = { - create(args: { - queryId?: uint64 - newOwner: c.Address - }): Ownable2Step_OwnershipTransferRequested { - return { - $: 'Ownable2Step_OwnershipTransferRequested', - ...args, - queryId: args.queryId ?? 0n - } - }, - fromSlice(s: c.Slice): Ownable2Step_OwnershipTransferRequested { - return { - $: 'Ownable2Step_OwnershipTransferRequested', - queryId: s.loadUintBig(64), - newOwner: s.loadAddress(), - } - }, - store(self: Ownable2Step_OwnershipTransferRequested, b: c.Builder): void { - b.storeUint(self.queryId, 64); - b.storeAddress(self.newOwner); - }, - toCell(self: Ownable2Step_OwnershipTransferRequested): c.Cell { - return makeCellFrom(self, Ownable2Step_OwnershipTransferRequested.store); - } -} - -/** - > struct Ownable2Step_OwnershipTransferred { - > queryId: uint64 - > oldOwner: address - > newOwner: address - > } - */ -export interface Ownable2Step_OwnershipTransferred { - readonly $: 'Ownable2Step_OwnershipTransferred' - queryId: uint64 - oldOwner: c.Address - newOwner: c.Address -} - -export const Ownable2Step_OwnershipTransferred = { - create(args: { - queryId?: uint64 - oldOwner: c.Address - newOwner: c.Address - }): Ownable2Step_OwnershipTransferred { - return { - $: 'Ownable2Step_OwnershipTransferred', - ...args, - queryId: args.queryId ?? 0n - } - }, - fromSlice(s: c.Slice): Ownable2Step_OwnershipTransferred { - return { - $: 'Ownable2Step_OwnershipTransferred', - queryId: s.loadUintBig(64), - oldOwner: s.loadAddress(), - newOwner: s.loadAddress(), - } - }, - store(self: Ownable2Step_OwnershipTransferred, b: c.Builder): void { - b.storeUint(self.queryId, 64); - b.storeAddress(self.oldOwner); - b.storeAddress(self.newOwner); - }, - toCell(self: Ownable2Step_OwnershipTransferred): c.Cell { - return makeCellFrom(self, Ownable2Step_OwnershipTransferred.store); - } -} - -/** - > struct JettonWithdrawable_WithdrawFeeTransfer { - > wallet: address - > value: coins - > msg: AskToTransfer - > } - */ -export interface JettonWithdrawable_WithdrawFeeTransfer { - readonly $: 'JettonWithdrawable_WithdrawFeeTransfer' - wallet: c.Address - value: coins - msg: AskToTransfer -} - -export const JettonWithdrawable_WithdrawFeeTransfer = { - create(args: { - wallet: c.Address - value: coins - msg: AskToTransfer - }): JettonWithdrawable_WithdrawFeeTransfer { - return { - $: 'JettonWithdrawable_WithdrawFeeTransfer', - ...args - } - }, - fromSlice(s: c.Slice): JettonWithdrawable_WithdrawFeeTransfer { - return { - $: 'JettonWithdrawable_WithdrawFeeTransfer', - wallet: s.loadAddress(), - value: s.loadCoins(), - msg: AskToTransfer.fromSlice(s), - } - }, - store(self: JettonWithdrawable_WithdrawFeeTransfer, b: c.Builder): void { - b.storeAddress(self.wallet); - b.storeCoins(self.value); - AskToTransfer.store(self.msg, b); - }, - toCell(self: JettonWithdrawable_WithdrawFeeTransfer): c.Cell { - return makeCellFrom(self, JettonWithdrawable_WithdrawFeeTransfer.store); - } -} - -/** - > struct (0x0d00995c) JettonWithdrawable_Withdraw { - > queryId: uint64 - > transfers: array - > } - */ -export interface JettonWithdrawable_Withdraw { - readonly $: 'JettonWithdrawable_Withdraw' - queryId: uint64 - transfers: array -} - -export const JettonWithdrawable_Withdraw = { - PREFIX: 0x0d00995c, - - create(args: { - queryId?: uint64 - transfers: array - }): JettonWithdrawable_Withdraw { - return { - $: 'JettonWithdrawable_Withdraw', - ...args, - queryId: args.queryId ?? 0n - } - }, - fromSlice(s: c.Slice): JettonWithdrawable_Withdraw { - loadAndCheckPrefix32(s, 0x0d00995c, 'JettonWithdrawable_Withdraw'); - return { - $: 'JettonWithdrawable_Withdraw', - queryId: s.loadUintBig(64), - transfers: loadArrayOf(s, JettonWithdrawable_WithdrawFeeTransfer.fromSlice), - } - }, - store(self: JettonWithdrawable_Withdraw, b: c.Builder): void { - b.storeUint(0x0d00995c, 32); - b.storeUint(self.queryId, 64); - storeArrayOf(self.transfers, b, JettonWithdrawable_WithdrawFeeTransfer.store); - }, - toCell(self: JettonWithdrawable_Withdraw): c.Cell { - return makeCellFrom(self, JettonWithdrawable_Withdraw.store); - } -} - -/** - > struct JettonWithdrawable_FeeTokenWithdrawn { - > wallet: address - > amount: coins - > } - */ -export interface JettonWithdrawable_FeeTokenWithdrawn { - readonly $: 'JettonWithdrawable_FeeTokenWithdrawn' - wallet: c.Address - amount: coins -} - -export const JettonWithdrawable_FeeTokenWithdrawn = { - create(args: { - wallet: c.Address - amount: coins - }): JettonWithdrawable_FeeTokenWithdrawn { - return { - $: 'JettonWithdrawable_FeeTokenWithdrawn', - ...args - } - }, - fromSlice(s: c.Slice): JettonWithdrawable_FeeTokenWithdrawn { - return { - $: 'JettonWithdrawable_FeeTokenWithdrawn', - wallet: s.loadAddress(), - amount: s.loadCoins(), - } - }, - store(self: JettonWithdrawable_FeeTokenWithdrawn, b: c.Builder): void { - b.storeAddress(self.wallet); - b.storeCoins(self.amount); - }, - toCell(self: JettonWithdrawable_FeeTokenWithdrawn): c.Cell { - return makeCellFrom(self, JettonWithdrawable_FeeTokenWithdrawn.store); - } -} - -/** - > type CrossChainAddress = slice - */ -export type CrossChainAddress = c.Slice - -export const CrossChainAddress = { - fromSlice(s: c.Slice): CrossChainAddress { - return invokeCustomUnpackFromSlice('CrossChainAddress', s); - }, - store(self: CrossChainAddress, b: c.Builder): void { - invokeCustomPackToBuilder('CrossChainAddress', self, b); - }, - toCell(self: CrossChainAddress): c.Cell { - return makeCellFrom(self, CrossChainAddress.store); - } -} - -/** - > struct CursedSubjects { - > data: map - > } - */ -export interface CursedSubjects { - readonly $: 'CursedSubjects' - data: Set /* = [] as map */ -} - -export const CursedSubjects = { - create(args: { - data: Set /* = [] as map */ - }): CursedSubjects { - return { - $: 'CursedSubjects', - ...args - } - }, - fromSlice(s: c.Slice): CursedSubjects { - return { - $: 'CursedSubjects', - data: dictToSet(c.Dictionary.load(c.Dictionary.Keys.BigUint(128), createDictionaryValue<[]>( - (s) => [], - (v,b) => { {} } - ), s)), - } - }, - store(self: CursedSubjects, b: c.Builder): void { - b.storeDict(setToDict(self.data, c.Dictionary.Keys.BigUint(128), createDictionaryValue<[]>( - (s) => [], - (v,b) => { {} } - )), c.Dictionary.Keys.BigUint(128), createDictionaryValue<[]>( - (s) => [], - (v,b) => { {} } - )); - }, - toCell(self: CursedSubjects): c.Cell { - return makeCellFrom(self, CursedSubjects.store); - } -} - -/** - > struct TokenPool_DynamicConfig { - > router: address - > rateLimitAdmin: address? - > feeAdmin: address? - > allowedDepositNamespaces: map - > } - */ -export interface TokenPool_DynamicConfig { - readonly $: 'TokenPool_DynamicConfig' - router: c.Address - rateLimitAdmin: c.Address | null /* = null */ - feeAdmin: c.Address | null - allowedDepositNamespaces: Set /* = [] as map */ -} - -export const TokenPool_DynamicConfig = { - create(args: { - router: c.Address - rateLimitAdmin?: c.Address | null /* = null */ - feeAdmin: c.Address | null - allowedDepositNamespaces: Set /* = [] as map */ - }): TokenPool_DynamicConfig { - return { - $: 'TokenPool_DynamicConfig', - rateLimitAdmin: null, - ...args - } - }, - fromSlice(s: c.Slice): TokenPool_DynamicConfig { - return { - $: 'TokenPool_DynamicConfig', - router: s.loadAddress(), - rateLimitAdmin: s.loadMaybeAddress(), - feeAdmin: s.loadMaybeAddress(), - allowedDepositNamespaces: dictToSet(c.Dictionary.load(c.Dictionary.Keys.BigUint(32), createDictionaryValue<[]>( - (s) => [], - (v,b) => { {} } - ), s)), - } - }, - store(self: TokenPool_DynamicConfig, b: c.Builder): void { - b.storeAddress(self.router); - b.storeAddress(self.rateLimitAdmin); - b.storeAddress(self.feeAdmin); - b.storeDict(setToDict(self.allowedDepositNamespaces, c.Dictionary.Keys.BigUint(32), createDictionaryValue<[]>( - (s) => [], - (v,b) => { {} } - )), c.Dictionary.Keys.BigUint(32), createDictionaryValue<[]>( - (s) => [], - (v,b) => { {} } - )); - }, - toCell(self: TokenPool_DynamicConfig): c.Cell { - return makeCellFrom(self, TokenPool_DynamicConfig.store); - } -} - -/** - > struct TokenPool_LocalPolicy { - > cursedSubjects: CursedSubjects - > } - */ -export interface TokenPool_LocalPolicy { - readonly $: 'TokenPool_LocalPolicy' - cursedSubjects: CursedSubjects -} - -export const TokenPool_LocalPolicy = { - create(args: { - cursedSubjects: CursedSubjects - }): TokenPool_LocalPolicy { - return { - $: 'TokenPool_LocalPolicy', - ...args - } - }, - fromSlice(s: c.Slice): TokenPool_LocalPolicy { - return { - $: 'TokenPool_LocalPolicy', - cursedSubjects: CursedSubjects.fromSlice(s), - } - }, - store(self: TokenPool_LocalPolicy, b: c.Builder): void { - CursedSubjects.store(self.cursedSubjects, b); - }, - toCell(self: TokenPool_LocalPolicy): c.Cell { - return makeCellFrom(self, TokenPool_LocalPolicy.store); - } -} - -/** - > struct TokenPool_RateLimiterPair { - > outbound: Cell - > inbound: Cell - > } - */ -export interface TokenPool_RateLimiterPair { - readonly $: 'TokenPool_RateLimiterPair' - outbound: RateLimiter_TokenBucket - inbound: RateLimiter_TokenBucket -} - -export const TokenPool_RateLimiterPair = { - create(args: { - outbound: RateLimiter_TokenBucket - inbound: RateLimiter_TokenBucket - }): TokenPool_RateLimiterPair { - return { - $: 'TokenPool_RateLimiterPair', - ...args - } - }, - fromSlice(s: c.Slice): TokenPool_RateLimiterPair { - return { - $: 'TokenPool_RateLimiterPair', - outbound: loadCellRef(s, RateLimiter_TokenBucket.fromSlice), - inbound: loadCellRef(s, RateLimiter_TokenBucket.fromSlice), - } - }, - store(self: TokenPool_RateLimiterPair, b: c.Builder): void { - storeCellRef(self.outbound, b, RateLimiter_TokenBucket.store); - storeCellRef(self.inbound, b, RateLimiter_TokenBucket.store); - }, - toCell(self: TokenPool_RateLimiterPair): c.Cell { - return makeCellFrom(self, TokenPool_RateLimiterPair.store); - } -} - -/** - > struct TokenPool_RateLimitConfigPair { - > outbound: Cell - > inbound: Cell - > } - */ -export interface TokenPool_RateLimitConfigPair { - readonly $: 'TokenPool_RateLimitConfigPair' - outbound: RateLimiter_Config - inbound: RateLimiter_Config -} - -export const TokenPool_RateLimitConfigPair = { - create(args: { - outbound: RateLimiter_Config - inbound: RateLimiter_Config - }): TokenPool_RateLimitConfigPair { - return { - $: 'TokenPool_RateLimitConfigPair', - ...args - } - }, - fromSlice(s: c.Slice): TokenPool_RateLimitConfigPair { - return { - $: 'TokenPool_RateLimitConfigPair', - outbound: loadCellRef(s, RateLimiter_Config.fromSlice), - inbound: loadCellRef(s, RateLimiter_Config.fromSlice), - } - }, - store(self: TokenPool_RateLimitConfigPair, b: c.Builder): void { - storeCellRef(self.outbound, b, RateLimiter_Config.store); - storeCellRef(self.inbound, b, RateLimiter_Config.store); - }, - toCell(self: TokenPool_RateLimitConfigPair): c.Cell { - return makeCellFrom(self, TokenPool_RateLimitConfigPair.store); - } -} - -/** - > struct TokenPool_ChainUpdate { - > remoteChainSelector: uint64 - > remotePoolAddresses: SnakedCell - > remoteTokenAddress: Cell - > rateLimitConfigs: Cell - > } - */ -export interface TokenPool_ChainUpdate { - readonly $: 'TokenPool_ChainUpdate' - remoteChainSelector: uint64 - remotePoolAddresses: SnakedCell - remoteTokenAddress: CrossChainAddress - rateLimitConfigs: TokenPool_RateLimitConfigPair -} - -export const TokenPool_ChainUpdate = { - create(args: { - remoteChainSelector: uint64 - remotePoolAddresses: SnakedCell - remoteTokenAddress: CrossChainAddress - rateLimitConfigs: TokenPool_RateLimitConfigPair - }): TokenPool_ChainUpdate { - return { - $: 'TokenPool_ChainUpdate', - ...args - } - }, - fromSlice(s: c.Slice): TokenPool_ChainUpdate { - return { - $: 'TokenPool_ChainUpdate', - remoteChainSelector: s.loadUintBig(64), - remotePoolAddresses: loadSnakedCellOf(s, CrossChainAddress.fromSlice), - remoteTokenAddress: loadCellRef(s, CrossChainAddress.fromSlice), - rateLimitConfigs: loadCellRef(s, TokenPool_RateLimitConfigPair.fromSlice), - } - }, - store(self: TokenPool_ChainUpdate, b: c.Builder): void { - b.storeUint(self.remoteChainSelector, 64); - storeSnakedCellOf(self.remotePoolAddresses, b, CrossChainAddress.store); - storeCellRef(self.remoteTokenAddress, b, CrossChainAddress.store); - storeCellRef(self.rateLimitConfigs, b, TokenPool_RateLimitConfigPair.store); - }, - toCell(self: TokenPool_ChainUpdate): c.Cell { - return makeCellFrom(self, TokenPool_ChainUpdate.store); - } -} - -/** - > struct TokenPool_RemoteChainConfig { - > remoteTokenAddress: Cell - > remotePools: map> - > rateLimiters: Cell - > fastFinalityRateLimiters: Cell - > } - */ -export interface TokenPool_RemoteChainConfig { - readonly $: 'TokenPool_RemoteChainConfig' - remoteTokenAddress: CrossChainAddress - remotePools: Map /* = [] as map> */ - rateLimiters: TokenPool_RateLimiterPair - fastFinalityRateLimiters: TokenPool_RateLimiterPair -} - -export const TokenPool_RemoteChainConfig = { - create(args: { - remoteTokenAddress: CrossChainAddress - remotePools: Map /* = [] as map> */ - rateLimiters: TokenPool_RateLimiterPair - fastFinalityRateLimiters: TokenPool_RateLimiterPair - }): TokenPool_RemoteChainConfig { - return { - $: 'TokenPool_RemoteChainConfig', - ...args - } - }, - fromSlice(s: c.Slice): TokenPool_RemoteChainConfig { - return { - $: 'TokenPool_RemoteChainConfig', - remoteTokenAddress: loadCellRef(s, CrossChainAddress.fromSlice), - remotePools: dictToMap(c.Dictionary.load(c.Dictionary.Keys.BigUint(256), createDictionaryValue( - (s) => loadCellRef(s, CrossChainAddress.fromSlice), - (v,b) => storeCellRef(v, b, CrossChainAddress.store) - ), s)), - rateLimiters: loadCellRef(s, TokenPool_RateLimiterPair.fromSlice), - fastFinalityRateLimiters: loadCellRef(s, TokenPool_RateLimiterPair.fromSlice), - } - }, - store(self: TokenPool_RemoteChainConfig, b: c.Builder): void { - storeCellRef(self.remoteTokenAddress, b, CrossChainAddress.store); - b.storeDict(mapToDict(self.remotePools, c.Dictionary.Keys.BigUint(256), createDictionaryValue( - (s) => loadCellRef(s, CrossChainAddress.fromSlice), - (v,b) => storeCellRef(v, b, CrossChainAddress.store) - )), c.Dictionary.Keys.BigUint(256), createDictionaryValue( - (s) => loadCellRef(s, CrossChainAddress.fromSlice), - (v,b) => storeCellRef(v, b, CrossChainAddress.store) - )); - storeCellRef(self.rateLimiters, b, TokenPool_RateLimiterPair.store); - storeCellRef(self.fastFinalityRateLimiters, b, TokenPool_RateLimiterPair.store); - }, - toCell(self: TokenPool_RemoteChainConfig): c.Cell { - return makeCellFrom(self, TokenPool_RemoteChainConfig.store); - } -} - -/** - > struct TokenPool_RateLimitConfigArgs { - > remoteChainSelector: uint64 - > fastFinality: bool - > outboundRateLimiterConfig: Cell - > inboundRateLimiterConfig: Cell - > } - */ -export interface TokenPool_RateLimitConfigArgs { - readonly $: 'TokenPool_RateLimitConfigArgs' - remoteChainSelector: uint64 - fastFinality: boolean - outboundRateLimiterConfig: RateLimiter_Config - inboundRateLimiterConfig: RateLimiter_Config -} - -export const TokenPool_RateLimitConfigArgs = { - create(args: { - remoteChainSelector: uint64 - fastFinality: boolean - outboundRateLimiterConfig: RateLimiter_Config - inboundRateLimiterConfig: RateLimiter_Config - }): TokenPool_RateLimitConfigArgs { - return { - $: 'TokenPool_RateLimitConfigArgs', - ...args - } - }, - fromSlice(s: c.Slice): TokenPool_RateLimitConfigArgs { - return { - $: 'TokenPool_RateLimitConfigArgs', - remoteChainSelector: s.loadUintBig(64), - fastFinality: s.loadBoolean(), - outboundRateLimiterConfig: loadCellRef(s, RateLimiter_Config.fromSlice), - inboundRateLimiterConfig: loadCellRef(s, RateLimiter_Config.fromSlice), - } - }, - store(self: TokenPool_RateLimitConfigArgs, b: c.Builder): void { - b.storeUint(self.remoteChainSelector, 64); - b.storeBit(self.fastFinality); - storeCellRef(self.outboundRateLimiterConfig, b, RateLimiter_Config.store); - storeCellRef(self.inboundRateLimiterConfig, b, RateLimiter_Config.store); - }, - toCell(self: TokenPool_RateLimitConfigArgs): c.Cell { - return makeCellFrom(self, TokenPool_RateLimitConfigArgs.store); - } -} - -/** - > struct TokenPool_TokenTransferFeeConfigArgs { - > destChainSelector: uint64 - > tokenTransferFeeConfig: TokenPool_TokenTransferFeeConfig - > } - */ -export interface TokenPool_TokenTransferFeeConfigArgs { - readonly $: 'TokenPool_TokenTransferFeeConfigArgs' - destChainSelector: uint64 - tokenTransferFeeConfig: TokenPool_TokenTransferFeeConfig -} - -export const TokenPool_TokenTransferFeeConfigArgs = { - create(args: { - destChainSelector: uint64 - tokenTransferFeeConfig: TokenPool_TokenTransferFeeConfig - }): TokenPool_TokenTransferFeeConfigArgs { - return { - $: 'TokenPool_TokenTransferFeeConfigArgs', - ...args - } - }, - fromSlice(s: c.Slice): TokenPool_TokenTransferFeeConfigArgs { - return { - $: 'TokenPool_TokenTransferFeeConfigArgs', - destChainSelector: s.loadUintBig(64), - tokenTransferFeeConfig: TokenPool_TokenTransferFeeConfig.fromSlice(s), - } - }, - store(self: TokenPool_TokenTransferFeeConfigArgs, b: c.Builder): void { - b.storeUint(self.destChainSelector, 64); - TokenPool_TokenTransferFeeConfig.store(self.tokenTransferFeeConfig, b); - }, - toCell(self: TokenPool_TokenTransferFeeConfigArgs): c.Cell { - return makeCellFrom(self, TokenPool_TokenTransferFeeConfigArgs.store); - } -} - -/** - > struct TokenPool_LockOrBurnPrepared { - > feeAmount: coins - > destTokenAmount: coins - > out: TokenPool_LockOrBurnOutV1 - > } - */ -export interface TokenPool_LockOrBurnPrepared { - readonly $: 'TokenPool_LockOrBurnPrepared' - feeAmount: coins - destTokenAmount: coins - out: TokenPool_LockOrBurnOutV1 -} - -export const TokenPool_LockOrBurnPrepared = { - create(args: { - feeAmount: coins - destTokenAmount: coins - out: TokenPool_LockOrBurnOutV1 - }): TokenPool_LockOrBurnPrepared { - return { - $: 'TokenPool_LockOrBurnPrepared', - ...args - } - }, - fromSlice(s: c.Slice): TokenPool_LockOrBurnPrepared { - return { - $: 'TokenPool_LockOrBurnPrepared', - feeAmount: s.loadCoins(), - destTokenAmount: s.loadCoins(), - out: TokenPool_LockOrBurnOutV1.fromSlice(s), - } - }, - store(self: TokenPool_LockOrBurnPrepared, b: c.Builder): void { - b.storeCoins(self.feeAmount); - b.storeCoins(self.destTokenAmount); - TokenPool_LockOrBurnOutV1.store(self.out, b); - }, - toCell(self: TokenPool_LockOrBurnPrepared): c.Cell { - return makeCellFrom(self, TokenPool_LockOrBurnPrepared.store); - } -} - -/** - > struct TokenPool_ReleaseOrMintPrepared { - > requestedFinalityConfig: uint32 - > localAmount: coins - > out: TokenPool_ReleaseOrMintOutV1 - > } - */ -export interface TokenPool_ReleaseOrMintPrepared { - readonly $: 'TokenPool_ReleaseOrMintPrepared' - requestedFinalityConfig: uint32 - localAmount: coins - out: TokenPool_ReleaseOrMintOutV1 -} - -export const TokenPool_ReleaseOrMintPrepared = { - create(args: { - requestedFinalityConfig: uint32 - localAmount: coins - out: TokenPool_ReleaseOrMintOutV1 - }): TokenPool_ReleaseOrMintPrepared { - return { - $: 'TokenPool_ReleaseOrMintPrepared', - ...args - } - }, - fromSlice(s: c.Slice): TokenPool_ReleaseOrMintPrepared { - return { - $: 'TokenPool_ReleaseOrMintPrepared', - requestedFinalityConfig: s.loadUintBig(32), - localAmount: s.loadCoins(), - out: TokenPool_ReleaseOrMintOutV1.fromSlice(s), - } - }, - store(self: TokenPool_ReleaseOrMintPrepared, b: c.Builder): void { - b.storeUint(self.requestedFinalityConfig, 32); - b.storeCoins(self.localAmount); - TokenPool_ReleaseOrMintOutV1.store(self.out, b); - }, - toCell(self: TokenPool_ReleaseOrMintPrepared): c.Cell { - return makeCellFrom(self, TokenPool_ReleaseOrMintPrepared.store); - } -} - -/** - > struct TokenPool_TokenTransferFeeConfig { - > destGasOverhead: uint32 - > destBytesOverhead: uint32 - > finalityFeeUSDCents: coins - > fastFinalityFeeUSDCents: coins - > finalityTransferFeeBps: uint16 - > fastFinalityTransferFeeBps: uint16 - > isEnabled: bool - > } - */ -export interface TokenPool_TokenTransferFeeConfig { - readonly $: 'TokenPool_TokenTransferFeeConfig' - destGasOverhead: uint32 - destBytesOverhead: uint32 - finalityFeeUSDCents: coins - fastFinalityFeeUSDCents: coins - finalityTransferFeeBps: uint16 - fastFinalityTransferFeeBps: uint16 - isEnabled: boolean -} - -export const TokenPool_TokenTransferFeeConfig = { - create(args: { - destGasOverhead: uint32 - destBytesOverhead: uint32 - finalityFeeUSDCents: coins - fastFinalityFeeUSDCents: coins - finalityTransferFeeBps: uint16 - fastFinalityTransferFeeBps: uint16 - isEnabled: boolean - }): TokenPool_TokenTransferFeeConfig { - return { - $: 'TokenPool_TokenTransferFeeConfig', - ...args - } - }, - fromSlice(s: c.Slice): TokenPool_TokenTransferFeeConfig { - return { - $: 'TokenPool_TokenTransferFeeConfig', - destGasOverhead: s.loadUintBig(32), - destBytesOverhead: s.loadUintBig(32), - finalityFeeUSDCents: s.loadCoins(), - fastFinalityFeeUSDCents: s.loadCoins(), - finalityTransferFeeBps: s.loadUintBig(16), - fastFinalityTransferFeeBps: s.loadUintBig(16), - isEnabled: s.loadBoolean(), - } - }, - store(self: TokenPool_TokenTransferFeeConfig, b: c.Builder): void { - b.storeUint(self.destGasOverhead, 32); - b.storeUint(self.destBytesOverhead, 32); - b.storeCoins(self.finalityFeeUSDCents); - b.storeCoins(self.fastFinalityFeeUSDCents); - b.storeUint(self.finalityTransferFeeBps, 16); - b.storeUint(self.fastFinalityTransferFeeBps, 16); - b.storeBit(self.isEnabled); - }, - toCell(self: TokenPool_TokenTransferFeeConfig): c.Cell { - return makeCellFrom(self, TokenPool_TokenTransferFeeConfig.store); - } -} - -/** - > struct TokenPool_Transfer { - > id: uint256 - > details: Cell> - > } - */ -export interface TokenPool_Transfer { - readonly $: 'TokenPool_Transfer' - id: uint256 - details: TokenPool_TransferDetails -} - -export const TokenPool_Transfer = { - create(args: { - id: uint256 - details: TokenPool_TransferDetails - }): TokenPool_Transfer { - return { - $: 'TokenPool_Transfer', - ...args - } - }, -} - -/** - > struct TokenPool_TransferDetails { - > receiver: R - > remoteChainSelector: uint64 - > originalSender: S - > amount: C - > localToken: address - > } - */ -export interface TokenPool_TransferDetails { - readonly $: 'TokenPool_TransferDetails' - receiver: R - remoteChainSelector: uint64 - originalSender: S - amount: C - localToken: c.Address -} - -export const TokenPool_TransferDetails = { - create(args: { - receiver: R - remoteChainSelector: uint64 - originalSender: S - amount: C - localToken: c.Address - }): TokenPool_TransferDetails { - return { - $: 'TokenPool_TransferDetails', - ...args - } - }, -} - -/** - > type TokenPool_LockOrBurnTransfer = TokenPool_Transfer, coins> - */ -export type TokenPool_LockOrBurnTransfer = TokenPool_Transfer - -export const TokenPool_LockOrBurnTransfer = { - fromSlice(s: c.Slice): TokenPool_LockOrBurnTransfer { - return (() => { - return { - $: 'TokenPool_Transfer', - id: s.loadUintBig(256), - details: loadCellRef>(s, - (s) => (() => { - return { - $: 'TokenPool_TransferDetails', - receiver: loadCellRef(s, CrossChainAddress.fromSlice), - remoteChainSelector: s.loadUintBig(64), - originalSender: s.loadAddress(), - amount: s.loadCoins(), - localToken: s.loadAddress(), - } - })() - ), - } - })(); - }, - store(self: TokenPool_LockOrBurnTransfer, b: c.Builder): void { - b.storeUint(self.id, 256); - storeCellRef>(self.details, b, - (v,b) => { storeCellRef(v.receiver, b, CrossChainAddress.store); - b.storeUint(v.remoteChainSelector, 64); - b.storeAddress(v.originalSender); - b.storeCoins(v.amount); - b.storeAddress(v.localToken); } - ); - }, - toCell(self: TokenPool_LockOrBurnTransfer): c.Cell { - return makeCellFrom(self, TokenPool_LockOrBurnTransfer.store); - } -} - -/** - > type TokenPool_ReleaseOrMintTransfer = TokenPool_Transfer, address, uint256> - */ -export type TokenPool_ReleaseOrMintTransfer = TokenPool_Transfer - -export const TokenPool_ReleaseOrMintTransfer = { - fromSlice(s: c.Slice): TokenPool_ReleaseOrMintTransfer { - return (() => { - return { - $: 'TokenPool_Transfer', - id: s.loadUintBig(256), - details: loadCellRef>(s, - (s) => (() => { - return { - $: 'TokenPool_TransferDetails', - receiver: s.loadAddress(), - remoteChainSelector: s.loadUintBig(64), - originalSender: loadCellRef(s, CrossChainAddress.fromSlice), - amount: s.loadUintBig(256), - localToken: s.loadAddress(), - } - })() - ), - } - })(); - }, - store(self: TokenPool_ReleaseOrMintTransfer, b: c.Builder): void { - b.storeUint(self.id, 256); - storeCellRef>(self.details, b, - (v,b) => { b.storeAddress(v.receiver); - b.storeUint(v.remoteChainSelector, 64); - storeCellRef(v.originalSender, b, CrossChainAddress.store); - b.storeUint(v.amount, 256); - b.storeAddress(v.localToken); } - ); - }, - toCell(self: TokenPool_ReleaseOrMintTransfer): c.Cell { - return makeCellFrom(self, TokenPool_ReleaseOrMintTransfer.store); - } -} - -/** - > struct TokenPool_LockOrBurnInV1 { - > transfer: TokenPool_LockOrBurnTransfer - > } - */ -export interface TokenPool_LockOrBurnInV1 { - readonly $: 'TokenPool_LockOrBurnInV1' - transfer: TokenPool_LockOrBurnTransfer -} - -export const TokenPool_LockOrBurnInV1 = { - create(args: { - transfer: TokenPool_LockOrBurnTransfer - }): TokenPool_LockOrBurnInV1 { - return { - $: 'TokenPool_LockOrBurnInV1', - ...args - } - }, - fromSlice(s: c.Slice): TokenPool_LockOrBurnInV1 { - return { - $: 'TokenPool_LockOrBurnInV1', - transfer: TokenPool_LockOrBurnTransfer.fromSlice(s), - } - }, - store(self: TokenPool_LockOrBurnInV1, b: c.Builder): void { - TokenPool_LockOrBurnTransfer.store(self.transfer, b); - }, - toCell(self: TokenPool_LockOrBurnInV1): c.Cell { - return makeCellFrom(self, TokenPool_LockOrBurnInV1.store); - } -} - -/** - > struct TokenPool_LockOrBurnOutV1 { - > destTokenAddress: Cell - > destPoolData: cell - > } - */ -export interface TokenPool_LockOrBurnOutV1 { - readonly $: 'TokenPool_LockOrBurnOutV1' - destTokenAddress: CrossChainAddress - destPoolData: c.Cell -} - -export const TokenPool_LockOrBurnOutV1 = { - create(args: { - destTokenAddress: CrossChainAddress - destPoolData: c.Cell - }): TokenPool_LockOrBurnOutV1 { - return { - $: 'TokenPool_LockOrBurnOutV1', - ...args - } - }, - fromSlice(s: c.Slice): TokenPool_LockOrBurnOutV1 { - return { - $: 'TokenPool_LockOrBurnOutV1', - destTokenAddress: loadCellRef(s, CrossChainAddress.fromSlice), - destPoolData: s.loadRef(), - } - }, - store(self: TokenPool_LockOrBurnOutV1, b: c.Builder): void { - storeCellRef(self.destTokenAddress, b, CrossChainAddress.store); - b.storeRef(self.destPoolData); - }, - toCell(self: TokenPool_LockOrBurnOutV1): c.Cell { - return makeCellFrom(self, TokenPool_LockOrBurnOutV1.store); - } -} - -/** - > struct TokenPool_ReleaseOrMintInV1 { - > transfer: TokenPool_ReleaseOrMintTransfer - > sourcePoolAddress: Cell - > sourcePoolData: cell? - > offchainTokenData: cell? - > } - */ -export interface TokenPool_ReleaseOrMintInV1 { - readonly $: 'TokenPool_ReleaseOrMintInV1' - transfer: TokenPool_ReleaseOrMintTransfer - sourcePoolAddress: CrossChainAddress - sourcePoolData: c.Cell | null - offchainTokenData: c.Cell | null -} - -export const TokenPool_ReleaseOrMintInV1 = { - create(args: { - transfer: TokenPool_ReleaseOrMintTransfer - sourcePoolAddress: CrossChainAddress - sourcePoolData: c.Cell | null - offchainTokenData: c.Cell | null - }): TokenPool_ReleaseOrMintInV1 { - return { - $: 'TokenPool_ReleaseOrMintInV1', - ...args - } - }, - fromSlice(s: c.Slice): TokenPool_ReleaseOrMintInV1 { - return { - $: 'TokenPool_ReleaseOrMintInV1', - transfer: TokenPool_ReleaseOrMintTransfer.fromSlice(s), - sourcePoolAddress: loadCellRef(s, CrossChainAddress.fromSlice), - sourcePoolData: s.loadBoolean() ? s.loadRef() : null, - offchainTokenData: s.loadBoolean() ? s.loadRef() : null, - } - }, - store(self: TokenPool_ReleaseOrMintInV1, b: c.Builder): void { - TokenPool_ReleaseOrMintTransfer.store(self.transfer, b); - storeCellRef(self.sourcePoolAddress, b, CrossChainAddress.store); - storeTolkNullable(self.sourcePoolData, b, - (v,b) => b.storeRef(v) - ); - storeTolkNullable(self.offchainTokenData, b, - (v,b) => b.storeRef(v) - ); - }, - toCell(self: TokenPool_ReleaseOrMintInV1): c.Cell { - return makeCellFrom(self, TokenPool_ReleaseOrMintInV1.store); - } -} - -/** - > struct TokenPool_ReleaseOrMintOutV1 { - > destinationAmount: coins - > } - */ -export interface TokenPool_ReleaseOrMintOutV1 { - readonly $: 'TokenPool_ReleaseOrMintOutV1' - destinationAmount: coins -} - -export const TokenPool_ReleaseOrMintOutV1 = { - create(args: { - destinationAmount: coins - }): TokenPool_ReleaseOrMintOutV1 { - return { - $: 'TokenPool_ReleaseOrMintOutV1', - ...args - } - }, - fromSlice(s: c.Slice): TokenPool_ReleaseOrMintOutV1 { - return { - $: 'TokenPool_ReleaseOrMintOutV1', - destinationAmount: s.loadCoins(), - } - }, - store(self: TokenPool_ReleaseOrMintOutV1, b: c.Builder): void { - b.storeCoins(self.destinationAmount); - }, - toCell(self: TokenPool_ReleaseOrMintOutV1): c.Cell { - return makeCellFrom(self, TokenPool_ReleaseOrMintOutV1.store); - } -} - -/** - > struct TokenPool_LockedOrBurned { - > remoteChainSelector: uint64 - > details: Cell - > } - */ -export interface TokenPool_LockedOrBurned { - readonly $: 'TokenPool_LockedOrBurned' - remoteChainSelector: uint64 - details: TokenPool_LockedOrBurnedDetails -} - -export const TokenPool_LockedOrBurned = { - create(args: { - remoteChainSelector: uint64 - details: TokenPool_LockedOrBurnedDetails - }): TokenPool_LockedOrBurned { - return { - $: 'TokenPool_LockedOrBurned', - ...args - } - }, - fromSlice(s: c.Slice): TokenPool_LockedOrBurned { - return { - $: 'TokenPool_LockedOrBurned', - remoteChainSelector: s.loadUintBig(64), - details: loadCellRef(s, TokenPool_LockedOrBurnedDetails.fromSlice), - } - }, - store(self: TokenPool_LockedOrBurned, b: c.Builder): void { - b.storeUint(self.remoteChainSelector, 64); - storeCellRef(self.details, b, TokenPool_LockedOrBurnedDetails.store); - }, - toCell(self: TokenPool_LockedOrBurned): c.Cell { - return makeCellFrom(self, TokenPool_LockedOrBurned.store); - } -} - -/** - > struct TokenPool_LockedOrBurnedDetails { - > token: address - > sender: address - > amount: coins - > } - */ -export interface TokenPool_LockedOrBurnedDetails { - readonly $: 'TokenPool_LockedOrBurnedDetails' - token: c.Address - sender: c.Address - amount: coins -} - -export const TokenPool_LockedOrBurnedDetails = { - create(args: { - token: c.Address - sender: c.Address - amount: coins - }): TokenPool_LockedOrBurnedDetails { - return { - $: 'TokenPool_LockedOrBurnedDetails', - ...args - } - }, - fromSlice(s: c.Slice): TokenPool_LockedOrBurnedDetails { - return { - $: 'TokenPool_LockedOrBurnedDetails', - token: s.loadAddress(), - sender: s.loadAddress(), - amount: s.loadCoins(), - } - }, - store(self: TokenPool_LockedOrBurnedDetails, b: c.Builder): void { - b.storeAddress(self.token); - b.storeAddress(self.sender); - b.storeCoins(self.amount); - }, - toCell(self: TokenPool_LockedOrBurnedDetails): c.Cell { - return makeCellFrom(self, TokenPool_LockedOrBurnedDetails.store); - } -} - -/** - > struct TokenPool_ReleasedOrMinted { - > remoteChainSelector: uint64 - > details: Cell - > } - */ -export interface TokenPool_ReleasedOrMinted { - readonly $: 'TokenPool_ReleasedOrMinted' - remoteChainSelector: uint64 - details: TokenPool_ReleasedOrMintedDetails -} - -export const TokenPool_ReleasedOrMinted = { - create(args: { - remoteChainSelector: uint64 - details: TokenPool_ReleasedOrMintedDetails - }): TokenPool_ReleasedOrMinted { - return { - $: 'TokenPool_ReleasedOrMinted', - ...args - } - }, - fromSlice(s: c.Slice): TokenPool_ReleasedOrMinted { - return { - $: 'TokenPool_ReleasedOrMinted', - remoteChainSelector: s.loadUintBig(64), - details: loadCellRef(s, TokenPool_ReleasedOrMintedDetails.fromSlice), - } - }, - store(self: TokenPool_ReleasedOrMinted, b: c.Builder): void { - b.storeUint(self.remoteChainSelector, 64); - storeCellRef(self.details, b, TokenPool_ReleasedOrMintedDetails.store); - }, - toCell(self: TokenPool_ReleasedOrMinted): c.Cell { - return makeCellFrom(self, TokenPool_ReleasedOrMinted.store); - } -} - -/** - > struct TokenPool_ReleasedOrMintedDetails { - > token: address - > sender: address - > amount: coins - > recipient: Cell
- > } - */ -export interface TokenPool_ReleasedOrMintedDetails { - readonly $: 'TokenPool_ReleasedOrMintedDetails' - token: c.Address - sender: c.Address - amount: coins - recipient: c.Address -} - -export const TokenPool_ReleasedOrMintedDetails = { - create(args: { - token: c.Address - sender: c.Address - amount: coins - recipient: c.Address - }): TokenPool_ReleasedOrMintedDetails { - return { - $: 'TokenPool_ReleasedOrMintedDetails', - ...args - } - }, - fromSlice(s: c.Slice): TokenPool_ReleasedOrMintedDetails { - return { - $: 'TokenPool_ReleasedOrMintedDetails', - token: s.loadAddress(), - sender: s.loadAddress(), - amount: s.loadCoins(), - recipient: loadCellRef(s, - (s) => s.loadAddress() - ), - } - }, - store(self: TokenPool_ReleasedOrMintedDetails, b: c.Builder): void { - b.storeAddress(self.token); - b.storeAddress(self.sender); - b.storeCoins(self.amount); - storeCellRef(self.recipient, b, - (v,b) => b.storeAddress(v) - ); - }, - toCell(self: TokenPool_ReleasedOrMintedDetails): c.Cell { - return makeCellFrom(self, TokenPool_ReleasedOrMintedDetails.store); - } -} - -/** - > struct TokenPool_ChainAdded { - > remoteChainSelector: uint64 - > remoteTokenAddress: Cell - > } - */ -export interface TokenPool_ChainAdded { - readonly $: 'TokenPool_ChainAdded' - remoteChainSelector: uint64 - remoteTokenAddress: CrossChainAddress -} - -export const TokenPool_ChainAdded = { - create(args: { - remoteChainSelector: uint64 - remoteTokenAddress: CrossChainAddress - }): TokenPool_ChainAdded { - return { - $: 'TokenPool_ChainAdded', - ...args - } - }, - fromSlice(s: c.Slice): TokenPool_ChainAdded { - return { - $: 'TokenPool_ChainAdded', - remoteChainSelector: s.loadUintBig(64), - remoteTokenAddress: loadCellRef(s, CrossChainAddress.fromSlice), - } - }, - store(self: TokenPool_ChainAdded, b: c.Builder): void { - b.storeUint(self.remoteChainSelector, 64); - storeCellRef(self.remoteTokenAddress, b, CrossChainAddress.store); - }, - toCell(self: TokenPool_ChainAdded): c.Cell { - return makeCellFrom(self, TokenPool_ChainAdded.store); - } -} - -/** - > struct TokenPool_ChainRemoved { - > remoteChainSelector: uint64 - > } - */ -export interface TokenPool_ChainRemoved { - readonly $: 'TokenPool_ChainRemoved' - remoteChainSelector: uint64 -} - -export const TokenPool_ChainRemoved = { - create(args: { - remoteChainSelector: uint64 - }): TokenPool_ChainRemoved { - return { - $: 'TokenPool_ChainRemoved', - ...args - } - }, - fromSlice(s: c.Slice): TokenPool_ChainRemoved { - return { - $: 'TokenPool_ChainRemoved', - remoteChainSelector: s.loadUintBig(64), - } - }, - store(self: TokenPool_ChainRemoved, b: c.Builder): void { - b.storeUint(self.remoteChainSelector, 64); - }, - toCell(self: TokenPool_ChainRemoved): c.Cell { - return makeCellFrom(self, TokenPool_ChainRemoved.store); - } -} - -/** - > struct TokenPool_RemotePoolAdded { - > remoteChainSelector: uint64 - > remotePoolAddress: Cell - > } - */ -export interface TokenPool_RemotePoolAdded { - readonly $: 'TokenPool_RemotePoolAdded' - remoteChainSelector: uint64 - remotePoolAddress: CrossChainAddress -} - -export const TokenPool_RemotePoolAdded = { - create(args: { - remoteChainSelector: uint64 - remotePoolAddress: CrossChainAddress - }): TokenPool_RemotePoolAdded { - return { - $: 'TokenPool_RemotePoolAdded', - ...args - } - }, - fromSlice(s: c.Slice): TokenPool_RemotePoolAdded { - return { - $: 'TokenPool_RemotePoolAdded', - remoteChainSelector: s.loadUintBig(64), - remotePoolAddress: loadCellRef(s, CrossChainAddress.fromSlice), - } - }, - store(self: TokenPool_RemotePoolAdded, b: c.Builder): void { - b.storeUint(self.remoteChainSelector, 64); - storeCellRef(self.remotePoolAddress, b, CrossChainAddress.store); - }, - toCell(self: TokenPool_RemotePoolAdded): c.Cell { - return makeCellFrom(self, TokenPool_RemotePoolAdded.store); - } -} - -/** - > struct TokenPool_RemotePoolRemoved { - > remoteChainSelector: uint64 - > remotePoolAddress: Cell - > } - */ -export interface TokenPool_RemotePoolRemoved { - readonly $: 'TokenPool_RemotePoolRemoved' - remoteChainSelector: uint64 - remotePoolAddress: CrossChainAddress -} - -export const TokenPool_RemotePoolRemoved = { - create(args: { - remoteChainSelector: uint64 - remotePoolAddress: CrossChainAddress - }): TokenPool_RemotePoolRemoved { - return { - $: 'TokenPool_RemotePoolRemoved', - ...args - } - }, - fromSlice(s: c.Slice): TokenPool_RemotePoolRemoved { - return { - $: 'TokenPool_RemotePoolRemoved', - remoteChainSelector: s.loadUintBig(64), - remotePoolAddress: loadCellRef(s, CrossChainAddress.fromSlice), - } - }, - store(self: TokenPool_RemotePoolRemoved, b: c.Builder): void { - b.storeUint(self.remoteChainSelector, 64); - storeCellRef(self.remotePoolAddress, b, CrossChainAddress.store); - }, - toCell(self: TokenPool_RemotePoolRemoved): c.Cell { - return makeCellFrom(self, TokenPool_RemotePoolRemoved.store); - } -} - -/** - > struct TokenPool_OutboundRateLimitConsumed { - > remoteChainSelector: uint64 - > token: address - > amount: coins - > } - */ -export interface TokenPool_OutboundRateLimitConsumed { - readonly $: 'TokenPool_OutboundRateLimitConsumed' - remoteChainSelector: uint64 - token: c.Address - amount: coins -} - -export const TokenPool_OutboundRateLimitConsumed = { - create(args: { - remoteChainSelector: uint64 - token: c.Address - amount: coins - }): TokenPool_OutboundRateLimitConsumed { - return { - $: 'TokenPool_OutboundRateLimitConsumed', - ...args - } - }, - fromSlice(s: c.Slice): TokenPool_OutboundRateLimitConsumed { - return { - $: 'TokenPool_OutboundRateLimitConsumed', - remoteChainSelector: s.loadUintBig(64), - token: s.loadAddress(), - amount: s.loadCoins(), - } - }, - store(self: TokenPool_OutboundRateLimitConsumed, b: c.Builder): void { - b.storeUint(self.remoteChainSelector, 64); - b.storeAddress(self.token); - b.storeCoins(self.amount); - }, - toCell(self: TokenPool_OutboundRateLimitConsumed): c.Cell { - return makeCellFrom(self, TokenPool_OutboundRateLimitConsumed.store); - } -} - -/** - > struct TokenPool_InboundRateLimitConsumed { - > remoteChainSelector: uint64 - > token: address - > amount: coins - > } - */ -export interface TokenPool_InboundRateLimitConsumed { - readonly $: 'TokenPool_InboundRateLimitConsumed' - remoteChainSelector: uint64 - token: c.Address - amount: coins -} - -export const TokenPool_InboundRateLimitConsumed = { - create(args: { - remoteChainSelector: uint64 - token: c.Address - amount: coins - }): TokenPool_InboundRateLimitConsumed { - return { - $: 'TokenPool_InboundRateLimitConsumed', - ...args - } - }, - fromSlice(s: c.Slice): TokenPool_InboundRateLimitConsumed { - return { - $: 'TokenPool_InboundRateLimitConsumed', - remoteChainSelector: s.loadUintBig(64), - token: s.loadAddress(), - amount: s.loadCoins(), - } - }, - store(self: TokenPool_InboundRateLimitConsumed, b: c.Builder): void { - b.storeUint(self.remoteChainSelector, 64); - b.storeAddress(self.token); - b.storeCoins(self.amount); - }, - toCell(self: TokenPool_InboundRateLimitConsumed): c.Cell { - return makeCellFrom(self, TokenPool_InboundRateLimitConsumed.store); - } -} - -/** - > struct TokenPool_FastFinalityOutboundRateLimitConsumed { - > remoteChainSelector: uint64 - > token: address - > amount: coins - > } - */ -export interface TokenPool_FastFinalityOutboundRateLimitConsumed { - readonly $: 'TokenPool_FastFinalityOutboundRateLimitConsumed' - remoteChainSelector: uint64 - token: c.Address - amount: coins -} - -export const TokenPool_FastFinalityOutboundRateLimitConsumed = { - create(args: { - remoteChainSelector: uint64 - token: c.Address - amount: coins - }): TokenPool_FastFinalityOutboundRateLimitConsumed { - return { - $: 'TokenPool_FastFinalityOutboundRateLimitConsumed', - ...args - } - }, - fromSlice(s: c.Slice): TokenPool_FastFinalityOutboundRateLimitConsumed { - return { - $: 'TokenPool_FastFinalityOutboundRateLimitConsumed', - remoteChainSelector: s.loadUintBig(64), - token: s.loadAddress(), - amount: s.loadCoins(), - } - }, - store(self: TokenPool_FastFinalityOutboundRateLimitConsumed, b: c.Builder): void { - b.storeUint(self.remoteChainSelector, 64); - b.storeAddress(self.token); - b.storeCoins(self.amount); - }, - toCell(self: TokenPool_FastFinalityOutboundRateLimitConsumed): c.Cell { - return makeCellFrom(self, TokenPool_FastFinalityOutboundRateLimitConsumed.store); - } -} - -/** - > struct TokenPool_FastFinalityInboundRateLimitConsumed { - > remoteChainSelector: uint64 - > token: address - > amount: coins - > } - */ -export interface TokenPool_FastFinalityInboundRateLimitConsumed { - readonly $: 'TokenPool_FastFinalityInboundRateLimitConsumed' - remoteChainSelector: uint64 - token: c.Address - amount: coins -} - -export const TokenPool_FastFinalityInboundRateLimitConsumed = { - create(args: { - remoteChainSelector: uint64 - token: c.Address - amount: coins - }): TokenPool_FastFinalityInboundRateLimitConsumed { - return { - $: 'TokenPool_FastFinalityInboundRateLimitConsumed', - ...args - } - }, - fromSlice(s: c.Slice): TokenPool_FastFinalityInboundRateLimitConsumed { - return { - $: 'TokenPool_FastFinalityInboundRateLimitConsumed', - remoteChainSelector: s.loadUintBig(64), - token: s.loadAddress(), - amount: s.loadCoins(), - } - }, - store(self: TokenPool_FastFinalityInboundRateLimitConsumed, b: c.Builder): void { - b.storeUint(self.remoteChainSelector, 64); - b.storeAddress(self.token); - b.storeCoins(self.amount); - }, - toCell(self: TokenPool_FastFinalityInboundRateLimitConsumed): c.Cell { - return makeCellFrom(self, TokenPool_FastFinalityInboundRateLimitConsumed.store); - } -} - -/** - > struct TokenPool_OutboundRateLimitRefunded { - > remoteChainSelector: uint64 - > token: address - > amount: coins - > } - */ -export interface TokenPool_OutboundRateLimitRefunded { - readonly $: 'TokenPool_OutboundRateLimitRefunded' - remoteChainSelector: uint64 - token: c.Address - amount: coins -} - -export const TokenPool_OutboundRateLimitRefunded = { - create(args: { - remoteChainSelector: uint64 - token: c.Address - amount: coins - }): TokenPool_OutboundRateLimitRefunded { - return { - $: 'TokenPool_OutboundRateLimitRefunded', - ...args - } - }, - fromSlice(s: c.Slice): TokenPool_OutboundRateLimitRefunded { - return { - $: 'TokenPool_OutboundRateLimitRefunded', - remoteChainSelector: s.loadUintBig(64), - token: s.loadAddress(), - amount: s.loadCoins(), - } - }, - store(self: TokenPool_OutboundRateLimitRefunded, b: c.Builder): void { - b.storeUint(self.remoteChainSelector, 64); - b.storeAddress(self.token); - b.storeCoins(self.amount); - }, - toCell(self: TokenPool_OutboundRateLimitRefunded): c.Cell { - return makeCellFrom(self, TokenPool_OutboundRateLimitRefunded.store); - } -} - -/** - > struct TokenPool_InboundRateLimitRefunded { - > remoteChainSelector: uint64 - > token: address - > amount: coins - > } - */ -export interface TokenPool_InboundRateLimitRefunded { - readonly $: 'TokenPool_InboundRateLimitRefunded' - remoteChainSelector: uint64 - token: c.Address - amount: coins -} - -export const TokenPool_InboundRateLimitRefunded = { - create(args: { - remoteChainSelector: uint64 - token: c.Address - amount: coins - }): TokenPool_InboundRateLimitRefunded { - return { - $: 'TokenPool_InboundRateLimitRefunded', - ...args - } - }, - fromSlice(s: c.Slice): TokenPool_InboundRateLimitRefunded { - return { - $: 'TokenPool_InboundRateLimitRefunded', - remoteChainSelector: s.loadUintBig(64), - token: s.loadAddress(), - amount: s.loadCoins(), - } - }, - store(self: TokenPool_InboundRateLimitRefunded, b: c.Builder): void { - b.storeUint(self.remoteChainSelector, 64); - b.storeAddress(self.token); - b.storeCoins(self.amount); - }, - toCell(self: TokenPool_InboundRateLimitRefunded): c.Cell { - return makeCellFrom(self, TokenPool_InboundRateLimitRefunded.store); - } -} - -/** - > struct TokenPool_FastFinalityOutboundRateLimitRefunded { - > remoteChainSelector: uint64 - > token: address - > amount: coins - > } - */ -export interface TokenPool_FastFinalityOutboundRateLimitRefunded { - readonly $: 'TokenPool_FastFinalityOutboundRateLimitRefunded' - remoteChainSelector: uint64 - token: c.Address - amount: coins -} - -export const TokenPool_FastFinalityOutboundRateLimitRefunded = { - create(args: { - remoteChainSelector: uint64 - token: c.Address - amount: coins - }): TokenPool_FastFinalityOutboundRateLimitRefunded { - return { - $: 'TokenPool_FastFinalityOutboundRateLimitRefunded', - ...args - } - }, - fromSlice(s: c.Slice): TokenPool_FastFinalityOutboundRateLimitRefunded { - return { - $: 'TokenPool_FastFinalityOutboundRateLimitRefunded', - remoteChainSelector: s.loadUintBig(64), - token: s.loadAddress(), - amount: s.loadCoins(), - } - }, - store(self: TokenPool_FastFinalityOutboundRateLimitRefunded, b: c.Builder): void { - b.storeUint(self.remoteChainSelector, 64); - b.storeAddress(self.token); - b.storeCoins(self.amount); - }, - toCell(self: TokenPool_FastFinalityOutboundRateLimitRefunded): c.Cell { - return makeCellFrom(self, TokenPool_FastFinalityOutboundRateLimitRefunded.store); - } -} - -/** - > struct TokenPool_FastFinalityInboundRateLimitRefunded { - > remoteChainSelector: uint64 - > token: address - > amount: coins - > } - */ -export interface TokenPool_FastFinalityInboundRateLimitRefunded { - readonly $: 'TokenPool_FastFinalityInboundRateLimitRefunded' - remoteChainSelector: uint64 - token: c.Address - amount: coins -} - -export const TokenPool_FastFinalityInboundRateLimitRefunded = { - create(args: { - remoteChainSelector: uint64 - token: c.Address - amount: coins - }): TokenPool_FastFinalityInboundRateLimitRefunded { - return { - $: 'TokenPool_FastFinalityInboundRateLimitRefunded', - ...args - } - }, - fromSlice(s: c.Slice): TokenPool_FastFinalityInboundRateLimitRefunded { - return { - $: 'TokenPool_FastFinalityInboundRateLimitRefunded', - remoteChainSelector: s.loadUintBig(64), - token: s.loadAddress(), - amount: s.loadCoins(), - } - }, - store(self: TokenPool_FastFinalityInboundRateLimitRefunded, b: c.Builder): void { - b.storeUint(self.remoteChainSelector, 64); - b.storeAddress(self.token); - b.storeCoins(self.amount); - }, - toCell(self: TokenPool_FastFinalityInboundRateLimitRefunded): c.Cell { - return makeCellFrom(self, TokenPool_FastFinalityInboundRateLimitRefunded.store); - } -} - -/** - > struct TokenPool_TokenTransferFeeConfigUpdated { - > destChainSelector: uint64 - > tokenTransferFeeConfig: Cell - > } - */ -export interface TokenPool_TokenTransferFeeConfigUpdated { - readonly $: 'TokenPool_TokenTransferFeeConfigUpdated' - destChainSelector: uint64 - tokenTransferFeeConfig: TokenPool_TokenTransferFeeConfig -} - -export const TokenPool_TokenTransferFeeConfigUpdated = { - create(args: { - destChainSelector: uint64 - tokenTransferFeeConfig: TokenPool_TokenTransferFeeConfig - }): TokenPool_TokenTransferFeeConfigUpdated { - return { - $: 'TokenPool_TokenTransferFeeConfigUpdated', - ...args - } - }, - fromSlice(s: c.Slice): TokenPool_TokenTransferFeeConfigUpdated { - return { - $: 'TokenPool_TokenTransferFeeConfigUpdated', - destChainSelector: s.loadUintBig(64), - tokenTransferFeeConfig: loadCellRef(s, TokenPool_TokenTransferFeeConfig.fromSlice), - } - }, - store(self: TokenPool_TokenTransferFeeConfigUpdated, b: c.Builder): void { - b.storeUint(self.destChainSelector, 64); - storeCellRef(self.tokenTransferFeeConfig, b, TokenPool_TokenTransferFeeConfig.store); - }, - toCell(self: TokenPool_TokenTransferFeeConfigUpdated): c.Cell { - return makeCellFrom(self, TokenPool_TokenTransferFeeConfigUpdated.store); - } -} - -/** - > struct TokenPool_TokenTransferFeeConfigDeleted { - > destChainSelector: uint64 - > } - */ -export interface TokenPool_TokenTransferFeeConfigDeleted { - readonly $: 'TokenPool_TokenTransferFeeConfigDeleted' - destChainSelector: uint64 -} - -export const TokenPool_TokenTransferFeeConfigDeleted = { - create(args: { - destChainSelector: uint64 - }): TokenPool_TokenTransferFeeConfigDeleted { - return { - $: 'TokenPool_TokenTransferFeeConfigDeleted', - ...args - } - }, - fromSlice(s: c.Slice): TokenPool_TokenTransferFeeConfigDeleted { - return { - $: 'TokenPool_TokenTransferFeeConfigDeleted', - destChainSelector: s.loadUintBig(64), - } - }, - store(self: TokenPool_TokenTransferFeeConfigDeleted, b: c.Builder): void { - b.storeUint(self.destChainSelector, 64); - }, - toCell(self: TokenPool_TokenTransferFeeConfigDeleted): c.Cell { - return makeCellFrom(self, TokenPool_TokenTransferFeeConfigDeleted.store); - } -} - -/** - > struct TokenPool_RateLimitConfigured { - > args: TokenPool_RateLimitConfigArgs - > } - */ -export interface TokenPool_RateLimitConfigured { - readonly $: 'TokenPool_RateLimitConfigured' - args: TokenPool_RateLimitConfigArgs -} - -export const TokenPool_RateLimitConfigured = { - create(args: { - args: TokenPool_RateLimitConfigArgs - }): TokenPool_RateLimitConfigured { - return { - $: 'TokenPool_RateLimitConfigured', - ...args - } - }, - fromSlice(s: c.Slice): TokenPool_RateLimitConfigured { - return { - $: 'TokenPool_RateLimitConfigured', - args: TokenPool_RateLimitConfigArgs.fromSlice(s), - } - }, - store(self: TokenPool_RateLimitConfigured, b: c.Builder): void { - TokenPool_RateLimitConfigArgs.store(self.args, b); - }, - toCell(self: TokenPool_RateLimitConfigured): c.Cell { - return makeCellFrom(self, TokenPool_RateLimitConfigured.store); - } -} - -/** - > struct RateLimiter_Config { - > isEnabled: bool - > capacity: uint120 - > rate: uint120 - > } - */ -export interface RateLimiter_Config { - readonly $: 'RateLimiter_Config' - isEnabled: boolean - capacity: uint120 - rate: uint120 -} - -export const RateLimiter_Config = { - create(args: { - isEnabled: boolean - capacity: uint120 - rate: uint120 - }): RateLimiter_Config { - return { - $: 'RateLimiter_Config', - ...args - } - }, - fromSlice(s: c.Slice): RateLimiter_Config { - return { - $: 'RateLimiter_Config', - isEnabled: s.loadBoolean(), - capacity: s.loadUintBig(120), - rate: s.loadUintBig(120), - } - }, - store(self: RateLimiter_Config, b: c.Builder): void { - b.storeBit(self.isEnabled); - b.storeUint(self.capacity, 120); - b.storeUint(self.rate, 120); - }, - toCell(self: RateLimiter_Config): c.Cell { - return makeCellFrom(self, RateLimiter_Config.store); - } -} - -/** - > struct RateLimiter_TokenBucket { - > tokens: uint120 - > lastUpdated: uint64 - > isEnabled: bool - > capacity: uint120 - > rate: uint120 - > } - */ -export interface RateLimiter_TokenBucket { - readonly $: 'RateLimiter_TokenBucket' - tokens: uint120 - lastUpdated: uint64 - isEnabled: boolean - capacity: uint120 - rate: uint120 -} - -export const RateLimiter_TokenBucket = { - create(args: { - tokens: uint120 - lastUpdated: uint64 - isEnabled: boolean - capacity: uint120 - rate: uint120 - }): RateLimiter_TokenBucket { - return { - $: 'RateLimiter_TokenBucket', - ...args - } - }, - fromSlice(s: c.Slice): RateLimiter_TokenBucket { - return { - $: 'RateLimiter_TokenBucket', - tokens: s.loadUintBig(120), - lastUpdated: s.loadUintBig(64), - isEnabled: s.loadBoolean(), - capacity: s.loadUintBig(120), - rate: s.loadUintBig(120), - } - }, - store(self: RateLimiter_TokenBucket, b: c.Builder): void { - b.storeUint(self.tokens, 120); - b.storeUint(self.lastUpdated, 64); - b.storeBit(self.isEnabled); - b.storeUint(self.capacity, 120); - b.storeUint(self.rate, 120); - }, - toCell(self: RateLimiter_TokenBucket): c.Cell { - return makeCellFrom(self, RateLimiter_TokenBucket.store); - } -} - -// ———————————————————————————————————————————— -// class MockTokenPool -// - -interface ExtraSendOptions { - bounce?: boolean // default: false - sendMode?: SendMode // default: SendMode.PAY_GAS_SEPARATELY - extraCurrencies?: c.ExtraCurrency // default: empty dict -} - -interface DeployedAddrOptions { - workchain?: number // default: 0 (basechain) - toShard?: { fixedPrefixLength: number; closeTo: c.Address } - overrideContractCode?: c.Cell -} - -function calculateDeployedAddress(code: c.Cell, data: c.Cell, options: DeployedAddrOptions): c.Address { - const stateInitCell = beginCell().store(c.storeStateInit({ - code, - data, - splitDepth: options.toShard?.fixedPrefixLength, - special: null, - libraries: null, - })).endCell(); - - let addrHash = stateInitCell.hash(); - if (options.toShard) { - const shardDepth = options.toShard.fixedPrefixLength; - addrHash = beginCell() - .storeBits(new c.BitString(options.toShard.closeTo.hash, 0, shardDepth)) - .storeBits(new c.BitString(stateInitCell.hash(), shardDepth, 256 - shardDepth)) - .endCell() - .beginParse().loadBuffer(32); - } - - return new c.Address(options.workchain ?? 0, addrHash); -} - -export class MockTokenPool implements c.Contract { - static CodeCell = c.Cell.fromBase64('te6ccgECnQEAJzYAART/APSkE/S88sgLAQICzQIDAgEgBAUAH9TFsIiFus5THBcMAkltw4oCASAGBwIBIGBhAgEgCAkCASATFAIBIAoLAgEgDxACASAMDQGpXtou371ywnkNvtDI5E1ywnzxTyVJRbcNsx4YIAwoojbrPy9CGCAMKKBMcFE/L0IG0D1ws/iwIByMs/FfpSEvpSycjPhyAUznHPC2ETzMlw+wDjDX+A4AxT4kfJA7UTQ1NEg0NTU0wf0BPQE0W1tbW1tbW1tbW1tgQCH+JL4lxESERMREhERERIREREQEREREA8REA8Q71YU8Aps0Y4SNQPIzBLMywf0APQAycjMye1U4F8FhA8BxwDy9IABpCDCTZMwcHHgcXqTIsIAjiAicbDAAZyE/yKpBCG+8oRmqAHeAqsAIMIAlFEgqALeAugwMXCAAZmwS0z/6SDCCAMKIUTTHBRPy9IIAwolTI8cFs/L0IYsCyM+HIM5wzwthEss/EvpSyXD7AABXUhbpJbcOCCaQAAAAAAAAAAAAAAAAAAASKDBvQOb6Exklt/4AGDBvQOb6ExgCASAREgCPDAjs5F/lSDAAMMA4pEw4FNS+CMnoRBoXjQQN0iAUoDwCDVRZbmVgT+t8vDgUzS5jhBfBSCVgT+u8vDhMIE/rvLw4FA0oVA0gAFkMCOzkX+VIMAAwwDikTDgU1L4IyehEGheNBA3SIBSgPAINVBFoFAFtghERAOACASAkJQIBIBUWAgEgFxgCASAhIgH1CbDAJUrbrPDAJFw4psGERIGK9p2BRERBeAj0NP/1NEg0NM/+kgx+gD6SDCBOj1WHdDUMfpQMdQx+kgwWMcF8vSBOjkiVhqAQPQOb6Ex8vRWG1YbVhtWG1YbVhtWG1YbVhtWG1YbVhtWG1YbVhtWG1YbVhtWE/ANVhsCgGQBNFD+Xww0NYE6OgTQ9ATRIfAFsxTy9MMAlSBus8MAkXDiktog4F8DgA/5WGwJWGwJWGwJWGwJWGwJWGwJWGwJWGwJWGwJWGwJWGwJWGwJWGwJWGwJWGwJWGwJWGwIBERUBERRWGPAOZqEl4w+BOjhRMYBA9A5voRTy9ALU9AQx1DHUMdFWGMjL/8nIz5Pp9pESKc8LPyjPFCfPCx9SYPQAUlD6VMnIJPoCGhscAv5WGtDUMfpQMdQx+kgx1DHTH/pQMfQEMdFSYPAJgTo4I1YZgED0Dm+hEvL01PQE1NTR0NTU0QHQ03fTP9IA03fTd9EijjNWI9DUMfpQMdQx+kgwUqDwBgTIy3cTyz/KAMt3y3fJyMzMyQPIzBL0AMzMUjIRGYBA9EPjDlYa0NQxHR4B/oE6OCNWGYBA9A5voRLy9NT0BNTU0QHQ1NTRAdDTd9M/0gDTd9N30VYj0NQx+lAx1DH6SDBSoPAGBMjLdxPLP8oAy3fLd8nIzMzJA8jMEvQAEszMUjIRGYBA9ENWGtDUMfpQMdQx+kgwI8jLP/pSVhj6AsnIz48YAASCEM9QWfwgAMZWGvoCI88UIs8UyStWHglWHglWHlGQCVYeCVYeCVYeCVYeCVYeCVYeCVYeCVYeCVYeCVYeCVYeCVYeCVYeCVYeCQgRHggHER0HBhEcBgURGwUEER4EAxEdA1nwDwIREwJQRAMB9l8JgTo4I1YZgED0Dm+hEvL01PQE1NTRAdDU1NEB0NN30z/SANN303fRViPQ1DH6UDHUMfpIMFKg8AYEyMt3E8s/ygDLd8t3ycjMzMkDyMwS9AASzMxSMhEZgED0Q1Ya0NQx+lAx1DH6SDAjyMs/+lJWGPoCycjPjxgABB8AVvpQMdQx+kgwI8jLP/pSVhj6AsnIz48YAASCEOukjAvPC/dxzwthzMlw+wAAJIIQz1BZ/M8L93HPC2HMyXD7AAAYzwv3cc8LYczJcPsAAJcVxFXEV8OMzPQ0z/6SDH6ADACgED0Dm+hk18DcOHTHzHTHzH6ADH6ADHTD9MP0gDRk18EcOEDkTCRMuKBOjQigScQufL0qIEnEKkEgAZcODk5OTo6Ojo6Ojo7Ozs7BMMAlShus8MAkXDinToQSQgQR0YVRBMC2pHgNTY2B9DUMfpQMdQx+kgx1DHTHzH6UPQEMdEgbuMDXwhwgIwCYJdD6ADH6ANQx1DHR+CgFyPpSE8wWzMnIz5EEp0QmFcs/EswWyx8U9ABQBPoCEvpSEvQAycjPhYgS+lLPhBBz+gJxzwtlzMmAQPsAfwIBICYnAgEgKCkANQgjhU2XLyVgT+s8vDgUVKooBS2CPgjUETgW4AApCGRW+GBOkkhlAK6wwCTbCFw4vL0gA2c7aLt+yDXLCfT7SIknmwh0z/U0x/0BPpQMPALj5TXLCBHl/28jwnXLCU2/TEc4w/jDeJ/gKissAfEVhfQ1DH6UDHU+kgx1DHTHzH6UDH0BDHR0PpI+lAx+lAx9AQx0SaBOj4CxwXy9CbDAJUsbrPDAJFw4pgGERIGLNpxDOAREREXEREREBEWERAPERUPDhEUDg0REw0MERIMCxEXCwoRFgoJERUJCBEUCAcREwcGERIGgXgP4bCHTPzHXTFYT0NQx+lAx1DH6SDHUMdMfMfpQ9AQx0YE6PiFus5UDxwXDAJMxMnDiEvL00PpIMdTU0SHQ1ywn0+0iJPK/0z8x1NcLHwHQ0/8x10zQAtAC1ws/AvoAMfoAMAHjD9DXLCfT7SIk8r/TP9Qx0x8x9AH6UDAgbi0uLwPa1ywjmxaE5I4SMdM/+gD6UFUD8YAQgBmAEts4j8/XLCGo+78cnGwh0z/U0x/6UDDwFI+41ywk8VNbNI8t1ywhDzjsPI6i1ywmKjtpXI4XbCHTP/pI0z/6ANMf0wf0BPpI9AVt8BvjDuMN4w3i4jM0NQL+bCHTPzHXTFYT0NQx+lAx1DH6SDHUMdMfMfpQ9AQx0YE6PiFus5UDxwXDAJMxMnDiEvL00PpI1NTRAdAB0AHXLCfT7SIk8r/TP9TTH/QE+lAwBfoA+gDU10zIz5Pp9pESKM8LPxfMFcsfE/QAUmD6VMnIWPoCWPoCEswSzMnIiVxdAvyBOjgiVhOAQPQOb6ES8vTU9ATU1NEg0NTU0QHQ03fTP9IA03fTd9EijjhfBgHQ1NTRAdDTd9M/0gDTd9N30VYd0NQx+lAx1DH6SDBSoPAHBMjLdxPLP8oAy3fLd8nIzMzJAeMNA8jMEvQAzMxSIhETgED0Q1YU0NQx+lAx1DEwMQH2gTo4IlYTgED0Dm+hEvL01PQE1NTRAdDU1NEB0NN30z/SANN303fRVh3Q1DH6UDHUMfpIMFKg8AcEyMt3E8s/ygDLd8t3ycjMzMkDyMwS9AASzMxSIhETgED0Q1YU0NQx+lAx1DH6SDACyMs/EvpSARER+gLJyM+PGAAEMgA+kVuOGsjPhQj6UoIQNHbqcs8Ljss/z4jpFsmAQPsA4gBWNlYd0NQx+lAx1DH6SDAQRRA0QTBUJqDwBwTIy3cTyz/KAMt3y3fJyMzMyQBQ+kgwAsjLPxL6UgEREfoCycjPjxgABIIQFB9+LM8L93HPC2HMyXD7AAAkghAw66vbzwv3cc8LYczJcPsABP7XLCaRSiasjmBsIdM/+kjTP/oA0x/TB/QE9AVWGlYaVhpWGlYaVhpWGlYaVhpWGlYaVhpWGlYaVhpWGlYaVhpWF1YXVhdWF/AdCMjLHxfLH1AF+gJQA/oCyw/LD8oAAfoCygDJ+ChZ8BuPlNcsIYMJWLyPCdcsIre56bzjD+MNNjc4OQP2bCHTPzHXTFYT0NQx+lAx1DH6SDHUMdMfMfpQ9AQx0YE6PiFus5UDxwXDAJMxMnDiEvL00PpIMdTU0SHQ1ywhqPu/HPK/0z8x1NcLHwHQ0/8x10zQAtAC+kgx1ws/AtMfMfoAMAHjD9DXLCGo+78c8r/TP9MfMfpQMCBuVldYAL5sIdM/MddMVhPQ1DH6UDHUMfpIMdQx0x8x+lD0BDHRgTo+IW6zlQPHBcMAkzEycOIS8vTQ+kjU1NEB0AHQAdcsIaj7vxzyv9M/1NMf+lAwBNMf+gD6ADAQVhBFEDTwGgP+bCHTP9TXTFYV0NT6UDHUMfpIMdQx0x8x+lAx9AQx0dD6SPpQMdEkggDCiALHBfL0AdCUIMcAs44/INdLAZEwm4E0vAHAAfL010zQ4tM/UhARFIBA9FuBOjgB8vTIz48YAASCECeQgovPC/dwzwthEss/yXD7ABES6DDQioroMDo7PAMo1ywgvhIW5I8J1ywiE1xmJOMP4w1AQUIA+mwh0z/U9AVWFdDUMfpQMdQx+kgx1DHTHzH6UPQEMdGBOj4hbrOVBccFwwCTMTRw4hTy9IE6RiNus/L0AtD6SPQE9AUgbo4QMMjPkbHCy3YTyz8TzPQAyY4SyM+QVjdfVhTLPxTMEswS9ADJ4sjPhQgS+lJxzwtuzMmAQPsAAALiAAggxwCzAf4g10sBkTCbgTS8AcAB8vTXTNDi0z/U1NSBOjcj0NMHIcFB8oUBqgLXGNHXScMA8vSBOjslVheAQPQOb6Exs/L0AdDU1NFtAtDSANN303fR+CMiyMt3yz8TygDLd8t3yQHQ0gDTd9N30fgjIsjLd8s/E8oAy3fLd8kByMzMyfgjPQAuyM+FCBL6UoIQrXgz188Ljss/yYBA+wABtHDIy3fLP3DPC/DJ+CNwyMt3yz9wzwvwyQHIzMzJJAbQlCDHALOK6DAFyMwS9ADME8xSMhEVgED0Q8jPjxgABIIQ7TfEvM8L93DPC2ETyz8BERMBzMlw+wARET4B/iDXSwGRMJuBNLwBwAHy9NdM0OLTByHBQfKFAaoC1xjIItdJIKk4AvJFqwIgwUHyhc8LBxLOyYE6NyHQ0wchwUHyhQGqAtcY0ddJwwDy9CD5AIE6P1MWgwf0Dm+hMbPy9FRBFoMH9BfIz48YAASCEL8NGrbPC/dwzwthKc8LPxU/AArMyXD7AAH2bCHTP9M/10xWFdDU+lAx1DH6SDHUMdMfMfpQMfQEMdHQ+kj6UDHRJIIAwogCxwXy9IE6OCJWFIBA9A5voTHy9IE6OCJWFIBA9A5voRLy9NT0BNTU0ST5AFADgwf0W4E6QAHy9APIzBP0ABLMzFIiERSAQPRDyM+PGAAEQwLq1ywmu4lAhI7q1ywh4oUc3I5fbCHTP9cLHxEU0NT6UNT6SNTTHzH6UPQE0SbQ+kj6UDHRKYIAwogCxwXy9FYaB8jMFvpUFMwS+lLME8sfEvpU9ADJyM+FCBP6UoIQQmpxO88Ljss/ARETAcsfyYBA+wDjDuMNREUB/mwh0z/TP9dMVhXQ1PpQMdQx+kgx1DHTHzH6UDH0BDHR0PpI+lAx0SSCAMKIAscF8vSBOjgiVhSAQPQOb6Ex8vSBOjgiVhSAQPQOb6ES8vTU9ATU1NGBOjcl0NMHIcFB8oUBqgLXGNHXScMA8vQk+QCBOj9TFIMH9A5voTGz8vRVAHCCELwUx+jPC/dwzwthIs8LP1YTzxTJcPsAyM+FCBT6UoIQ4XvzzM8LjhLLP8s/AREQAczJgED7AAP41ywh+uT6vI9x1ywhw0cYTI5cbCHTP/QFERTQ1PpQ1PpI1NMf+lD0BDHRJtD6SPpQMdEpggDCiALHBfL0VhoHyMwW+lQUzBL6UszLH/pU9ADJyM+FCBP6UoIQidYC5c8Ljss/ARETAfQAyYBA+wCPCdcsJCHCChTjD+LjDUZHSAH6bCHTP/pI+lD6UDARFtDU+lDUMfpI1NMf+lD0BNEm0PpI+lAx0SuCAMKIAscF8vSBOjeLAirHBbPy9G0pyPpSUpD6VFYeAfpU9ADJB8jMFvpUFswT+lLMyx8S+lT0AMnIz5Lc14wyFMs/EvpS+lQBERQB+lTJyM+FCBL6UnFUAPRsIdM/9AURFNDU+lDU+kjU0x/6UPQE0SfQ+kj6UDHRKoIAwogCxwXy9AXQ+kj6UPpQ9AQx0QLI+lL6VPpUAREbAfQAyQbIzBX6VBXM+lITzMsfAREVAfpUAREUAfQAycjPhQgS+lKCEMH/46bPC44BERMByz/JgED7AAP81ywifxaTZI9z1ywhhQ6PvI7o1ywkyU2yFI5dbCHTP/pQMBEU0NT6UDHU+kjU0x/6UPQE0SbQ+kj6UDHRKYIAwogCxwXy9FYaB8jMF/pUFcwT+lLMyx/6VPQAycjPhQgT+lKCEOXQiy7PC47LPwEREwH6VMmAQPsA4w7jDeMNSUpLALxsIdM/+lAwERTQ1PpQ1PpI1NMf+lAx9ATRJtD6SPpQMdEpggDCiALHBfL0VhoHyMwW+lQUzBL6UszLHxL6VPQAycjPhQgT+lKCEDyGnYDPC47LPwEREwH6VMmAQPsAAfLXLCTtJtBMjm5sIdM/9AVWFNDU+lDUMfpIMdQx0x8x+lAx9AQx0QHQ+kj6UDHRJIE6PgLHBZIxf44QIW6zllJCxwXDAJIxcOLDAOLy9BET0PQEMdFWEsj0AMnIz4UIE/pSghAVgAFhzwuOyz8BERIB9ADJgED7AOMOTAL+bCHTP9TXTFYV0NT6UDHUMfpIMdQx0x8x+lAx9AQx0dD6SPpQMdEkggDCiALHBfL0AdCUIMcAs4roMNCUIMcAs446INdLAZEwm4E0vAHAAfL010zQ4tM/UhAREoBA9FswyM+PGAAEghDWRsfRzwv3cM8LYRLLP8lw+wAREOgwyE5PAdRsIdM/10xWFNDU+lAx1PpIMdQx0x8x+lAx9AQx0dD6SPpQ+lD0BNEE0PpI+lAx0ZLwHgBUJYDsXySBOj4DxwWSMH+U2gHDAOLy9NCUIMcAs4roMMjPhQgS+lKCEN17DHHPC47LP8mAQPsAUQHu1ywgaATK5I5UMDFWE9DU+lDU+kjU0x/6UPQE0QfQ+kj6UNFBCinwA44qOFcaERnI+lIW+lTJyMwT+lTM+lISzAERFAHLH/pUARESAfQAyRERf9sx4BCJXwnHANsx4THTP28AAdMH9AWTIG6ziugwIW+IuvKJ8B9NAFrQ9ASOJvpI+gDXLCB8U/Us8r/TP/oA+kj6UPQE+gCLCAxVgG8Jb4wjxwAU5jAB/iDXSwGRMJuBNLwBwAHy9NdM0OLTP9Mf0x/6APoA0w/TD9IAgTo4KVYcgED0Dm+hMfL0gTo1IvL0gTo0JIEnELny9IE6NCOBJxC58vSBOjUowgDy9CfIyx8nzwsfJvoCJfoCJM8LDyPPCw8izwoAUpIRG4BA9EMHyMsfFssfUARQASyJzxYS+lKCECjLzGTPC47LP8mAQPsAkABU+gJY+gLLD8sPygDJyM+PGAAEghD75h8Vzwv3cM8LYRPLPxLMyXD7ABERAvwg10sBkTCbgTS8AcAB8vTXTNDi0z/SANTUgTo4JVYXgED0Dm+hEvL01PQE1NTRJ44/AdDUMdQx0SXQ0gDTd9N30fgjIsjLd8s/E8oAy3fLd8kl0NIA03fTd9H4IyLIy3fLPxPKAMt3y3fJAcjMzMkB4w0DyMwS9ADMzFJSERdSUwB60NQx1DHRJdDSANN303fR+CMiyMt3yz8TygDLd8t3ySXQ0gDTd9N30fgjIsjLd8s/E8oAy3fLd8kByMzMyQBKgED0Q8jPjxgABIIQ/52/ds8L93DPC2EVyz8TygDMzMlw+wAREQASzwtuzMmAQPsAAKpURRSDB/QXyM+PGAAEghC/DRq2zwv3cM8LYSbPCz8lzxTJcPsAA8jME/QAEszMUiIRFIBA9EPIz4UIFPpSghASzEmFzwuOEss/yz8BERABzMmAQPsAAv6BOjgiVhOAQPQOb6ES8vTU9ATU1NEg0NTU0dDTd9M/0gDTd9N30SKOOF8GAdDU1NHQ03fTP9IA03fTd9FWHdDUMfpQMdQx+kgwUqDwBwTIy3cTyz/KAMt3y3fJAcjMzMkB4w0DyMwS9ADMzFIiEROAQPRDVhTQ1DH6UDHUMfpIWVoB9oE6OCJWE4BA9A5voRLy9NT0BNTU0QHQ1NTR0NN30z/SANN303fRVh3Q1DH6UDHUMfpIMFKg8AcEyMt3E8s/ygDLd8t3yQHIzMzJA8jMEvQAEszMUiIRE4BA9ENWFNDUMfpQMdQx+kgwAsjLPxL6UgEREfoCycjPjxgABFsAPpFbjhrIz4UI+lKCEO8Ms27PC47LP8+I6RbJgED7AOIAWDZWHdDUMfpQMdQx+kgwEEUQNEEwVCag8AcEyMt3E8s/ygDLd8t3yQHIzMzJAEwwAsjLPxL6UgEREfoCycjPjxgABIIQNH/8fM8L93HPC2HMyXD7AAAkghB0Ca2Pzwv3cc8LYczJcPsAAAjno1BBADzPFhPLPxT6UhPMEszJyM+FiBL6UnHPC27MyYBA+wAB/gURFwUEERYEAxEVAwIRFAIBERMBERJWF1YXVhdWF1YXVhfwDASOIF8EVxJXElcSVxJXElcSCxERCwoREAoQnxCOEH0QbFVV4MjPk+n2kRJWG88LPwERGgHMAREYAcsfAREWAfQAVhQB+lTJyAERFvoCAREW+gIBERYBzAERFAFfAJzMycjPk56NQQYBERYByz8BERYB+lIBEREBzAEREwHMycjPhYgf+lJxzwtuHszJgED7AAsREQsKERAKEJ8QjhB9EGwQWxBKEDlIFkVVBwMCASBiYwIBIIGCAgEgZGUCASBxcgIBIGZnAgEgbm8C9QmwwCVKW6zwwCRcOKZMAUREQUo2mEM4IE6PlYY0NQx+lAx1DH6SNdM+CjIz4QC+lIS+lLJAcjPhNDMzPkWyM+KAEDL/89QJ8cF8vRWF1YXVhdWF1YXVhdWF1YXVhdWF1YXVhdWF1YXVhdWF1YXVhdWF1YXVhdWF1YXioGhpAY07aLt+1cSVxBfDyLQ1DH6UDHU+kgx1DHTHzH6UDH0BDHR0PpI+lAx+lAx9ATRUyHHBZJfBeAggCD0hm+lMpEBiuiBOj7y8IG0ABlvwEwP+7eO6gBd/7RGPcSH0BCFumDEgxwCSMG3gktHQ4vpI1NTRVhoBVhoBVhoBVhoBVhoBVhoBVhoBVhoBVhoBVhoBVhoBVhoBVhoBVhoBVhoBVhoBVhoBVhoBVhoBVhoBVhoBVhoBVhoBERpWGIrt47qAGX/tEYrtQe3xAfL/7UHt8WprbACoMRBHEDZFdvAT+CdvEFMBvJGikltw4vgvoHL7AgHQ1ywn0+0iJPK/0z/UMdMfMfQB+lAwIG6SXwOOGcjPhQj6UoIQNHbqcs8Ljss/yw/JgQCC+wDiANQg0NcsJ9PtIiTyv9dM0NP/MddM0NM/MfpI+gAwgTpIURi68vSBOkcmbrPy9FYaAVYaAVYaAVYaAVYaAVYaAVYaAVYaAVYaAVYaAVYaAVYaAVYaAVYaAVYaAVYaAVYaAVYaAVYXAfARWPASAAYB8v8AnlMF0NQx+lAx1DH6SDHUMdMfMfpQMfQE0YE6PiFus/L0JMj6UhLLH1Jg+lLJAcjPhNDMzPkWyM+KAEDL/89QJMcFlF8G2zHgIYAg9HxvpTIB9QowwCVKm6zwwCRcOKYCBEUCCrakQzgbDMzMwLQAdAB1ywn0+0iJPK/0z/U0x8x9AH6UDAB0NP/MdTR0NQx0z/6SDH6ADH6SNEE+gAx+gDU10wGyPpSF/pSIfoCycjPjxgABIIQN91vbs8L93DPC2ETyz8SzMlw+wAhboHAAgwwIG6SXwTgghAF9eEAbYsEyM+QPin6lhbLP1AE+gJSIPpSEvpUEvQAz4QgEs7JyM+FCBP6UgH6AnHPC2rMyXP7AIABOkl8FjiEEyMwTzMnIz4WIE/pSghD0MqTjzwuOyz/MAfoCyYBA+wDiAgEgc3QCASB/gAH3FYW0NQx+lAx1PpIMdQx0x8x+lAx9AQx0dD6SPpQMfpQMfQEMdElgTo+AscF8vQlwwCVL26zwwCRcOKbNAQREARVAi7aUQzgERERFhERERARFREQDxEUDw4REw4NERINDBEWDAsRFQsKERQKCRETCQgREggHERYHBhEVBoHUB9QlwwCVLm6zwwCRcOKbBRERBS7aZQQREATgItDT/zHU1PQE9AQx0QLQ+kgx0z/UMdP/+kjRgTo9VhzQ1DH6UDHUMfpIMFjHBfL0gTo5IlYZgED0Dm+hMfL0VhpWGlYaVhpWGlYaVhpWGlYaVhpWGlYaVhpWGlYaVhpWGoHcB/AURFAUEERMEAxESAwIRFgIBERUBERRWE1YTVhhWGFYY8BUDjhxfA1cSVxJXElcSVxIMEREMCxEQCxCvEJ4QjVVH4BEUERkRFBETERgRExESERcREhERERYREREQERUREA8RFA8OERMODRESDQwREQwLERALEK8QnhCNEHwQa3YAEhBaEEkQOFjwGgH8VhpWE/ANVhpWGlYaVhpWGlYaVhpWGlYaVhpWGlYaVhpWGlYaVhpWGlYaVhOBOkARFvAWE/L0VhkBVhkBVhkBVhkBVhkBVhkBVhkBVhkBVhkBVhkBVhkBVhkBVhkBVhkBVhkBVhkBVhkBVhkBERTwF5LwGAASVhoCVhoCVhoCeAP+VhoCVhoCVhoCVhoCVhoCVhoCVhoCVhoCVhoCVhoCVhoCVhoCVhoCVhoCVhoCgBR/7RHaASDBAJF/liCEd7zDAOKVgTpC8vDgI+MPIlYVyM+Q1H3fjifPCz8mzxQlzwsfUkD6VMkiyMsfIvoCVhj6AskpVhwIVhwIVhxRgAhWHHl6ewL+VhjQ1DH6UDHUMfpIMdQx0x/6UDH0BDHRUkDwCYE6OCJWF4BA9A5voRLy9NT0BNTU0dDU1NHQ03fTP9IA03fTd9EijjRWIdDUMfpQMdQx+kgwUqDwBgTIy3cTyz/KAMt3y3fJAcjMzMkDyMwS9ADMzFIiEReAQPRD4w5WGNDUMXx9AfSBOjgiVheAQPQOb6ES8vTU9ATU1NEB0NTU0dDTd9M/0gDTd9N30VYh0NQx+lAx1DH6SDBSoPAGBMjLdxPLP8oAy3fLd8kByMzMyQPIzBL0ABLMzFIiEReAQPRDVhjQ1DH6UDHUMfpIMALIyz8S+lJWFfoCycjPjxgABH4AdghWHAhWHAhWHAhWHAhWHAhWHAhWHAhWHAhWHAhWHAhWHAhWHAhWHAgHERwHBhEbBgURGgVQQ/AZAxESAfZfCYE6OCJWF4BA9A5voRLy9NT0BNTU0QHQ1NTR0NN30z/SANN303fRViHQ1DH6UDHUMfpIMFKg8AYEyMt3E8s/ygDLd8t3yQHIzMzJA8jMEvQAEszMUiIRF4BA9ENWGNDUMfpQMdQx+kgwIsjLP/pSVhb6AsnIz48YAAR+AFj6UDHUMfpIMALIyz8S+lJWFfoCycjPjxgABIIQy8QOW88L93HPC2HMyXD7AAAkghCLsl+ozwv3cc8LYczJcPsAAE0VxFXEV8OMwKAQPQOb6GSW3Dh1DH0BNQx1DHRAfkAAYMH9A5voTGAAXRXEV8PMiBukTDgMdCBOkEh10mDB7qXIddKwADDAJFw4vL00//RgTpBIYQHu/L0gAgEgg4QCASCRkgIBIIWGAgEgiIkAexXEV8PMlMhupJsIeBTIbydAqLwAZWBOkLy8OCpBOACofABlYE6QvLw4IE6QiGZhP8iqQQjvsMAkX/i8vSogAYsNzg4ODg4ODg5OTk6Ojo6AsMAlSBus8MAkXDilzkQOFUC2oHgMDMzBtDUMfpQMdQx+kgx1DHTHzH6UPQEMdEgbuMDXwdwghwCKIdDTHzH6APoAMdH4KAjI+lIUzBLMycjPkcDwrWIWyz8UzAH6AssfE/pS9ADJyM+FiBL6Us+EEHP6AnHPC2XMyYBA+wB/AdUKMMAlS9us8MAkXDimAgRFAgv2pEM4DIzA9DT/zHU1DH0BDH0BDHR0PpI0z/UMdP/MfpI0QLI+lLJAsj6Uhf6UlAD+gISzMnIz48YAASCEOnADJfPC/dwzwthFcs/FMzJcPsAIm6SXwPjDoIoE8wyVhvQ1DH6UDHUMfpIMdQx0x/6UDH0BDHRUlDwCYE6PVYc0NQx+lAx1DH6SDApxwXy9IE6OSdWGoBA9A5voTHy9ClWHNDUMfpQMdQx+kgx1DHTHzH6UPQEMdEgbuMDW2xiiCJujhDIz5BWN19WFMs/E8zM9ADJ4w3Igi4yNjgA6yAH6AsnIz4WIE/pSghDg6IL1zwuOyz/MyYBA+wAB/jtWHAFWHAFWHAFWHAFWHAFWHAFWHAFWHAFWHAFWHAFWHAFWHAFWHAFWHAFWHAFWHAFWHAFWHAFWGQERGVYYVhhWGPAc+CgHyPpSEvQAEvQAycjPkxUdtK4Zyz8X+lIVyz9QBfoCyx8Tywf0APpS9ADJyM+FiBL6Us+EEHP6AnGPAAAAHjLIz5Gxwst2E8s/zPQAyQEgic8WEvpScc8LbszJgED7AJAAEs8LZczJgED7AAABQgIBIJOUAgEgmJkC9whljDwHRhfCOE0W1YTAVYTAVYTAVYTAVYTAVYTAVYTAVYTAVYTAVYTAVYTAVYTAVYTAVYTAVYTAVYTAVYTAVYTARET8BeS8BgAAREUAQEREwEBERIBARERAQEREAEfHh0cGxoZGBcWFRRDMIAUf+0R2gEgwQCRf+MO4wKCVlgHfGzENDU1NTUTgED0Dm+hILORf44ZIdMfMdMfMfoAMfoAMdMPMdMPMdIA0bPDAOKOIjMzAY4QAdMf0x/6APoA0w/TD9IA0ZgxcFRwAFMAcOJVBnDgMNMf0x/6APoA0w/TD9IA0ScKkjc34w4QR1Ujf4JcADCCEd7zDAAAKgTpC8vAAZDlUQRiSNybegTo0KIEnELny9FJoqIEnEKkEFqEgwQCRf5YghHe8wwDilYE6QvLw4AcFAB0NFsgbrOUxwXDAJJbcOKAB9wkwwCVJW6zwwCRcOKYBBEQBCXaUQzgMYT/gTpEVhbQ1PpQMdT6SDHUMdMfMfpQMfQEMdHQ+kj6UPpQ9ATRBND6SPpQMdGS8CAAVCWg7F9SYscFkjB/lNoBwwDi8vSCANmYIm+IwAHy9CFvEG8pXwiCANmYVhfQ1DH6UDGCaAW7UMfpI10z4KMjPhAL6UhL6UskByM+E0MzM+RbIz4oAQMv/z1ASxwXy9G1wVHADb4iSXLmK6F8JmwH8IaRSc2+BbylRx6BRtaCCANmXLIIQBfXhAKBWErvy9IsCJccFloIA2ZTy8OAtbrOOKVNNjiHtou37cCFviJJcuY4QIaRSM2+BJMcFlV8Ef9sx4OhfBHDYs8MAkXDiloIA2ZXy8OCCANmWU2+78vSCANmVA24T8vTIz5JQ+KB6nADAVhEB+lLJJcjPkD4p+pYYyz9QB/oCFPpSEvpUFPQAAfoCGM7JyM+FiFJA+lJQA/oCz4Fz+gJxzwtlEszJgBD7AMjPjxgABIIQqodQKc8L93DPC2ES+lJQBfoCyXD7ABAj'); - - static Errors = { - 'Common_Error.CrossChainAddressOutOfRange': 5, - 'Utils_Error.InvalidData': 13500, - 'TokenPool_Error.InvalidTransferFeeBps': 14900, - 'TokenPool_Error.InvalidTokenTransferFeeConfig': 14901, - 'TokenPool_Error.ZeroAddressInvalid': 14903, - 'TokenPool_Error.NonExistentChain': 14904, - 'TokenPool_Error.ChainNotAllowed': 14905, - 'TokenPool_Error.CursedByRMN': 14906, - 'TokenPool_Error.ChainAlreadyExists': 14907, - 'TokenPool_Error.InvalidToken': 14909, - 'TokenPool_Error.Unauthorized': 14910, - 'TokenPool_Error.PoolAlreadyAdded': 14911, - 'TokenPool_Error.InvalidRemotePoolForChain': 14912, - 'TokenPool_Error.InvalidRemoteChainDecimals': 14913, - 'TokenPool_Error.OverflowDetected': 14914, - 'TokenPool_Error.CallerIsNotOwnerOrFeeAdmin': 14916, - 'TokenPool_Error.MissingForwardPayload': 14918, - 'TokenPool_Error.MissingTransferInitiator': 14919, - 'TokenPool_Error.AmountMismatch': 14920, - 'TokenPool_Error.InvalidRequestedFinality': 14921, - 'RateLimiter_Error.BucketOverfilled': 16300, - 'RateLimiter_Error.TokenMaxCapacityExceeded': 16301, - 'RateLimiter_Error.TokenRateLimitReached': 16302, - 'Ownable2Step_Error.OnlyCallableByOwner': 49800, - 'Ownable2Step_Error.CannotTransferToSelf': 49801, - 'Ownable2Step_Error.MustBeProposedOwner': 49802, - 'JettonWithdrawable_Error.ZeroAddressNotAllowed': 55700, - 'JettonWithdrawable_Error.UnallowedRecipient': 55701, - 'JettonWithdrawable_Error.MaxAmountExceeded': 55702, - 'JettonWithdrawable_Error.InsufficientValue': 55703, - 'JettonWithdrawable_Error.InvalidWithdrawWallet': 55704, - } - - readonly address: c.Address - readonly init: { code: c.Cell, data: c.Cell } | undefined - - protected constructor(address: c.Address, init?: { code: c.Cell, data: c.Cell }) { - this.address = address; - this.init = init; - } - - static registerCustomPackUnpack( - typeName: string, - packToBuilderFn: CustomPackToBuilderFn | null, - unpackFromSliceFn: CustomUnpackFromSliceFn | null, - ) { - if (customSerializersRegistry.has(typeName)) { - throw new Error(`Custom pack/unpack for 'MockTokenPool.${typeName}' already registered`); - } - customSerializersRegistry.set(typeName, [packToBuilderFn, unpackFromSliceFn]); - } - - static fromAddress(address: c.Address) { - return new MockTokenPool(address); - } - - static fromStorage(emptyStorage: { - poolData: TokenPool_Data - }, deployedOptions?: DeployedAddrOptions) { - const initialState = { - code: deployedOptions?.overrideContractCode ?? MockTokenPool.CodeCell, - data: Storage.toCell(Storage.create(emptyStorage)), - }; - const address = calculateDeployedAddress(initialState.code, initialState.data, deployedOptions ?? {}); - return new MockTokenPool(address, initialState); - } - - static createCellOfTokenPoolLockOrBurn(body: { - queryId?: uint64 - request: TokenPool_LockOrBurnInV1 - requestedFinalityConfig: uint32 - tokenArgs: c.Cell | null - replyTo: c.Address | null - }) { - return TokenPool_LockOrBurn.toCell(TokenPool_LockOrBurn.create(body)); - } - - static createCellOfTransferNotificationForRecipient(body: { - queryId?: uint64 - jettonAmount: coins - transferInitiator: c.Address | null - forwardPayload: ForwardPayloadRemainder - }) { - return TransferNotificationForRecipient.toCell(TransferNotificationForRecipient.create(body)); - } - - static createCellOfTokenPoolPreflightCheckFinished(body: { - queryId?: uint64 - forwardPayload: TokenPool_LockOrBurnForwardPayload - }) { - return TokenPool_PreflightCheckFinished.toCell(TokenPool_PreflightCheckFinished.create(body)); - } - - static createCellOfTokenPoolPreflightCheckFailed(body: { - queryId?: uint64 - forwardPayload: TokenPool_LockOrBurnForwardPayload - }) { - return TokenPool_PreflightCheckFailed.toCell(TokenPool_PreflightCheckFailed.create(body)); - } - - static createCellOfTokenPoolReleaseOrMint(body: { - queryId?: uint64 - request: TokenPool_ReleaseOrMintInV1 - requestedFinalityConfig: uint32 - replyTo?: c.Address | null /* = null */ - }) { - return TokenPool_ReleaseOrMint.toCell(TokenPool_ReleaseOrMint.create(body)); - } - - static createCellOfTokenPoolPostflightCheckFinished(body: { - queryId?: uint64 - forwardPayload: TokenPool_ReleaseOrMintForwardPayload - }) { - return TokenPool_PostflightCheckFinished.toCell(TokenPool_PostflightCheckFinished.create(body)); - } - - static createCellOfTokenPoolPostflightCheckFailed(body: { - queryId?: uint64 - forwardPayload: TokenPool_ReleaseOrMintForwardPayload - }) { - return TokenPool_PostflightCheckFailed.toCell(TokenPool_PostflightCheckFailed.create(body)); - } - - static createCellOfTokenPoolGetCCVs(body: { - queryId?: uint64 - localToken: c.Address - remoteChainSelector: uint64 - amount: coins - requestedFinalityConfig: uint32 - direction: uint8 - extraData: c.Cell | null - replyTo: c.Address - forwardPayload: c.Cell | null - }) { - return TokenPool_GetCCVs.toCell(TokenPool_GetCCVs.create(body)); - } - - static createCellOfTokenPoolGetCCVsAndFees(body: { - queryId?: uint64 - localToken: c.Address - remoteChainSelector: uint64 - amount: coins - requestedFinalityConfig: uint32 - direction: uint8 - extraData: c.Cell | null - forwardPayload: c.Cell | null - }) { - return TokenPool_GetCCVsAndFees.toCell(TokenPool_GetCCVsAndFees.create(body)); - } - - static createCellOfTokenPoolQueryCCVsReply(body: { - queryId?: uint64 - requiredCCVs: SnakedCell - replyPayload: c.Cell | null - }) { - return TokenPool_QueryCCVsReply.toCell(TokenPool_QueryCCVsReply.create(body)); - } - - static createCellOfTokenPoolApplyChainUpdates(body: { - queryId?: uint64 - remoteChainSelectorsToRemove: SnakedCell - chainsToAdd: SnakedCell - }) { - return TokenPool_ApplyChainUpdates.toCell(TokenPool_ApplyChainUpdates.create(body)); - } - - static createCellOfTokenPoolAddRemotePool(body: { - queryId?: uint64 - remoteChainSelector: uint64 - remotePoolAddress: CrossChainAddress - }) { - return TokenPool_AddRemotePool.toCell(TokenPool_AddRemotePool.create(body)); - } - - static createCellOfTokenPoolRemoveRemotePool(body: { - queryId?: uint64 - remoteChainSelector: uint64 - remotePoolAddress: CrossChainAddress - }) { - return TokenPool_RemoveRemotePool.toCell(TokenPool_RemoveRemotePool.create(body)); - } - - static createCellOfTokenPoolSetDynamicConfig(body: { - queryId?: uint64 - router: c.Address - rateLimitAdmin?: c.Address | null /* = null */ - feeAdmin?: c.Address | null /* = null */ - }) { - return TokenPool_SetDynamicConfig.toCell(TokenPool_SetDynamicConfig.create(body)); - } - - static createCellOfTokenPoolSetAllowedFinalityConfig(body: { - queryId?: uint64 - allowedFinalityConfig: uint32 - }) { - return TokenPool_SetAllowedFinalityConfig.toCell(TokenPool_SetAllowedFinalityConfig.create(body)); - } - - static createCellOfTokenPoolSetAdvancedPoolHooks(body: { - queryId?: uint64 - advancedPoolHooks: c.Address | null - }) { - return TokenPool_SetAdvancedPoolHooks.toCell(TokenPool_SetAdvancedPoolHooks.create(body)); - } - - static createCellOfTokenPoolSetDeployableCode(body: { - queryId?: uint64 - deployableCode: c.Cell | null - }) { - return TokenPool_SetDeployableCode.toCell(TokenPool_SetDeployableCode.create(body)); - } - - static createCellOfTokenPoolSetAllowedDepositNamespaces(body: { - queryId?: uint64 - allowedDepositNamespaces: Set - }) { - return TokenPool_SetAllowedDepositNamespaces.toCell(TokenPool_SetAllowedDepositNamespaces.create(body)); - } - - static createCellOfTokenPoolSetRateLimitConfig(body: { - queryId?: uint64 - updates: SnakedCell - }) { - return TokenPool_SetRateLimitConfig.toCell(TokenPool_SetRateLimitConfig.create(body)); - } - - static createCellOfTokenPoolApplyTokenTransferFeeConfigUpdates(body: { - queryId?: uint64 - updates: SnakedCell - disableChainSelectors: SnakedCell - }) { - return TokenPool_ApplyTokenTransferFeeConfigUpdates.toCell(TokenPool_ApplyTokenTransferFeeConfigUpdates.create(body)); - } - - static createCellOfTokenPoolSetRMNProxy(body: { - queryId?: uint64 - rmnProxy: c.Address | null - }) { - return TokenPool_SetRMNProxy.toCell(TokenPool_SetRMNProxy.create(body)); - } - - static createCellOfTokenPoolSetCursedSubjects(body: { - queryId?: uint64 - cursedSubjects: CursedSubjects - }) { - return TokenPool_SetCursedSubjects.toCell(TokenPool_SetCursedSubjects.create(body)); - } - - static createCellOfJettonWithdrawableWithdraw(body: { - queryId?: uint64 - transfers: array - }) { - return JettonWithdrawable_Withdraw.toCell(JettonWithdrawable_Withdraw.create(body)); - } - - async sendDeploy(provider: ContractProvider, via: Sender, msgValue: coins, extraOptions?: ExtraSendOptions) { - return provider.internal(via, { - value: msgValue, - body: c.Cell.EMPTY, - ...extraOptions - }); - } - - send(provider: ContractProvider, via: Sender, msgValue: coins, body: c.Cell, extraOptions?: ExtraSendOptions): Promise { - return provider.internal(via, { - value: msgValue, - body, - ...extraOptions - }); - } - - async sendTokenPoolLockOrBurn(provider: ContractProvider, via: Sender, msgValue: coins, body: { - queryId?: uint64 - request: TokenPool_LockOrBurnInV1 - requestedFinalityConfig: uint32 - tokenArgs: c.Cell | null - replyTo: c.Address | null - }, extraOptions?: ExtraSendOptions) { - return provider.internal(via, { - value: msgValue, - body: TokenPool_LockOrBurn.toCell(TokenPool_LockOrBurn.create(body)), - ...extraOptions - }); - } - - async sendTransferNotificationForRecipient(provider: ContractProvider, via: Sender, msgValue: coins, body: { - queryId?: uint64 - jettonAmount: coins - transferInitiator: c.Address | null - forwardPayload: ForwardPayloadRemainder - }, extraOptions?: ExtraSendOptions) { - return provider.internal(via, { - value: msgValue, - body: TransferNotificationForRecipient.toCell(TransferNotificationForRecipient.create(body)), - ...extraOptions - }); - } - - async sendTokenPoolPreflightCheckFinished(provider: ContractProvider, via: Sender, msgValue: coins, body: { - queryId?: uint64 - forwardPayload: TokenPool_LockOrBurnForwardPayload - }, extraOptions?: ExtraSendOptions) { - return provider.internal(via, { - value: msgValue, - body: TokenPool_PreflightCheckFinished.toCell(TokenPool_PreflightCheckFinished.create(body)), - ...extraOptions - }); - } - - async sendTokenPoolPreflightCheckFailed(provider: ContractProvider, via: Sender, msgValue: coins, body: { - queryId?: uint64 - forwardPayload: TokenPool_LockOrBurnForwardPayload - }, extraOptions?: ExtraSendOptions) { - return provider.internal(via, { - value: msgValue, - body: TokenPool_PreflightCheckFailed.toCell(TokenPool_PreflightCheckFailed.create(body)), - ...extraOptions - }); - } - - async sendTokenPoolReleaseOrMint(provider: ContractProvider, via: Sender, msgValue: coins, body: { - queryId?: uint64 - request: TokenPool_ReleaseOrMintInV1 - requestedFinalityConfig: uint32 - replyTo?: c.Address | null /* = null */ - }, extraOptions?: ExtraSendOptions) { - return provider.internal(via, { - value: msgValue, - body: TokenPool_ReleaseOrMint.toCell(TokenPool_ReleaseOrMint.create(body)), - ...extraOptions - }); - } - - async sendTokenPoolPostflightCheckFinished(provider: ContractProvider, via: Sender, msgValue: coins, body: { - queryId?: uint64 - forwardPayload: TokenPool_ReleaseOrMintForwardPayload - }, extraOptions?: ExtraSendOptions) { - return provider.internal(via, { - value: msgValue, - body: TokenPool_PostflightCheckFinished.toCell(TokenPool_PostflightCheckFinished.create(body)), - ...extraOptions - }); - } - - async sendTokenPoolPostflightCheckFailed(provider: ContractProvider, via: Sender, msgValue: coins, body: { - queryId?: uint64 - forwardPayload: TokenPool_ReleaseOrMintForwardPayload - }, extraOptions?: ExtraSendOptions) { - return provider.internal(via, { - value: msgValue, - body: TokenPool_PostflightCheckFailed.toCell(TokenPool_PostflightCheckFailed.create(body)), - ...extraOptions - }); - } - - async sendTokenPoolGetCCVs(provider: ContractProvider, via: Sender, msgValue: coins, body: { - queryId?: uint64 - localToken: c.Address - remoteChainSelector: uint64 - amount: coins - requestedFinalityConfig: uint32 - direction: uint8 - extraData: c.Cell | null - replyTo: c.Address - forwardPayload: c.Cell | null - }, extraOptions?: ExtraSendOptions) { - return provider.internal(via, { - value: msgValue, - body: TokenPool_GetCCVs.toCell(TokenPool_GetCCVs.create(body)), - ...extraOptions - }); - } - - async sendTokenPoolGetCCVsAndFees(provider: ContractProvider, via: Sender, msgValue: coins, body: { - queryId?: uint64 - localToken: c.Address - remoteChainSelector: uint64 - amount: coins - requestedFinalityConfig: uint32 - direction: uint8 - extraData: c.Cell | null - forwardPayload: c.Cell | null - }, extraOptions?: ExtraSendOptions) { - return provider.internal(via, { - value: msgValue, - body: TokenPool_GetCCVsAndFees.toCell(TokenPool_GetCCVsAndFees.create(body)), - ...extraOptions - }); - } - - async sendTokenPoolQueryCCVsReply(provider: ContractProvider, via: Sender, msgValue: coins, body: { - queryId?: uint64 - requiredCCVs: SnakedCell - replyPayload: c.Cell | null - }, extraOptions?: ExtraSendOptions) { - return provider.internal(via, { - value: msgValue, - body: TokenPool_QueryCCVsReply.toCell(TokenPool_QueryCCVsReply.create(body)), - ...extraOptions - }); - } - - async sendTokenPoolApplyChainUpdates(provider: ContractProvider, via: Sender, msgValue: coins, body: { - queryId?: uint64 - remoteChainSelectorsToRemove: SnakedCell - chainsToAdd: SnakedCell - }, extraOptions?: ExtraSendOptions) { - return provider.internal(via, { - value: msgValue, - body: TokenPool_ApplyChainUpdates.toCell(TokenPool_ApplyChainUpdates.create(body)), - ...extraOptions - }); - } - - async sendTokenPoolAddRemotePool(provider: ContractProvider, via: Sender, msgValue: coins, body: { - queryId?: uint64 - remoteChainSelector: uint64 - remotePoolAddress: CrossChainAddress - }, extraOptions?: ExtraSendOptions) { - return provider.internal(via, { - value: msgValue, - body: TokenPool_AddRemotePool.toCell(TokenPool_AddRemotePool.create(body)), - ...extraOptions - }); - } - - async sendTokenPoolRemoveRemotePool(provider: ContractProvider, via: Sender, msgValue: coins, body: { - queryId?: uint64 - remoteChainSelector: uint64 - remotePoolAddress: CrossChainAddress - }, extraOptions?: ExtraSendOptions) { - return provider.internal(via, { - value: msgValue, - body: TokenPool_RemoveRemotePool.toCell(TokenPool_RemoveRemotePool.create(body)), - ...extraOptions - }); - } - - async sendTokenPoolSetDynamicConfig(provider: ContractProvider, via: Sender, msgValue: coins, body: { - queryId?: uint64 - router: c.Address - rateLimitAdmin?: c.Address | null /* = null */ - feeAdmin?: c.Address | null /* = null */ - }, extraOptions?: ExtraSendOptions) { - return provider.internal(via, { - value: msgValue, - body: TokenPool_SetDynamicConfig.toCell(TokenPool_SetDynamicConfig.create(body)), - ...extraOptions - }); - } - - async sendTokenPoolSetAllowedFinalityConfig(provider: ContractProvider, via: Sender, msgValue: coins, body: { - queryId?: uint64 - allowedFinalityConfig: uint32 - }, extraOptions?: ExtraSendOptions) { - return provider.internal(via, { - value: msgValue, - body: TokenPool_SetAllowedFinalityConfig.toCell(TokenPool_SetAllowedFinalityConfig.create(body)), - ...extraOptions - }); - } - - async sendTokenPoolSetAdvancedPoolHooks(provider: ContractProvider, via: Sender, msgValue: coins, body: { - queryId?: uint64 - advancedPoolHooks: c.Address | null - }, extraOptions?: ExtraSendOptions) { - return provider.internal(via, { - value: msgValue, - body: TokenPool_SetAdvancedPoolHooks.toCell(TokenPool_SetAdvancedPoolHooks.create(body)), - ...extraOptions - }); - } - - async sendTokenPoolSetDeployableCode(provider: ContractProvider, via: Sender, msgValue: coins, body: { - queryId?: uint64 - deployableCode: c.Cell | null - }, extraOptions?: ExtraSendOptions) { - return provider.internal(via, { - value: msgValue, - body: TokenPool_SetDeployableCode.toCell(TokenPool_SetDeployableCode.create(body)), - ...extraOptions - }); - } - - async sendTokenPoolSetAllowedDepositNamespaces(provider: ContractProvider, via: Sender, msgValue: coins, body: { - queryId?: uint64 - allowedDepositNamespaces: Set - }, extraOptions?: ExtraSendOptions) { - return provider.internal(via, { - value: msgValue, - body: TokenPool_SetAllowedDepositNamespaces.toCell(TokenPool_SetAllowedDepositNamespaces.create(body)), - ...extraOptions - }); - } - - async sendTokenPoolSetRateLimitConfig(provider: ContractProvider, via: Sender, msgValue: coins, body: { - queryId?: uint64 - updates: SnakedCell - }, extraOptions?: ExtraSendOptions) { - return provider.internal(via, { - value: msgValue, - body: TokenPool_SetRateLimitConfig.toCell(TokenPool_SetRateLimitConfig.create(body)), - ...extraOptions - }); - } - - async sendTokenPoolApplyTokenTransferFeeConfigUpdates(provider: ContractProvider, via: Sender, msgValue: coins, body: { - queryId?: uint64 - updates: SnakedCell - disableChainSelectors: SnakedCell - }, extraOptions?: ExtraSendOptions) { - return provider.internal(via, { - value: msgValue, - body: TokenPool_ApplyTokenTransferFeeConfigUpdates.toCell(TokenPool_ApplyTokenTransferFeeConfigUpdates.create(body)), - ...extraOptions - }); - } - - async sendTokenPoolSetRMNProxy(provider: ContractProvider, via: Sender, msgValue: coins, body: { - queryId?: uint64 - rmnProxy: c.Address | null - }, extraOptions?: ExtraSendOptions) { - return provider.internal(via, { - value: msgValue, - body: TokenPool_SetRMNProxy.toCell(TokenPool_SetRMNProxy.create(body)), - ...extraOptions - }); - } - - async sendTokenPoolSetCursedSubjects(provider: ContractProvider, via: Sender, msgValue: coins, body: { - queryId?: uint64 - cursedSubjects: CursedSubjects - }, extraOptions?: ExtraSendOptions) { - return provider.internal(via, { - value: msgValue, - body: TokenPool_SetCursedSubjects.toCell(TokenPool_SetCursedSubjects.create(body)), - ...extraOptions - }); - } - - async sendJettonWithdrawableWithdraw(provider: ContractProvider, via: Sender, msgValue: coins, body: { - queryId?: uint64 - transfers: array - }, extraOptions?: ExtraSendOptions) { - return provider.internal(via, { - value: msgValue, - body: JettonWithdrawable_Withdraw.toCell(JettonWithdrawable_Withdraw.create(body)), - ...extraOptions - }); - } -} From 40b5e09555eac25cdc6f4cc94d9ad186b032a446 Mon Sep 17 00:00:00 2001 From: Kristijan Date: Tue, 15 Sep 2026 12:16:06 +0200 Subject: [PATCH 11/23] bindings: model AllowedDepositNamespaces as tlbe.Dict[uint32, struct{}] Replace the raw *cell.Dictionary ("dict 32" tag) for the pool's AllowedDepositNamespaces with *tlbe.Dict[uint32, struct{}] (tlb:"." so it routes through tlbe.Dict's cell marshaller rather than tonutils-go's hard *dict N* type assertion). The value is a unit-value set (map on-chain). A struct{} value encodes to an empty, 0-bit inline leaf, so the wire form is byte-identical to the previous dict 32 encoding (verified by a new round-trip test that hashes both encodings). This also gives the field explicit set semantics and tlbe's JSON tooling support. The nil *cell.Dictionary trick for "empty map" no longer applies on the "." tag path (a nil *Dict errors), so deployment init data now passes tlbe.NewEmptyDict[uint32, struct{}]() and the getter decodes via tlbe.NewDictFromDictionary (nil-safe), matching the deposit Beneficiaries precedent. CursedSubjects stays a raw *cell.Dictionary: its values are not unit (they carry an uint128 timestamp) and it is serialized through the "dict N" tag path. --- deployment/ccip/1_6_0/sequences/tokens.go | 5 +- pkg/ccip/bindings/tokenpool/reader.go | 16 ++--- pkg/ccip/bindings/tokenpool/types.go | 33 +++++---- pkg/ccip/bindings/tokenpool/types_test.go | 82 +++++++++++++++++++++++ 4 files changed, 114 insertions(+), 22 deletions(-) create mode 100644 pkg/ccip/bindings/tokenpool/types_test.go diff --git a/deployment/ccip/1_6_0/sequences/tokens.go b/deployment/ccip/1_6_0/sequences/tokens.go index 669c0215c..6f0912d28 100644 --- a/deployment/ccip/1_6_0/sequences/tokens.go +++ b/deployment/ccip/1_6_0/sequences/tokens.go @@ -402,8 +402,9 @@ func (a *TonTokenAdapter) DeployTokenPoolForToken() *cldf_ops.Sequence[tokensapi Router: &routerAddr, RateLimitAdmin: rateLimitAdmin, FeeAdmin: feeAdmin, - // Unit-value dict (map); nil serializes as an empty map. - AllowedDepositNamespaces: nil, + // Unit-value set (map); an empty dict serializes as an + // empty map. Must be non-nil: the tlb:"." tag errors on a nil dict. + AllowedDepositNamespaces: tlbe.NewEmptyDict[uint32, struct{}](), }, JettonClient: tokenpool.JettonClient{ MasterAddress: tokenAddr, diff --git a/pkg/ccip/bindings/tokenpool/reader.go b/pkg/ccip/bindings/tokenpool/reader.go index 7f062ccb8..823978193 100644 --- a/pkg/ccip/bindings/tokenpool/reader.go +++ b/pkg/ccip/bindings/tokenpool/reader.go @@ -14,6 +14,7 @@ import ( "github.com/smartcontractkit/chainlink-ton/cciplib/ccip/bindings/common" "github.com/smartcontractkit/chainlink-ton/cciplib/ccip/bindings/ownable2step" "github.com/smartcontractkit/chainlink-ton/cciplib/ton/parser" + "github.com/smartcontractkit/chainlink-ton/cciplib/ton/tlbe" "github.com/smartcontractkit/chainlink-ton/cciplib/ton/tvm" ) @@ -182,14 +183,13 @@ var GetDynamicConfig = tvm.NewNoArgsGetter(tvm.NoArgsOpts[DynamicConfig]{ if err != nil { return cfg, fmt.Errorf("error getting Cell(3) - allowedDepositNamespaces: %w", err) } - if dictCell == nil { - cfg.AllowedDepositNamespaces = cell.NewDict(32) - } else { - dict := dictCell.AsDict(32) // uint32 keys - if dict == nil { - dict = cell.NewDict(32) - } - cfg.AllowedDepositNamespaces = dict + var dict *cell.Dictionary + if dictCell != nil { + dict = dictCell.AsDict(32) // uint32 keys + } + cfg.AllowedDepositNamespaces, err = tlbe.NewDictFromDictionary[uint32, struct{}](dict) + if err != nil { + return cfg, fmt.Errorf("error converting dict to tlbe.Dict - allowedDepositNamespaces: %w", err) } return cfg, nil diff --git a/pkg/ccip/bindings/tokenpool/types.go b/pkg/ccip/bindings/tokenpool/types.go index 6b57f64a3..07868105b 100644 --- a/pkg/ccip/bindings/tokenpool/types.go +++ b/pkg/ccip/bindings/tokenpool/types.go @@ -48,13 +48,20 @@ const ( // DynamicConfig holds the router and admin addresses for the pool. // -// AllowedDepositNamespaces is a unit-value set (map on-chain), so it -// is modelled as a raw *cell.Dictionary like CursedSubjects below. +// AllowedDepositNamespaces is a unit-value set (map on-chain): a key +// is present iff the corresponding deployable namespace is allowed as a deposit +// source. It is modelled as *tlbe.Dict[uint32, struct{}] so the "set" semantics +// are explicit and the value marshals through tlbe's JSON support, while still +// producing the exact map wire form (a struct{} value encodes to an +// empty, 0-bit inline leaf). The field uses the tlb:"." tag rather than +// "dict 32" because tonutils-go's tlb encoder type-asserts "dict N" fields +// directly to *cell.Dictionary; the "." tag instead routes through tlbe.Dict's +// ToCell marshaller. type DynamicConfig struct { - Router *address.Address `tlb:"addr"` - RateLimitAdmin *address.Address `tlb:"addr"` - FeeAdmin *address.Address `tlb:"addr"` - AllowedDepositNamespaces *cell.Dictionary `tlb:"dict 32"` + Router *address.Address `tlb:"addr"` + RateLimitAdmin *address.Address `tlb:"addr"` + FeeAdmin *address.Address `tlb:"addr"` + AllowedDepositNamespaces *tlbe.Dict[uint32, struct{}] `tlb:"."` } // LocalPolicy holds the pool's independently managed RMN policy. It is @@ -63,9 +70,11 @@ type DynamicConfig struct { // addr_none. Ramp access is no longer pool state: the Router is the only entry // point of every pool (TokenPool.onlyRouter). // -// Dict fields use *cell.Dictionary rather than *tlbe.Dict: tonutils-go's tlb -// encoder (used to build init data for contract deploys, see -// deployment/utils/operation/deploy_ton_contract.go) type-asserts "dict N" +// CursedSubjects is kept as a raw *cell.Dictionary because its values are not +// unit (they carry an uint128 timestamp), so tlbe.Dict's value encoding would +// not apply, and it is serialized through tonutils-go's "dict N" tag path (used +// to build init data for contract deploys, see +// deployment/utils/operation/deploy_ton_contract.go), which type-asserts such // fields directly to *cell.Dictionary and panics on any other type. type LocalPolicy struct { CursedSubjects CursedSubjects `tlb:"."` @@ -326,9 +335,9 @@ type SetDeployableCode struct { // SetAllowedDepositNamespaces sets the Deployables namespaces the pool accepts as deposit sources. type SetAllowedDepositNamespaces struct { - _ tlb.Magic `tlb:"#84384142" json:"-"` //nolint:revive // (opcode) should stay uninitialized - QueryID uint64 `tlb:"## 64"` - AllowedDepositNamespaces *cell.Dictionary `tlb:"dict 32"` + _ tlb.Magic `tlb:"#84384142" json:"-"` //nolint:revive // (opcode) should stay uninitialized + QueryID uint64 `tlb:"## 64"` + AllowedDepositNamespaces *tlbe.Dict[uint32, struct{}] `tlb:"."` } // SetRateLimitConfig sets the rate limit configurations. diff --git a/pkg/ccip/bindings/tokenpool/types_test.go b/pkg/ccip/bindings/tokenpool/types_test.go new file mode 100644 index 000000000..3b737f84f --- /dev/null +++ b/pkg/ccip/bindings/tokenpool/types_test.go @@ -0,0 +1,82 @@ +package tokenpool + +import ( + "testing" + + "github.com/stretchr/testify/require" + "github.com/xssnick/tonutils-go/address" + "github.com/xssnick/tonutils-go/tlb" + "github.com/xssnick/tonutils-go/tvm/cell" + + "github.com/smartcontractkit/chainlink-ton/cciplib/ton/tlbe" +) + +// TestDynamicConfig_AllowedDepositNamespaces_WireFormat verifies that modelling +// AllowedDepositNamespaces as *tlbe.Dict[uint32, struct{}] (tlb:".") produces +// exactly the same wire form as a raw *cell.Dictionary serialized through the +// "dict 32" tag: a map whose unit values are 0-bit inline leaves. +func TestDynamicConfig_AllowedDepositNamespaces_WireFormat(t *testing.T) { + namespaces := tlbe.NewDict[uint32, struct{}](map[uint32]struct{}{ + 1: {}, + 42: {}, + }) + + cfg := DynamicConfig{ + AllowedDepositNamespaces: namespaces, + } + + cfgCell, err := tlb.ToCell(cfg) + require.NoError(t, err) + + // Same layout, but the dict is a raw *cell.Dictionary through the "dict 32" + // tag path (the encoding used before this change). + rawDict := cell.NewDict(32) + for k := range namespaces.AsMap() { + keyCell := cell.BeginCell().MustStoreUInt(uint64(k), 32).EndCell() + unitCell := cell.BeginCell().EndCell() // map<_,()> value: 0 bits, 0 refs + require.NoError(t, rawDict.Set(keyCell, unitCell)) + } + + rawStruct := struct { + Router *address.Address `tlb:"addr"` + RateLimitAdmin *address.Address `tlb:"addr"` + FeeAdmin *address.Address `tlb:"addr"` + AllowedDepositNamespaces *cell.Dictionary `tlb:"dict 32"` + }{AllowedDepositNamespaces: rawDict} + rawCell, err := tlb.ToCell(rawStruct) + require.NoError(t, err) + + require.Equal(t, rawCell.Hash(), cfgCell.Hash(), + "tlbe.Dict struct{} encoding must match the raw dict 32 wire form") +} + +// TestDynamicConfig_AllowedDepositNamespaces_RoundTrip verifies encode/decode +// through tonutils-go's tlb loader (using the tlb:"." marshaller path). +func TestDynamicConfig_AllowedDepositNamespaces_RoundTrip(t *testing.T) { + namespaces := tlbe.NewDict[uint32, struct{}](map[uint32]struct{}{ + 7: {}, + 13: {}, + }) + + cfg := DynamicConfig{AllowedDepositNamespaces: namespaces} + + c, err := tlb.ToCell(cfg) + require.NoError(t, err) + + var decoded DynamicConfig + require.NoError(t, tlb.LoadFromCell(&decoded, c.BeginParse())) + require.Len(t, decoded.AllowedDepositNamespaces.AsMap(), 2) + _, ok := decoded.AllowedDepositNamespaces.Get(7) + require.True(t, ok) + _, ok = decoded.AllowedDepositNamespaces.Get(13) + require.True(t, ok) + + // Empty set round-trips as an empty map. + empty := DynamicConfig{AllowedDepositNamespaces: tlbe.NewEmptyDict[uint32, struct{}]()} + emptyCell, err := tlb.ToCell(empty) + require.NoError(t, err) + + var decodedEmpty DynamicConfig + require.NoError(t, tlb.LoadFromCell(&decodedEmpty, emptyCell.BeginParse())) + require.Empty(t, decodedEmpty.AllowedDepositNamespaces.AsMap()) +} From 5286996f9fde2ec1ab7897bd1ca304858b76c842 Mon Sep 17 00:00:00 2001 From: Kristijan Date: Tue, 15 Sep 2026 12:48:52 +0200 Subject: [PATCH 12/23] tlbe: add comparable Uint128; use tlbe.Dict for CursedSubjects Add tlbe.Uint128, a 128-bit unsigned integer that is a comparable value type (two uint64 words), so it can key a tlbe.Dict directly and compare by value. This fixes a class of bug present in Uint160/Uint256 (and any big.Int alias): they are not comparable, so pointer-keyed dicts (e.g. Dict[*Uint256, *cell.Cell]) mis-key on pointer identity, and decoding them via Dict.LoadFromDictionary panics in tonutils' reflection path because a **T does not satisfy tlb.Unmarshaler when T has a pointer receiver. Uint128 avoids both: value receiver marshalling and value equality. Use it for the pool's CursedSubjects, which is map on-chain: replace the raw *cell.Dictionary ("dict 128") with *tlbe.Dict[tlbe.Uint128, struct{}] (tlb:"."). A struct{} value encodes to a 0-bit inline leaf, so the wire form is unchanged (verified by a new test hashing both encodings). Deployment init now passes an empty, non-nil dict (the "." tag errors on nil). Also drops the incorrect "values are not unit" comment, which contradicted the on-chain map. --- cciplib/ton/tlbe/biguint.go | 100 ++++++++++++++++++++++ cciplib/ton/tlbe/uint128_test.go | 97 +++++++++++++++++++++ deployment/ccip/1_6_0/sequences/tokens.go | 9 +- pkg/ccip/bindings/tokenpool/types.go | 21 +---- pkg/ccip/bindings/tokenpool/types_test.go | 47 ++++++++++ 5 files changed, 254 insertions(+), 20 deletions(-) create mode 100644 cciplib/ton/tlbe/uint128_test.go diff --git a/cciplib/ton/tlbe/biguint.go b/cciplib/ton/tlbe/biguint.go index 1374b9f17..1850d1258 100644 --- a/cciplib/ton/tlbe/biguint.go +++ b/cciplib/ton/tlbe/biguint.go @@ -83,6 +83,106 @@ func (b BigUint) toCell(bits uint) (*cell.Cell, error) { return builder.EndCell(), nil } +// Uint128 is a 128-bit unsigned integer that is safe to use as a dictionary key. +// +// Unlike [Uint160]/[Uint256] (which alias big.Int and are therefore neither +// comparable nor usable as map keys), Uint128 is a comparable value type, so it +// can key a tlbe.Dict directly and compares by value rather than pointer +// identity. +// +// The bit width is 128, matching Tolk uint128 (e.g. the cursed-subject map keys: +// map). +type Uint128 struct { + Hi uint64 + Lo uint64 +} + +// NewUint128 builds a Uint128 from a big.Int, interpreting it as an unsigned +// 128-bit value (the input is masked to 128 bits). +func NewUint128(v *big.Int) Uint128 { + u := AsUnsigned(v, 128) + lo := new(big.Int).And(u, maxUint64) // compute before Rsh mutates u in place + hi := new(big.Int).Rsh(u, 64) + + return Uint128{Hi: hi.Uint64(), Lo: lo.Uint64()} +} + +var maxUint64 = new(big.Int).SetUint64(^uint64(0)) + +func (Uint128) BitsLen() uint { + return 128 +} + +// ToBigInt returns the value as a new big.Int. +func (x Uint128) ToBigInt() *big.Int { + hi := new(big.Int).SetUint64(x.Hi) + hi.Lsh(hi, 64) + return hi.Or(hi, new(big.Int).SetUint64(x.Lo)) +} + +func (x Uint128) String() string { + return x.ToBigInt().String() +} + +// LoadFromCell implements tlb.Unmarshaler. +func (x *Uint128) LoadFromCell(loader *cell.Slice) error { + hi, err := loader.LoadUInt(64) + if err != nil { + return fmt.Errorf("failed to load Uint128 high word: %w", err) + } + lo, err := loader.LoadUInt(64) + if err != nil { + return fmt.Errorf("failed to load Uint128 low word: %w", err) + } + + x.Hi, x.Lo = hi, lo + return nil +} + +// ToCell implements tlb.Marshaller. +func (x Uint128) ToCell() (*cell.Cell, error) { + return cell.BeginCell().MustStoreUInt(x.Hi, 64).MustStoreUInt(x.Lo, 64).EndCell(), nil +} + +// MarshalJSON implements the [encoding/json.Marshaler] interface, emitting a +// canonical hexadecimal string (matching Uint160/Uint256). +func (x Uint128) MarshalJSON() ([]byte, error) { + return []byte(`"0x` + x.ToBigInt().Text(16) + `"`), nil +} + +// UnmarshalJSON implements the [encoding/json.Unmarshaler] interface. +func (x *Uint128) UnmarshalJSON(data []byte) error { + // Try a JSON string first (hex or decimal). + var s string + if err := json.Unmarshal(data, &s); err == nil { + base := 10 + if strings.HasPrefix(s, "0x") || strings.HasPrefix(s, "0X") { + base = 16 + s = s[2:] + } + b, ok := new(big.Int).SetString(s, base) + if !ok { + return fmt.Errorf("failed to parse Uint128 string %q", s) + } + if b.Sign() < 0 || b.BitLen() > 128 { + return errors.New("failed to unmarshal Uint128 from JSON: out of range") + } + *x = NewUint128(b) + return nil + } + + // Fallback: plain JSON number. + b := new(big.Int) + if err := b.UnmarshalJSON(data); err != nil { + return fmt.Errorf("failed to unmarshal Uint128 from JSON: %w", err) + } + if b.Sign() < 0 || b.BitLen() > 128 { + return errors.New("failed to unmarshal Uint128 from JSON: out of range") + } + *x = NewUint128(b) + return nil +} + // Uint160 is a 160-bit unsigned integer wrapper. type Uint160 big.Int diff --git a/cciplib/ton/tlbe/uint128_test.go b/cciplib/ton/tlbe/uint128_test.go new file mode 100644 index 000000000..975a5e95f --- /dev/null +++ b/cciplib/ton/tlbe/uint128_test.go @@ -0,0 +1,97 @@ +package tlbe // tlb extras + +import ( + "encoding/json" + "math/big" + "testing" + + "github.com/stretchr/testify/require" + "github.com/xssnick/tonutils-go/tlb" +) + +func TestUint128_Values(t *testing.T) { + // A value above the 64-bit range exercises the high word. + v := new(big.Int).Add(new(big.Int).Lsh(big.NewInt(1), 100), big.NewInt(12345)) + + u := NewUint128(v) + require.Equal(t, uint64(1<<36), u.Hi) // 2^100 >> 64 == 2^36 + require.Equal(t, uint64(12345), u.Lo) + require.Equal(t, v, u.ToBigInt()) + + // Zero and max round-trip through the words. + require.Equal(t, big.NewInt(0), NewUint128(big.NewInt(0)).ToBigInt()) + + max := new(big.Int).Sub(new(big.Int).Lsh(big.NewInt(1), 128), big.NewInt(1)) + require.Equal(t, max, NewUint128(max).ToBigInt()) +} + +func TestUint128_CellRoundTrip(t *testing.T) { + v := new(big.Int).Add(new(big.Int).Lsh(big.NewInt(7), 90), big.NewInt(42)) + original := NewUint128(v) + + c, err := original.ToCell() + require.NoError(t, err) + require.Equal(t, uint(128), c.BitsSize()) + + var decoded Uint128 + require.NoError(t, decoded.LoadFromCell(c.BeginParse())) + require.Equal(t, original, decoded) + require.Equal(t, v, decoded.ToBigInt()) +} + +func TestUint128_UsableAsDictKey(t *testing.T) { + // The whole point: Uint128 is comparable, so it keys a Dict by value and the + // key decodes correctly via NewDictFromDictionary (unlike *Uint256 keys). + d := NewDict[Uint128, struct{}](map[Uint128]struct{}{ + NewUint128(big.NewInt(5)): {}, + NewUint128(new(big.Int).Lsh(big.NewInt(1), 127)): {}, + }) + + c, err := d.ToCell() + require.NoError(t, err) + + dict, err := c.BeginParse().LoadDict(128) + require.NoError(t, err) + + restored, err := NewDictFromDictionary[Uint128, struct{}](dict) + require.NoError(t, err) + require.Len(t, restored.AsMap(), 2) + + _, ok := restored.Get(NewUint128(big.NewInt(5))) + require.True(t, ok) + _, ok = restored.Get(NewUint128(new(big.Int).Lsh(big.NewInt(1), 127))) + require.True(t, ok) +} + +func TestUint128_JSONRoundTrip(t *testing.T) { + u := NewUint128(new(big.Int).SetUint64(255)) + + payload, err := json.Marshal(u) + require.NoError(t, err) + require.JSONEq(t, `"0xff"`, string(payload)) + + var decoded Uint128 + require.NoError(t, json.Unmarshal(payload, &decoded)) + require.Equal(t, u, decoded) +} + +// Guards the generic path used by CursedSubjects: a struct field with a +// tlb:"." tag holding a *Dict[Uint128, struct{}]. +type uint128SetHolder struct { + Subjects *Dict[Uint128, struct{}] `tlb:"."` +} + +func TestUint128_DictStructFieldRoundTrip(t *testing.T) { + original := uint128SetHolder{ + Subjects: NewDict[Uint128, struct{}](map[Uint128]struct{}{ + NewUint128(big.NewInt(3)): {}, + }), + } + + c, err := tlb.ToCell(original) + require.NoError(t, err) + + var decoded uint128SetHolder + require.NoError(t, tlb.LoadFromCell(&decoded, c.BeginParse())) + require.Len(t, decoded.Subjects.AsMap(), 1) +} diff --git a/deployment/ccip/1_6_0/sequences/tokens.go b/deployment/ccip/1_6_0/sequences/tokens.go index 6f0912d28..5977ec54a 100644 --- a/deployment/ccip/1_6_0/sequences/tokens.go +++ b/deployment/ccip/1_6_0/sequences/tokens.go @@ -414,9 +414,12 @@ func (a *TonTokenAdapter) DeployTokenPoolForToken() *cldf_ops.Sequence[tokensapi AdvancedPoolHooks: nil, }, LocalPolicy: tokenpool.LocalPolicy{ - // nil dict serializes as an empty map (a single "no entries" bit), - // matching the Tolk contract's createEmptyMap() default. - CursedSubjects: tokenpool.CursedSubjects{Data: nil}, + // An empty dict serializes as an empty map (a single "no entries" + // bit), matching the Tolk contract's createEmptyMap() default. + // Must be non-nil: the tlb:"." tag errors on a nil dict. + CursedSubjects: tokenpool.CursedSubjects{ + Data: tlbe.NewEmptyDict[tlbe.Uint128, struct{}](), + }, }, TokenDecimals: defaultJettonDecimals, RemoteChainConfigs: nil, diff --git a/pkg/ccip/bindings/tokenpool/types.go b/pkg/ccip/bindings/tokenpool/types.go index 07868105b..f44e4c1f1 100644 --- a/pkg/ccip/bindings/tokenpool/types.go +++ b/pkg/ccip/bindings/tokenpool/types.go @@ -49,14 +49,7 @@ const ( // DynamicConfig holds the router and admin addresses for the pool. // // AllowedDepositNamespaces is a unit-value set (map on-chain): a key -// is present iff the corresponding deployable namespace is allowed as a deposit -// source. It is modelled as *tlbe.Dict[uint32, struct{}] so the "set" semantics -// are explicit and the value marshals through tlbe's JSON support, while still -// producing the exact map wire form (a struct{} value encodes to an -// empty, 0-bit inline leaf). The field uses the tlb:"." tag rather than -// "dict 32" because tonutils-go's tlb encoder type-asserts "dict N" fields -// directly to *cell.Dictionary; the "." tag instead routes through tlbe.Dict's -// ToCell marshaller. +// is present if the corresponding deployable namespace is allowed as a deposit source. type DynamicConfig struct { Router *address.Address `tlb:"addr"` RateLimitAdmin *address.Address `tlb:"addr"` @@ -69,20 +62,14 @@ type DynamicConfig struct { // configure a distinct RMN proxy, or disable proxy updates by setting it to // addr_none. Ramp access is no longer pool state: the Router is the only entry // point of every pool (TokenPool.onlyRouter). -// -// CursedSubjects is kept as a raw *cell.Dictionary because its values are not -// unit (they carry an uint128 timestamp), so tlbe.Dict's value encoding would -// not apply, and it is serialized through tonutils-go's "dict N" tag path (used -// to build init data for contract deploys, see -// deployment/utils/operation/deploy_ton_contract.go), which type-asserts such -// fields directly to *cell.Dictionary and panics on any other type. type LocalPolicy struct { CursedSubjects CursedSubjects `tlb:"."` } -// CursedSubjects represents the set of cursed subjects (uint128 keys with empty values). +// CursedSubjects represents the set of cursed subjects (uint128 keys with empty +// values), i.e. map on-chain. type CursedSubjects struct { - Data *cell.Dictionary `tlb:"dict 128"` + Data *tlbe.Dict[tlbe.Uint128, struct{}] `tlb:"."` } // RateLimitConfig represents a rate limiter configuration. diff --git a/pkg/ccip/bindings/tokenpool/types_test.go b/pkg/ccip/bindings/tokenpool/types_test.go index 3b737f84f..b9538aac8 100644 --- a/pkg/ccip/bindings/tokenpool/types_test.go +++ b/pkg/ccip/bindings/tokenpool/types_test.go @@ -1,6 +1,7 @@ package tokenpool import ( + "math/big" "testing" "github.com/stretchr/testify/require" @@ -50,6 +51,52 @@ func TestDynamicConfig_AllowedDepositNamespaces_WireFormat(t *testing.T) { "tlbe.Dict struct{} encoding must match the raw dict 32 wire form") } +// TestCursedSubjects_WireFormat verifies that modelling CursedSubjects.Data as +// *tlbe.Dict[tlbe.Uint128, struct{}] (tlb:".") produces the same wire form as a +// raw *cell.Dictionary serialized through the "dict 128" tag: a map +// with 0-bit unit values, inlined into the enclosing cell. +func TestCursedSubjects_WireFormat(t *testing.T) { + subjects := tlbe.NewDict[tlbe.Uint128, struct{}](map[tlbe.Uint128]struct{}{ + tlbe.NewUint128(big.NewInt(1)): {}, + tlbe.NewUint128(big.NewInt(42)): {}, + }) + + got, err := tlb.ToCell(CursedSubjects{Data: subjects}) + require.NoError(t, err) + + rawDict := cell.NewDict(128) + for k := range subjects.AsMap() { + keyCell := cell.BeginCell().MustStoreBigInt(k.ToBigInt(), 128).EndCell() + unitCell := cell.BeginCell().EndCell() // map<_,()> value: 0 bits, 0 refs + require.NoError(t, rawDict.Set(keyCell, unitCell)) + } + + want, err := tlb.ToCell(struct { + Data *cell.Dictionary `tlb:"dict 128"` + }{Data: rawDict}) + require.NoError(t, err) + + require.Equal(t, want.Hash(), got.Hash(), + "tlbe.Dict[Uint128, struct{}] encoding must match the raw dict 128 wire form") +} + +// TestCursedSubjects_RoundTrip verifies encode/decode via the tlb:"." marshaller. +func TestCursedSubjects_RoundTrip(t *testing.T) { + subjects := tlbe.NewDict[tlbe.Uint128, struct{}](map[tlbe.Uint128]struct{}{ + tlbe.NewUint128(big.NewInt(7)): {}, + }) + + c, err := tlb.ToCell(CursedSubjects{Data: subjects}) + require.NoError(t, err) + + var decoded CursedSubjects + require.NoError(t, tlb.LoadFromCell(&decoded, c.BeginParse())) + + _, ok := decoded.Data.Get(tlbe.NewUint128(big.NewInt(7))) + require.True(t, ok) + require.Equal(t, 1, decoded.Data.Len()) +} + // TestDynamicConfig_AllowedDepositNamespaces_RoundTrip verifies encode/decode // through tonutils-go's tlb loader (using the tlb:"." marshaller path). func TestDynamicConfig_AllowedDepositNamespaces_RoundTrip(t *testing.T) { From adc61b5f2ddb726046b377fc779a129a237f825a Mon Sep 17 00:00:00 2001 From: Kristijan Date: Tue, 15 Sep 2026 13:28:50 +0200 Subject: [PATCH 13/23] tlbe: make boxed uints comparable; fix pointer-key dict decode Uint160/Uint256 were declared as `type Uint160 big.Int`. That is misleading: the result is a struct containing a slice, so it is NOT comparable and has none of big.Int's methods. Two consequences: - They cannot be dictionary keys by value, which is why call sites used *tlbe.Uint256 / *tlbe.Uint160 pointer keys. - Pointer keys do not decode. A **T does not satisfy tlb.Unmarshaler when T.LoadFromCell takes a pointer receiver, so Dict.LoadFromDictionary panics inside tonutils' reflection path. RemoteChainConfig.RemotePools, mcms Signers/SeenSignedHashes/Timestamps/OpPendingCalls and rbac Roles were all affected (latent: none were decoded yet). Rework all three boxed widths (uint128/uint160/uint256) as comparable value types backed by fixed-size big-endian byte arrays, sharing one codec (uintBytes* helpers). Byte storage is required so uint160 is exactly 160 bits (a uint64-word layout would produce 192). - Uint128/Uint160/Uint256 are now comparable => proper value equality and usable as tlbe.Dict keys, matching Tolk map. - Pointer-keyed dicts switched to value keys; added a RemotePools-shaped decode regression test. - Constructors stay pointer-returning (*Uint128 etc.) because the external mcms v0.52.0 SDK assigns them into pointer fields; the API is unchanged. - Wire format is unchanged (verified by hashing the boxed encoding against the previous raw fixed-width big-endian store). - Uint160/Uint256 gain Cmp; Value() is retained as an alias for ToBigInt(). The dead BigUint helper is left in place for now (no in-repo callers). --- cciplib/ton/tlbe/biguint.go | 369 ++++++++++------------ cciplib/ton/tlbe/biguint_test.go | 28 +- cciplib/ton/tlbe/boxeduint_test.go | 185 +++++++++++ cciplib/ton/tlbe/uint128_test.go | 22 +- pkg/bindings/lib/access/rbac/types.go | 2 +- pkg/bindings/mcms/mcms/storage.go | 4 +- pkg/bindings/mcms/mcms/types.go | 4 +- pkg/bindings/mcms/timelock/storage.go | 6 +- pkg/bindings/mcms/timelock/types.go | 4 +- pkg/ccip/bindings/tokenpool/types.go | 8 +- pkg/ccip/bindings/tokenpool/types_test.go | 35 +- pkg/ton/tlbe/tlbe.go | 2 + 12 files changed, 426 insertions(+), 243 deletions(-) create mode 100644 cciplib/ton/tlbe/boxeduint_test.go diff --git a/cciplib/ton/tlbe/biguint.go b/cciplib/ton/tlbe/biguint.go index 1850d1258..1a5eb24bb 100644 --- a/cciplib/ton/tlbe/biguint.go +++ b/cciplib/ton/tlbe/biguint.go @@ -83,75 +83,81 @@ func (b BigUint) toCell(bits uint) (*cell.Cell, error) { return builder.EndCell(), nil } -// Uint128 is a 128-bit unsigned integer that is safe to use as a dictionary key. +// --- Fixed-width unsigned integers --- // -// Unlike [Uint160]/[Uint256] (which alias big.Int and are therefore neither -// comparable nor usable as map keys), Uint128 is a comparable value type, so it -// can key a tlbe.Dict directly and compares by value rather than pointer -// identity. +// Uint128/Uint160/Uint256 are boxed fixed-width unsigned integers used to model +// Tolk's uint128/uint160/uint256. They are deliberately NOT aliases of big.Int: +// big.Int is a struct containing a slice, so an alias is neither comparable nor +// usable as a map/dictionary key, and a pointer to it mis-keys (pointer +// identity) and panics when decoded through tonutils' reflection path. // -// The bit width is 128, matching Tolk uint128 (e.g. the cursed-subject map keys: -// map). -type Uint128 struct { - Hi uint64 - Lo uint64 -} +// Each type stores its value as big-endian 64-bit words in a fixed-size array, +// which makes it a comparable value type. As a result these can be used directly +// as tlbe.Dict keys (matching Tolk map) and compare +// with == rather than via a helper. +// +// All three share the same codec (the uintWords* helpers below); each type only +// declares its width and delegates. -// NewUint128 builds a Uint128 from a big.Int, interpreting it as an unsigned -// 128-bit value (the input is masked to 128 bits). -func NewUint128(v *big.Int) Uint128 { - u := AsUnsigned(v, 128) - lo := new(big.Int).And(u, maxUint64) // compute before Rsh mutates u in place - hi := new(big.Int).Rsh(u, 64) +// uintBytesFromBigInt converts v to exactly nbytes big-endian bytes, masking the +// input to bits bits first (so the sign bit is never misread). +func uintBytesFromBigInt(v *big.Int, bits uint, nbytes int) []byte { + out := make([]byte, nbytes) + AsUnsigned(v, bits).FillBytes(out) // big-endian, left-padded with zeros - return Uint128{Hi: hi.Uint64(), Lo: lo.Uint64()} + return out } -var maxUint64 = new(big.Int).SetUint64(^uint64(0)) +// uintBytesToBigInt converts big-endian bytes to an unsigned big.Int. +func uintBytesToBigInt(b []byte) *big.Int { + res := new(big.Int).SetBytes(b) + if res.Sign() == 0 { + // Return the canonical zero form (abs == nil) so it compares equal to + // big.NewInt(0). + return new(big.Int) + } -func (Uint128) BitsLen() uint { - return 128 + return res } -// ToBigInt returns the value as a new big.Int. -func (x Uint128) ToBigInt() *big.Int { - hi := new(big.Int).SetUint64(x.Hi) - hi.Lsh(hi, 64) - return hi.Or(hi, new(big.Int).SetUint64(x.Lo)) -} +// uintBytesToCell stores all bytes sequentially (8 bits each) into a single cell. +func uintBytesToCell(b []byte) (*cell.Cell, error) { + builder := cell.BeginCell() + for i, by := range b { + if err := builder.StoreUInt(uint64(by), 8); err != nil { + return nil, fmt.Errorf("failed to store byte %d: %w", i, err) + } + } -func (x Uint128) String() string { - return x.ToBigInt().String() + return builder.EndCell(), nil } -// LoadFromCell implements tlb.Unmarshaler. -func (x *Uint128) LoadFromCell(loader *cell.Slice) error { - hi, err := loader.LoadUInt(64) - if err != nil { - return fmt.Errorf("failed to load Uint128 high word: %w", err) - } - lo, err := loader.LoadUInt(64) - if err != nil { - return fmt.Errorf("failed to load Uint128 low word: %w", err) +// uintBytesFromCell loads len(dst) sequential bytes into dst. +func uintBytesFromCell(dst []byte, loader *cell.Slice) error { + for i := range dst { + by, err := loader.LoadUInt(8) + if err != nil { + return fmt.Errorf("failed to load byte %d: %w", i, err) + } + dst[i] = byte(by) } - x.Hi, x.Lo = hi, lo return nil } -// ToCell implements tlb.Marshaller. -func (x Uint128) ToCell() (*cell.Cell, error) { - return cell.BeginCell().MustStoreUInt(x.Hi, 64).MustStoreUInt(x.Lo, 64).EndCell(), nil +// uintBytesMarshalJSON emits the canonical hexadecimal string form. +func uintBytesMarshalJSON(b []byte) ([]byte, error) { + return []byte(`"0x` + uintBytesToBigInt(b).Text(16) + `"`), nil } -// MarshalJSON implements the [encoding/json.Marshaler] interface, emitting a -// canonical hexadecimal string (matching Uint160/Uint256). -func (x Uint128) MarshalJSON() ([]byte, error) { - return []byte(`"0x` + x.ToBigInt().Text(16) + `"`), nil -} +// parseUintJSON parses a JSON value (hex/decimal string, or number) into an +// unsigned big.Int that fits in bits bits. +func parseUintJSON(data []byte, bits uint) (*big.Int, error) { + var ( + b *big.Int + ok bool + ) -// UnmarshalJSON implements the [encoding/json.Unmarshaler] interface. -func (x *Uint128) UnmarshalJSON(data []byte) error { // Try a JSON string first (hex or decimal). var s string if err := json.Unmarshal(data, &s); err == nil { @@ -160,211 +166,162 @@ func (x *Uint128) UnmarshalJSON(data []byte) error { base = 16 s = s[2:] } - b, ok := new(big.Int).SetString(s, base) + b, ok = new(big.Int).SetString(s, base) if !ok { - return fmt.Errorf("failed to parse Uint128 string %q", s) + return nil, fmt.Errorf("failed to parse uint%d string %q", bits, s) } - if b.Sign() < 0 || b.BitLen() > 128 { - return errors.New("failed to unmarshal Uint128 from JSON: out of range") + } else { + // Fallback: plain JSON number. + b = new(big.Int) + if err := b.UnmarshalJSON(data); err != nil { + return nil, fmt.Errorf("failed to unmarshal uint%d from JSON: %w", bits, err) } - *x = NewUint128(b) - return nil } - // Fallback: plain JSON number. - b := new(big.Int) - if err := b.UnmarshalJSON(data); err != nil { - return fmt.Errorf("failed to unmarshal Uint128 from JSON: %w", err) - } - if b.Sign() < 0 || b.BitLen() > 128 { - return errors.New("failed to unmarshal Uint128 from JSON: out of range") + if b.Sign() < 0 || b.BitLen() > int(bits) { + return nil, fmt.Errorf("failed to unmarshal uint%d from JSON: out of range", bits) } - *x = NewUint128(b) - return nil -} - -// Uint160 is a 160-bit unsigned integer wrapper. -type Uint160 big.Int -func NewUint160(v *big.Int) *Uint160 { - return (*Uint160)(AsUnsigned(v, 160)) + return b, nil } -func (*Uint160) BitsLen() uint { - return 160 +// Uint128 is a 128-bit unsigned integer (Tolk uint128, e.g. cursed-subject map +// keys: map). See the fixed-width section note above. +type Uint128 struct { + F [16]byte } -// LoadFromCell implements tlb.Unmarshaler. -func (x *Uint160) LoadFromCell(loader *cell.Slice) error { - b := new(BigUint) - err := b.loadFromCell(x.BitsLen(), loader) - if err != nil { - return fmt.Errorf("failed to load Uint160 from cell: %w", err) - } +// NewUint128 builds a Uint128 from a big.Int, masking the input to 128 bits. +func NewUint128(v *big.Int) *Uint128 { + var a [16]byte + copy(a[:], uintBytesFromBigInt(v, 128, 16)) - *x = Uint160(*b.Value) - return nil + return &Uint128{F: a} } -// ToCell implements tlb.Marshaller. -func (x Uint160) ToCell() (*cell.Cell, error) { - b := BigUint{ - Bits: x.BitsLen(), - Value: (*big.Int)(&x), - } - return b.toCell(x.BitsLen()) -} +func (Uint128) BitsLen() uint { return 128 } -func (x *Uint160) MarshalJSON() ([]byte, error) { - if x == nil { - return []byte("null"), nil - } +// ToBigInt returns the value as a new big.Int. +func (x Uint128) ToBigInt() *big.Int { return uintBytesToBigInt(x.F[:]) } - // Canonical output: hexadecimal string. - // Avoids precision/scientific-notation issues in intermediate tooling. - v := x.Value() - if v.Sign() < 0 || v.BitLen() > int(x.BitsLen()) { - return nil, errors.New("failed to marshal Uint160: out of range") - } +// Value is an alias for [Uint128.ToBigInt]. +func (x Uint128) Value() *big.Int { return x.ToBigInt() } - hex := v.Text(16) // lowercase - return []byte(`"0x` + hex + `"`), nil -} +func (x Uint128) String() string { return x.ToBigInt().String() } -// UnmarshalJSON implements the [encoding/json.Unmarshaler] interface. -func (x *Uint160) UnmarshalJSON(data []byte) error { - // Try JSON string first - var s string - if err := json.Unmarshal(data, &s); err == nil { - base := 10 - if strings.HasPrefix(s, "0x") || strings.HasPrefix(s, "0X") { - base = 16 - s = s[2:] - } - b, ok := new(big.Int).SetString(s, base) - if !ok { - return fmt.Errorf("failed to parse Uint160 string %q", s) - } +// Cmp compares x and y and returns -1, 0 or +1. +func (x Uint128) Cmp(y Uint128) int { return x.ToBigInt().Cmp(y.ToBigInt()) } - if b.Sign() < 0 || b.BitLen() > int(x.BitsLen()) { - return errors.New("failed to unmarshal Uint160 from JSON: out of range") - } - *x = Uint160(*b) - return nil - } +// LoadFromCell implements tlb.Unmarshaler. +func (x *Uint128) LoadFromCell(loader *cell.Slice) error { return uintBytesFromCell(x.F[:], loader) } - // Fallback: plain JSON number - b := new(big.Int) - if err := b.UnmarshalJSON(data); err != nil { - return fmt.Errorf("failed to unmarshal Uint160 from JSON: %w", err) - } +// ToCell implements tlb.Marshaller. +func (x Uint128) ToCell() (*cell.Cell, error) { return uintBytesToCell(x.F[:]) } + +// MarshalJSON implements the [encoding/json.Marshaler] interface. +func (x Uint128) MarshalJSON() ([]byte, error) { return uintBytesMarshalJSON(x.F[:]) } - if b.Sign() < 0 || b.BitLen() > int(x.BitsLen()) { - return errors.New("failed to unmarshal Uint160 from JSON: out of range") +// UnmarshalJSON implements the [encoding/json.Unmarshaler] interface. +func (x *Uint128) UnmarshalJSON(data []byte) error { + v, err := parseUintJSON(data, 128) + if err != nil { + return err } - *x = Uint160(*b) + copy(x.F[:], uintBytesFromBigInt(v, 128, 16)) + return nil } -func (x Uint160) Value() *big.Int { - return (*big.Int)(&x) +// Uint160 is a 160-bit unsigned integer (Tolk uint160, e.g. a 20-byte EVM +// address). See the fixed-width section note above. +type Uint160 struct { + F [20]byte } -func (x Uint160) String() string { - return x.Value().String() +// NewUint160 builds a Uint160 from a big.Int, masking the input to 160 bits. +func NewUint160(v *big.Int) *Uint160 { + var a [20]byte + copy(a[:], uintBytesFromBigInt(v, 160, 20)) + + return &Uint160{F: a} } -// Uint256 is a 256-bit unsigned integer wrapper. -type Uint256 big.Int +func (Uint160) BitsLen() uint { return 160 } -func NewUint256(v *big.Int) *Uint256 { - return (*Uint256)(AsUnsigned(v, 256)) -} +// ToBigInt returns the value as a new big.Int. +func (x Uint160) ToBigInt() *big.Int { return uintBytesToBigInt(x.F[:]) } -func (*Uint256) BitsLen() uint { - return 256 -} +// Value is an alias for [Uint160.ToBigInt]. +func (x Uint160) Value() *big.Int { return x.ToBigInt() } -func (x *Uint256) Cmp(y *Uint256) (r int) { - return x.Value().Cmp(y.Value()) -} +func (x Uint160) String() string { return x.ToBigInt().String() } + +// Cmp compares x and y and returns -1, 0 or +1. +func (x Uint160) Cmp(y Uint160) int { return x.ToBigInt().Cmp(y.ToBigInt()) } // LoadFromCell implements tlb.Unmarshaler. -func (x *Uint256) LoadFromCell(loader *cell.Slice) error { - b := new(BigUint) - err := b.loadFromCell(x.BitsLen(), loader) +func (x *Uint160) LoadFromCell(loader *cell.Slice) error { return uintBytesFromCell(x.F[:], loader) } + +// ToCell implements tlb.Marshaller. +func (x Uint160) ToCell() (*cell.Cell, error) { return uintBytesToCell(x.F[:]) } + +// MarshalJSON implements the [encoding/json.Marshaler] interface. +func (x Uint160) MarshalJSON() ([]byte, error) { return uintBytesMarshalJSON(x.F[:]) } + +// UnmarshalJSON implements the [encoding/json.Unmarshaler] interface. +func (x *Uint160) UnmarshalJSON(data []byte) error { + v, err := parseUintJSON(data, 160) if err != nil { - return fmt.Errorf("failed to load Uint256 from cell: %w", err) + return err } + copy(x.F[:], uintBytesFromBigInt(v, 160, 20)) - *x = Uint256(*b.Value) return nil } -// ToCell implements tlb.Marshaller. -func (x Uint256) ToCell() (*cell.Cell, error) { - b := BigUint{ - Bits: x.BitsLen(), - Value: (*big.Int)(&x), - } - return b.toCell(x.BitsLen()) +// Uint256 is a 256-bit unsigned integer (Tolk uint256, e.g. a merkle root or +// operation id). See the fixed-width section note above. +type Uint256 struct { + F [32]byte } -func (x *Uint256) MarshalJSON() ([]byte, error) { - if x == nil { - return []byte("null"), nil - } - - // Canonical output: hexadecimal string. - // Avoids precision/scientific-notation issues in intermediate tooling. - v := x.Value() - if v.Sign() < 0 || v.BitLen() > int(x.BitsLen()) { - return nil, errors.New("failed to marshal Uint256: out of range") - } +// NewUint256 builds a Uint256 from a big.Int, masking the input to 256 bits. +func NewUint256(v *big.Int) *Uint256 { + var a [32]byte + copy(a[:], uintBytesFromBigInt(v, 256, 32)) - hex := v.Text(16) // lowercase - return []byte(`"0x` + hex + `"`), nil + return &Uint256{F: a} } -// UnmarshalJSON implements the [encoding/json.Unmarshaler] interface. -func (x *Uint256) UnmarshalJSON(data []byte) error { - // Try JSON string first - var s string - if err := json.Unmarshal(data, &s); err == nil { - base := 10 - if strings.HasPrefix(s, "0x") || strings.HasPrefix(s, "0X") { - base = 16 - s = s[2:] - } - b, ok := new(big.Int).SetString(s, base) - if !ok { - return fmt.Errorf("failed to parse Uint256 string %q", s) - } +func (Uint256) BitsLen() uint { return 256 } - if b.Sign() < 0 || b.BitLen() > int(x.BitsLen()) { - return errors.New("failed to unmarshal Uint256 from JSON: out of range") - } - *x = Uint256(*b) - return nil - } +// ToBigInt returns the value as a new big.Int. +func (x Uint256) ToBigInt() *big.Int { return uintBytesToBigInt(x.F[:]) } - // Fallback: plain JSON number - b := new(big.Int) - if err := b.UnmarshalJSON(data); err != nil { - return fmt.Errorf("failed to unmarshal Uint256 from JSON: %w", err) - } +// Value is an alias for [Uint256.ToBigInt]. +func (x Uint256) Value() *big.Int { return x.ToBigInt() } - if b.Sign() < 0 || b.BitLen() > int(x.BitsLen()) { - return errors.New("failed to unmarshal Uint256 from JSON: out of range") - } - *x = Uint256(*b) - return nil -} +func (x Uint256) String() string { return x.ToBigInt().String() } -func (x Uint256) Value() *big.Int { - return (*big.Int)(&x) -} +// Cmp compares x and y and returns -1, 0 or +1. +func (x Uint256) Cmp(y Uint256) int { return x.ToBigInt().Cmp(y.ToBigInt()) } + +// LoadFromCell implements tlb.Unmarshaler. +func (x *Uint256) LoadFromCell(loader *cell.Slice) error { return uintBytesFromCell(x.F[:], loader) } + +// ToCell implements tlb.Marshaller. +func (x Uint256) ToCell() (*cell.Cell, error) { return uintBytesToCell(x.F[:]) } + +// MarshalJSON implements the [encoding/json.Marshaler] interface. +func (x Uint256) MarshalJSON() ([]byte, error) { return uintBytesMarshalJSON(x.F[:]) } -func (x Uint256) String() string { - return x.Value().String() +// UnmarshalJSON implements the [encoding/json.Unmarshaler] interface. +func (x *Uint256) UnmarshalJSON(data []byte) error { + v, err := parseUintJSON(data, 256) + if err != nil { + return err + } + copy(x.F[:], uintBytesFromBigInt(v, 256, 32)) + + return nil } diff --git a/cciplib/ton/tlbe/biguint_test.go b/cciplib/ton/tlbe/biguint_test.go index 15c3d0aab..cc6c172d6 100644 --- a/cciplib/ton/tlbe/biguint_test.go +++ b/cciplib/ton/tlbe/biguint_test.go @@ -17,6 +17,13 @@ type legacyValues struct { } type typedValues struct { + Address Uint160 `tlb:"."` + Root Uint256 `tlb:"."` +} + +// ptrTypedValues covers the pointer-field form still used by the shared struct +// definitions (e.g. *tlbe.Uint256), which must keep working unchanged. +type ptrTypedValues struct { Address *Uint160 `tlb:"."` Root *Uint256 `tlb:"."` } @@ -59,12 +66,19 @@ func TestUintWrappers_MaskSignBit(t *testing.T) { err = tlb.LoadFromCell(&typed, c.BeginParse()) require.NoError(t, err) - require.NotNil(t, typed.Address.Value(), "address value is nil") require.Equal(t, expectedAddr, typed.Address.Value(), "address mismatch") - - require.NotNil(t, typed.Root.Value(), "root value is nil") require.Equal(t, expectedRoot, typed.Root.Value(), "root mismatch") + // Pointer fields must decode too. + var ptrTyped ptrTypedValues + err = tlb.LoadFromCell(&ptrTyped, c.BeginParse()) + require.NoError(t, err) + + require.NotNil(t, ptrTyped.Address, "pointer address is nil") + require.Equal(t, expectedAddr, ptrTyped.Address.Value(), "pointer address mismatch") + require.NotNil(t, ptrTyped.Root, "pointer root is nil") + require.Equal(t, expectedRoot, ptrTyped.Root.Value(), "pointer root mismatch") + // Testing legacy big.Int loading - should interpret as signed integers var legacy legacyValues err = tlb.LoadFromCell(&legacy, c.BeginParse()) @@ -81,8 +95,8 @@ func TestUintWrappers_RoundTrip(t *testing.T) { root := leadingBytes(32, 0x7f) original := typedValues{ - Address: NewUint160(new(big.Int).SetBytes(addr)), - Root: NewUint256(new(big.Int).SetBytes(root)), + Address: *NewUint160(new(big.Int).SetBytes(addr)), + Root: *NewUint256(new(big.Int).SetBytes(root)), } cellValue, err := tlb.ToCell(original) @@ -92,11 +106,9 @@ func TestUintWrappers_RoundTrip(t *testing.T) { err = tlb.LoadFromCell(&decoded, cellValue.BeginParse()) require.NoError(t, err) - require.NotNil(t, decoded.Address.Value(), "address value is nil after roundtrip") require.Equal(t, new(big.Int).SetBytes(addr), decoded.Address.Value(), "address mismatch after roundtrip") - - require.NotNil(t, decoded.Root.Value(), "root value is nil after roundtrip") require.Equal(t, new(big.Int).SetBytes(root), decoded.Root.Value(), "root mismatch after roundtrip") + require.Equal(t, original, decoded, "value types must be comparable with ==") var legacy legacyValues err = tlb.LoadFromCell(&legacy, cellValue.BeginParse()) diff --git a/cciplib/ton/tlbe/boxeduint_test.go b/cciplib/ton/tlbe/boxeduint_test.go new file mode 100644 index 000000000..f863ae60d --- /dev/null +++ b/cciplib/ton/tlbe/boxeduint_test.go @@ -0,0 +1,185 @@ +package tlbe // tlb extras + +import ( + "encoding/json" + "math/big" + "testing" + + "github.com/stretchr/testify/require" + "github.com/xssnick/tonutils-go/tlb" + "github.com/xssnick/tonutils-go/tvm/cell" +) + +// bigFromHex builds a big.Int from a hex string (helper for readable test cases). +// TestBoxedUints_WireCompatWithRawStore locks in that the new byte-based codec +// produces exactly the same cell as the previous BigUint/StoreBigInt path (and as +// a raw fixed-width store), so on-chain data stays bit-identical. +func TestBoxedUints_WireCompatWithRawStore(t *testing.T) { + v := new(big.Int).Add(new(big.Int).Lsh(big.NewInt(9), 200), big.NewInt(1234567)) + + cases := []struct { + name string + boxed any + raw *cell.Cell + }{ + {"uint128", *NewUint128(v), cell.BeginCell().MustStoreBigInt(AsUnsigned(v, 128), 128).EndCell()}, + {"uint160", *NewUint160(v), cell.BeginCell().MustStoreBigInt(AsUnsigned(v, 160), 160).EndCell()}, + {"uint256", *NewUint256(v), cell.BeginCell().MustStoreBigInt(AsUnsigned(v, 256), 256).EndCell()}, + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + c, err := tlb.ToCell(tc.boxed) + require.NoError(t, err) + require.Equal(t, tc.raw.Hash(), c.Hash(), + "boxed encoding must match the raw fixed-width big-endian store") + }) + } +} + +func bigFromHex(t *testing.T, s string) *big.Int { + t.Helper() + v, ok := new(big.Int).SetString(s, 16) + require.True(t, ok) + return v +} + +// TestBoxedUints_AreComparable locks in the core property: the boxed fixed-width +// uints are value types with == semantics (unlike a big.Int alias), so they can +// be used as Go map / tlbe.Dict keys. +func TestBoxedUints_AreComparable(t *testing.T) { + v128 := new(big.Int).Lsh(big.NewInt(1), 100) + require.Equal(t, *NewUint128(v128), *NewUint128(v128)) + require.NotEqual(t, *NewUint128(v128), *NewUint128(big.NewInt(1))) + + v160 := new(big.Int).Lsh(big.NewInt(1), 159) + require.Equal(t, *NewUint160(v160), *NewUint160(v160)) + require.NotEqual(t, *NewUint160(v160), *NewUint160(big.NewInt(1))) + + v256 := new(big.Int).Lsh(big.NewInt(1), 255) + require.Equal(t, *NewUint256(v256), *NewUint256(v256)) + require.NotEqual(t, *NewUint256(v256), *NewUint256(big.NewInt(1))) +} + +// TestBoxedUints_DictKeyRoundTrip is the regression test for the pointer-key bug: +// Uint160/Uint256 keys must survive ToCell -> LoadDict -> NewDictFromDictionary +// (the previous *Uint256 key form panicked in tonutils' reflection path). +func TestBoxedUints_DictKeyRoundTrip(t *testing.T) { + t.Run("uint160", func(t *testing.T) { + d := NewDict[Uint160, bool](map[Uint160]bool{ + *NewUint160(big.NewInt(5)): true, + *NewUint160(new(big.Int).Lsh(big.NewInt(1), 159)): false, + *NewUint160(bigFromHex(t, "ffffffffffffffffffffffffffffffffffffffff")): true, + }) + + c, err := d.ToCell() + require.NoError(t, err) + + dict, err := c.BeginParse().LoadDict(160) + require.NoError(t, err) + + restored, err := NewDictFromDictionary[Uint160, bool](dict) + require.NoError(t, err) + require.Len(t, restored.AsMap(), 3) + + v, ok := restored.Get(*NewUint160(big.NewInt(5))) + require.True(t, ok) + require.True(t, v) + + v, ok = restored.Get(*NewUint160(new(big.Int).Lsh(big.NewInt(1), 159))) + require.True(t, ok) + require.False(t, v) + }) + + t.Run("uint256", func(t *testing.T) { + d := NewDict[Uint256, uint64](map[Uint256]uint64{ + *NewUint256(big.NewInt(7)): 42, + *NewUint256(new(big.Int).Lsh(big.NewInt(1), 255)): 99, + }) + + c, err := d.ToCell() + require.NoError(t, err) + + dict, err := c.BeginParse().LoadDict(256) + require.NoError(t, err) + + restored, err := NewDictFromDictionary[Uint256, uint64](dict) + require.NoError(t, err) + require.Len(t, restored.AsMap(), 2) + + v, ok := restored.Get(*NewUint256(new(big.Int).Lsh(big.NewInt(1), 255))) + require.True(t, ok) + require.Equal(t, uint64(99), v) + }) +} + +// TestBoxedUints_CellRoundTripAndWidth checks each type's cell width and value. +func TestBoxedUints_CellRoundTripAndWidth(t *testing.T) { + testCases := []struct { + name string + build func(*big.Int) (any, uint) + }{ + {"uint128", func(v *big.Int) (any, uint) { return *NewUint128(v), 128 }}, + {"uint160", func(v *big.Int) (any, uint) { return *NewUint160(v), 160 }}, + {"uint256", func(v *big.Int) (any, uint) { return *NewUint256(v), 256 }}, + } + + value := new(big.Int).Add(new(big.Int).Lsh(big.NewInt(3), 120), big.NewInt(7)) + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + original, bits := tc.build(value) + + c, err := tlb.ToCell(original) + require.NoError(t, err) + require.Equal(t, bits, c.BitsSize()) + + switch x := original.(type) { + case Uint128: + var decoded Uint128 + require.NoError(t, decoded.LoadFromCell(c.BeginParse())) + require.Equal(t, x, decoded) + require.Equal(t, x.ToBigInt(), decoded.ToBigInt()) + case Uint160: + var decoded Uint160 + require.NoError(t, decoded.LoadFromCell(c.BeginParse())) + require.Equal(t, x, decoded) + case Uint256: + var decoded Uint256 + require.NoError(t, decoded.LoadFromCell(c.BeginParse())) + require.Equal(t, x, decoded) + } + }) + } +} + +// TestBoxedUints_JSONHexRoundTrip checks canonical hex JSON for all three types. +func TestBoxedUints_JSONHexRoundTrip(t *testing.T) { + for _, jsonCase := range []struct { + value any + want string + }{ + {*NewUint128(big.NewInt(255)), `"0xff"`}, + {*NewUint160(big.NewInt(255)), `"0xff"`}, + {*NewUint256(big.NewInt(255)), `"0xff"`}, + } { + payload, err := json.Marshal(jsonCase.value) + require.NoError(t, err) + require.JSONEq(t, jsonCase.want, string(payload)) + + switch x := jsonCase.value.(type) { + case Uint128: + var d Uint128 + require.NoError(t, json.Unmarshal(payload, &d)) + require.Equal(t, x, d) + case Uint160: + var d Uint160 + require.NoError(t, json.Unmarshal(payload, &d)) + require.Equal(t, x, d) + case Uint256: + var d Uint256 + require.NoError(t, json.Unmarshal(payload, &d)) + require.Equal(t, x, d) + } + } +} diff --git a/cciplib/ton/tlbe/uint128_test.go b/cciplib/ton/tlbe/uint128_test.go index 975a5e95f..23f3cf665 100644 --- a/cciplib/ton/tlbe/uint128_test.go +++ b/cciplib/ton/tlbe/uint128_test.go @@ -10,15 +10,15 @@ import ( ) func TestUint128_Values(t *testing.T) { - // A value above the 64-bit range exercises the high word. + // A value above the 64-bit range exercises multiple bytes. v := new(big.Int).Add(new(big.Int).Lsh(big.NewInt(1), 100), big.NewInt(12345)) u := NewUint128(v) - require.Equal(t, uint64(1<<36), u.Hi) // 2^100 >> 64 == 2^36 - require.Equal(t, uint64(12345), u.Lo) require.Equal(t, v, u.ToBigInt()) + require.Equal(t, uint8(0x0), u.F[0]) // high bytes zero + require.Equal(t, uint8(0x10), u.F[3]) // 2^100 sets bit 4 of byte 3 - // Zero and max round-trip through the words. + // Zero and max round-trip through the bytes. require.Equal(t, big.NewInt(0), NewUint128(big.NewInt(0)).ToBigInt()) max := new(big.Int).Sub(new(big.Int).Lsh(big.NewInt(1), 128), big.NewInt(1)) @@ -35,7 +35,7 @@ func TestUint128_CellRoundTrip(t *testing.T) { var decoded Uint128 require.NoError(t, decoded.LoadFromCell(c.BeginParse())) - require.Equal(t, original, decoded) + require.Equal(t, *original, decoded) require.Equal(t, v, decoded.ToBigInt()) } @@ -43,8 +43,8 @@ func TestUint128_UsableAsDictKey(t *testing.T) { // The whole point: Uint128 is comparable, so it keys a Dict by value and the // key decodes correctly via NewDictFromDictionary (unlike *Uint256 keys). d := NewDict[Uint128, struct{}](map[Uint128]struct{}{ - NewUint128(big.NewInt(5)): {}, - NewUint128(new(big.Int).Lsh(big.NewInt(1), 127)): {}, + *NewUint128(big.NewInt(5)): {}, + *NewUint128(new(big.Int).Lsh(big.NewInt(1), 127)): {}, }) c, err := d.ToCell() @@ -57,9 +57,9 @@ func TestUint128_UsableAsDictKey(t *testing.T) { require.NoError(t, err) require.Len(t, restored.AsMap(), 2) - _, ok := restored.Get(NewUint128(big.NewInt(5))) + _, ok := restored.Get(*NewUint128(big.NewInt(5))) require.True(t, ok) - _, ok = restored.Get(NewUint128(new(big.Int).Lsh(big.NewInt(1), 127))) + _, ok = restored.Get(*NewUint128(new(big.Int).Lsh(big.NewInt(1), 127))) require.True(t, ok) } @@ -72,7 +72,7 @@ func TestUint128_JSONRoundTrip(t *testing.T) { var decoded Uint128 require.NoError(t, json.Unmarshal(payload, &decoded)) - require.Equal(t, u, decoded) + require.Equal(t, *u, decoded) } // Guards the generic path used by CursedSubjects: a struct field with a @@ -84,7 +84,7 @@ type uint128SetHolder struct { func TestUint128_DictStructFieldRoundTrip(t *testing.T) { original := uint128SetHolder{ Subjects: NewDict[Uint128, struct{}](map[Uint128]struct{}{ - NewUint128(big.NewInt(3)): {}, + *NewUint128(big.NewInt(3)): {}, }), } diff --git a/pkg/bindings/lib/access/rbac/types.go b/pkg/bindings/lib/access/rbac/types.go index 7e1646a28..fca8bbbb4 100644 --- a/pkg/bindings/lib/access/rbac/types.go +++ b/pkg/bindings/lib/access/rbac/types.go @@ -136,7 +136,7 @@ var TLBs = tvm.MustNewTLBMap([]any{ // AccessControl data struct, auto-serialized to/from cell. type Data struct { // Roles mapping - Roles *tlbe.Dict[*tlbe.Uint256, RoleData] `tlb:"."` + Roles *tlbe.Dict[tlbe.Uint256, RoleData] `tlb:"."` } // Internal storage struct for role data diff --git a/pkg/bindings/mcms/mcms/storage.go b/pkg/bindings/mcms/mcms/storage.go index 0ab24cde6..1ddf22c52 100644 --- a/pkg/bindings/mcms/mcms/storage.go +++ b/pkg/bindings/mcms/mcms/storage.go @@ -18,13 +18,13 @@ func EmptyDataFrom(id uint32, owner *address.Address, chainID int64) Data { PendingOwner: nil, }, Oracle: owner, - Signers: tlbe.NewEmptyDict[*tlbe.Uint160, Signer](), + Signers: tlbe.NewEmptyDict[tlbe.Uint160, Signer](), Config: Config{ Signers: tlbe.NewEmptyDict[uint8, Signer](), GroupQuorums: tlbe.NewEmptyDict[uint8, uint8](), GroupParents: tlbe.NewEmptyDict[uint8, uint8](), }, - SeenSignedHashes: tlbe.NewEmptyDict[*tlbe.Uint256, bool](), + SeenSignedHashes: tlbe.NewEmptyDict[tlbe.Uint256, bool](), RootInfo: RootInfo{ ExpiringRootAndOpCount: ExpiringRootAndOpCount{ Root: tlbe.NewUint256(big.NewInt(0)), diff --git a/pkg/bindings/mcms/mcms/types.go b/pkg/bindings/mcms/mcms/types.go index a74161ca5..d6c22bcdd 100644 --- a/pkg/bindings/mcms/mcms/types.go +++ b/pkg/bindings/mcms/mcms/types.go @@ -273,13 +273,13 @@ type Data struct { // Signers is used to easily validate the existence of the signer by its public key. We still // have signers stored in config in order to easily deactivate them when a new config is set. - Signers *tlbe.Dict[*tlbe.Uint160, Signer] `tlb:"."` // exists if the public key is a signer + Signers *tlbe.Dict[tlbe.Uint160, Signer] `tlb:"."` // exists if the public key is a signer // The current configuration of the contract Config Config `tlb:"^"` // @dev split out as cell to avoid size limits // Remember signedHashes that this contract has seen. Each signedHash can only be set once. - SeenSignedHashes *tlbe.Dict[*tlbe.Uint256, bool] `tlb:"."` + SeenSignedHashes *tlbe.Dict[tlbe.Uint256, bool] `tlb:"."` // The current RootMetadata and ExpiringRootAndOpCount wrapped in a cell bc size limits. RootInfo RootInfo `tlb:"^"` diff --git a/pkg/bindings/mcms/timelock/storage.go b/pkg/bindings/mcms/timelock/storage.go index 09117e2de..936c5db08 100644 --- a/pkg/bindings/mcms/timelock/storage.go +++ b/pkg/bindings/mcms/timelock/storage.go @@ -11,7 +11,7 @@ func EmptyDataFrom(id uint32) Data { return Data{ ID: id, MinDelay: 0, - Timestamps: tlbe.NewEmptyDict[*tlbe.Uint256, uint64](), + Timestamps: tlbe.NewEmptyDict[tlbe.Uint256, uint64](), BlockedFnSelectorsLen: 0, BlockedFnSelectors: tlbe.NewEmptyDict[uint32, bool](), ExecutorRoleCheckEnabled: true, @@ -19,10 +19,10 @@ func EmptyDataFrom(id uint32) Data { ValidAfter: 0, OpFinalizationTimeout: 0, OpPendingID: tlbe.NewUint256(big.NewInt(0)), - OpPendingCalls: tlbe.NewEmptyDict[*tlbe.Uint256, bool](), + OpPendingCalls: tlbe.NewEmptyDict[tlbe.Uint256, bool](), }, RBAC: rbac.Data{ - Roles: tlbe.NewEmptyDict[*tlbe.Uint256, rbac.RoleData](), + Roles: tlbe.NewEmptyDict[tlbe.Uint256, rbac.RoleData](), }, } } diff --git a/pkg/bindings/mcms/timelock/types.go b/pkg/bindings/mcms/timelock/types.go index 8a0eebbcf..954f0e4ec 100644 --- a/pkg/bindings/mcms/timelock/types.go +++ b/pkg/bindings/mcms/timelock/types.go @@ -347,7 +347,7 @@ type Data struct { // Minimum delay for operations in seconds MinDelay uint32 `tlb:"## 32"` // Map of operation id to timestamp - Timestamps *tlbe.Dict[*tlbe.Uint256, uint64] `tlb:"."` + Timestamps *tlbe.Dict[tlbe.Uint256, uint64] `tlb:"."` // Number of fn selectors blocked by the contract. BlockedFnSelectorsLen uint32 `tlb:"## 32"` @@ -397,7 +397,7 @@ type OpPendingInfo struct { // The id of the currently pending operation (OperationBatch hash) OpPendingID *tlbe.Uint256 `tlb:"."` // The ids (fingerprints) for calls awaiting finalization in the pending op (true = pending, false = finalized/bounced) - OpPendingCalls *tlbe.Dict[*tlbe.Uint256, bool] `tlb:"."` + OpPendingCalls *tlbe.Dict[tlbe.Uint256, bool] `tlb:"."` } // --- Constants --- diff --git a/pkg/ccip/bindings/tokenpool/types.go b/pkg/ccip/bindings/tokenpool/types.go index f44e4c1f1..23fa0fd3c 100644 --- a/pkg/ccip/bindings/tokenpool/types.go +++ b/pkg/ccip/bindings/tokenpool/types.go @@ -114,10 +114,10 @@ type ChainUpdate struct { // RemoteChainConfig holds the configuration for a remote chain. type RemoteChainConfig struct { - RemoteTokenAddress *tlbe.Cell[common.CrossChainAddress] `tlb:"^"` - RemotePools *tlbe.Dict[*tlbe.Uint256, *cell.Cell] `tlb:"."` - RateLimiters RateLimiterPair `tlb:"^"` - FastFinalityRateLimiters RateLimiterPair `tlb:"^"` + RemoteTokenAddress *tlbe.Cell[common.CrossChainAddress] `tlb:"^"` + RemotePools *tlbe.Dict[tlbe.Uint256, *cell.Cell] `tlb:"."` + RateLimiters RateLimiterPair `tlb:"^"` + FastFinalityRateLimiters RateLimiterPair `tlb:"^"` } // RateLimitConfigArgs holds arguments for setting rate limit configs. diff --git a/pkg/ccip/bindings/tokenpool/types_test.go b/pkg/ccip/bindings/tokenpool/types_test.go index b9538aac8..7c2f7fe10 100644 --- a/pkg/ccip/bindings/tokenpool/types_test.go +++ b/pkg/ccip/bindings/tokenpool/types_test.go @@ -57,8 +57,8 @@ func TestDynamicConfig_AllowedDepositNamespaces_WireFormat(t *testing.T) { // with 0-bit unit values, inlined into the enclosing cell. func TestCursedSubjects_WireFormat(t *testing.T) { subjects := tlbe.NewDict[tlbe.Uint128, struct{}](map[tlbe.Uint128]struct{}{ - tlbe.NewUint128(big.NewInt(1)): {}, - tlbe.NewUint128(big.NewInt(42)): {}, + *tlbe.NewUint128(big.NewInt(1)): {}, + *tlbe.NewUint128(big.NewInt(42)): {}, }) got, err := tlb.ToCell(CursedSubjects{Data: subjects}) @@ -83,7 +83,7 @@ func TestCursedSubjects_WireFormat(t *testing.T) { // TestCursedSubjects_RoundTrip verifies encode/decode via the tlb:"." marshaller. func TestCursedSubjects_RoundTrip(t *testing.T) { subjects := tlbe.NewDict[tlbe.Uint128, struct{}](map[tlbe.Uint128]struct{}{ - tlbe.NewUint128(big.NewInt(7)): {}, + *tlbe.NewUint128(big.NewInt(7)): {}, }) c, err := tlb.ToCell(CursedSubjects{Data: subjects}) @@ -92,11 +92,38 @@ func TestCursedSubjects_RoundTrip(t *testing.T) { var decoded CursedSubjects require.NoError(t, tlb.LoadFromCell(&decoded, c.BeginParse())) - _, ok := decoded.Data.Get(tlbe.NewUint128(big.NewInt(7))) + _, ok := decoded.Data.Get(*tlbe.NewUint128(big.NewInt(7))) require.True(t, ok) require.Equal(t, 1, decoded.Data.Len()) } +// TestRemoteChainConfig_RemotePools_Decode is a regression test: RemotePools keys +// used to be *tlbe.Uint256, which panics on decode (pointer keys are not +// tlb.Unmarshaler). Value-typed Uint256 keys must decode, mirroring the +// RemotePools field shape with a plain payload to isolate key behaviour. +func TestRemoteChainConfig_RemotePools_Decode(t *testing.T) { + type remotePoolsHolder struct { + RemotePools *tlbe.Dict[tlbe.Uint256, uint64] `tlb:"."` + } + + cfg := remotePoolsHolder{ + RemotePools: tlbe.NewDict[tlbe.Uint256, uint64](map[tlbe.Uint256]uint64{ + *tlbe.NewUint256(big.NewInt(5)): 123, + }), + } + + c, err := tlb.ToCell(cfg) + require.NoError(t, err) + + var decoded remotePoolsHolder + require.NoError(t, tlb.LoadFromCell(&decoded, c.BeginParse())) + require.Len(t, decoded.RemotePools.AsMap(), 1) + + got, ok := decoded.RemotePools.Get(*tlbe.NewUint256(big.NewInt(5))) + require.True(t, ok) + require.Equal(t, uint64(123), got) +} + // TestDynamicConfig_AllowedDepositNamespaces_RoundTrip verifies encode/decode // through tonutils-go's tlb loader (using the tlb:"." marshaller path). func TestDynamicConfig_AllowedDepositNamespaces_RoundTrip(t *testing.T) { diff --git a/pkg/ton/tlbe/tlbe.go b/pkg/ton/tlbe/tlbe.go index 04a1be52d..2f53d7e90 100644 --- a/pkg/ton/tlbe/tlbe.go +++ b/pkg/ton/tlbe/tlbe.go @@ -17,6 +17,7 @@ import ( type Cell[T any] = src.Cell[T] type Dict[K comparable, V any] = src.Dict[K, V] +type Uint128 = src.Uint128 type Uint160 = src.Uint160 type Uint256 = src.Uint256 @@ -49,5 +50,6 @@ func NewEmptyDict[K comparable, V any]() *Dict[K, V] { return src.NewEmptyDict[K, V]() } +var NewUint128 = src.NewUint128 var NewUint160 = src.NewUint160 var NewUint256 = src.NewUint256 From be2eb3ed5ab23b2d33dd1bf581548a463d63e3ca Mon Sep 17 00:00:00 2001 From: Kristijan Date: Wed, 16 Sep 2026 23:42:00 +0200 Subject: [PATCH 14/23] fix(ccip): align pool admission with EVM override semantics and decode all rich bounces Token-pool operation hooks returned before the only code path performing the Router, curse, and rate-limit checks, so a pool overriding `onLockOrBurn` or `onReleaseOrMint` admitted requests without them. This contradicted the documented contract on `ensureNotCursed` and on the `validateLockOrBurn` hook. Follow EVM: `_validateLockOrBurn` / `_validateReleaseOrMint` are virtual and own the curse check and `_onlyOnRamp` / `_onlyOffRamp`. An override replaces them and takes on every check. Mirror that placement by moving `onlyRouter` out of the dispatcher and into `validateLockOrBurn` / `validateReleaseOrMint`, alongside `ensureNotCursed`, and drop the "cannot bypass" comments. Hook docs now state that setting an operation hook replaces the base admission checks. In-repo pools leave both hooks unset, so the default path is unchanged. Separately, `onBouncedMessage` treated every rich bounce as a token-pool relay and decoded `Router_RichBouncedMessage` unconditionally. `onWithdrawToTokenPool` sends `AskToTransfer` with rich bounce, which failed that union match and reverted inside the bounce handler. Add `AskToTransfer` to the union and handle it explicitly. The withdrawal failure is not yet propagated to the OnRamp, so the send stalls and the executor keeps waiting. Emit `TokenPoolWithdrawBounced` for visibility and leave a TODO; routing the withdrawal through an on-ramp deposit account is tracked separately. --- .../ccip/pools/lib/token_pool/entrypoint.tolk | 42 +++++++-------- contracts/contracts/ccip/router/contract.tolk | 16 ++++++ contracts/contracts/ccip/router/events.tolk | 11 ++++ contracts/contracts/ccip/router/messages.tolk | 3 +- contracts/wrappers/gen/ccip/Router.ts | 51 ++++++++++++++++++- .../gen/ccip/pools/BurnMintTokenPool.ts | 2 +- .../ccip/pools/LockReleaseLockboxTokenPool.ts | 2 +- .../gen/ccip/pools/LockReleaseTokenPool.ts | 2 +- 8 files changed, 104 insertions(+), 25 deletions(-) diff --git a/contracts/contracts/ccip/pools/lib/token_pool/entrypoint.tolk b/contracts/contracts/ccip/pools/lib/token_pool/entrypoint.tolk index 04f2fe43f..0adb5ca51 100644 --- a/contracts/contracts/ccip/pools/lib/token_pool/entrypoint.tolk +++ b/contracts/contracts/ccip/pools/lib/token_pool/entrypoint.tolk @@ -94,13 +94,16 @@ fun TokenPool_Data.storeAsContractData(self) { /// through every hook (`T?` when a hook may be invoked with no context, e.g. getters). /// /// There are three hook families, mirroring the three flows: -/// - **Guards**: curse checks — override to add custom policy. +/// - **Guards**: curse checks, invoked from the base admission path. /// - **Operation hooks**: entry + validation + (pre/post)flight for the LockOrBurn and /// ReleaseOrMint flows. Hooks returning a `TokenPool_*Prepared` may also signal `wait` to defer /// execution to the on-chain (async) `advancedPoolHooks` contract. /// - **Continuation hooks**: run after Jetton custody is settled, letting the pool track binding /// side effects (e.g. lock/release accrues fees only on confirmed deposit). /// +/// Setting an operation hook replaces the base flow for that phase, so the override owns every +/// check the base path would have performed (e.g., `validateLockOrBurn` / `validateReleaseOrMint`). +/// /// The fee-withdrawal hook `onWithdrawFeeTokens` is a fourth, standalone extension point. struct TokenPool_Hooks { /// RMN curse guard for a remote lane. @@ -1357,14 +1360,15 @@ fun TokenPool.onGetCCVsBounced( /// Validates the lock or burn input for correctness on /// - token to be locked or burned /// - RMN curse status -/// - if the sender is a valid onRamp +/// - if the sender is the configured Router /// - rate limiting for either default or FTF transfer messages. /// - preflight checks hooks (if enabled) /// /// @param sender The address of the original sender of the lock or burn request. /// @param msg The full LockOrBurn message containing all request fields. /// -/// @dev This function should always be called before executing a lock or burn. +/// @dev This function should always be called before executing a lock or burn. Not doing so would +/// allow for various exploits. fun TokenPool.validateLockOrBurn( mutate self, sender: address, @@ -1383,6 +1387,7 @@ fun TokenPool.validateLockOrBurn( assert(self.isSupportedToken(details.localToken), TokenPool_Error.InvalidToken); self.requireSupportedChain(details.remoteChainSelector); self.ensureNotCursed(details.remoteChainSelector); + self.onlyRouter(sender); val feeAmount = self.getFeeAmount(request.transfer, msg.requestedFinalityConfig); val destTokenAmount = details.amount - feeAmount; @@ -1421,10 +1426,6 @@ fun TokenPool.onLockOrBurn( sender: address, msg: TokenPool_LockOrBurn, ): void { - // Authenticate before invoking an overridable operation hook so a custom - // pool cannot accidentally bypass the Router boundary. - self.onlyRouter(sender); - if (self.hooks != null && self.hooks.onLockOrBurn != null) { self.context = self.hooks.onLockOrBurn(self.context!, sender, msg); @@ -1752,8 +1753,18 @@ fun TokenPool.onLockOrBurnTransferFinalize( } } -/// Validates the release or mint input and calls postflightCheck. +/// Validates the release or mint input for correctness on +/// - token to be released or minted +/// - RMN curse status +/// - if the sender is the configured Router +/// - if the source pool is configured for the remote chain +/// - rate limiting for either default or FTF transfer messages. +/// - postflight checks hooks (if enabled) +/// /// @param msg The full ReleaseOrMint message containing all request fields. +/// +/// @dev This function should always be called before executing a release or mint. Not doing so +/// would allow for various exploits. fun TokenPool.validateReleaseOrMint( mutate self, sender: address, @@ -1772,6 +1783,7 @@ fun TokenPool.validateReleaseOrMint( assert(self.isSupportedToken(details.localToken), TokenPool_Error.InvalidToken); self.requireSupportedChain(details.remoteChainSelector); self.ensureNotCursed(details.remoteChainSelector); + self.onlyRouter(sender); assert(self.isRemotePool(details.remoteChainSelector, request.sourcePoolAddress), TokenPool_Error.InvalidRemotePoolForChain); val remoteDecimals = self.parseRemoteDecimals(request.sourcePoolData); @@ -1811,10 +1823,6 @@ fun TokenPool.onReleaseOrMint( sender: address, msg: TokenPool_ReleaseOrMint, ): void { - // Authenticate before invoking an overridable operation hook so a custom - // pool cannot accidentally bypass the Router boundary. - self.onlyRouter(sender); - if (self.hooks != null && self.hooks.onReleaseOrMint != null) { self.context = self.hooks.onReleaseOrMint(self.context!, msg); @@ -1961,12 +1969,8 @@ fun TokenPool.onlyOwnerOrRMNProxy(self, sender: address) { ); } -/// Restricts CCIP token operations to the configured Router. -/// -/// This check intentionally runs in the message dispatcher, before any pool -/// hook can handle LockOrBurn or ReleaseOrMint. The Router owns ramp -/// authentication and applies its own RMN policy; the pool independently -/// applies its local cursed-subject policy during request validation. +/// Restricts CCIP token operations to the configured Router. The Router owns ramp authentication +/// and applies its own RMN policy; the pool applies its local cursed-subject policy independently. fun TokenPool.onlyRouter(self, sender: address) { val router = self.data.adminConfig.load().dynamicConfig.load().router; assert(sender == router, TokenPool_Error.Unauthorized); @@ -1981,8 +1985,6 @@ fun TokenPool.onlyAdvancedPoolHooks(self, sender: address) { } fun TokenPool.ensureNotCursed(self, remoteChainSelector: uint64) { - // The owner-selected local RMN policy is mandatory. Hooks may impose an - // additional restriction, but cannot bypass this policy domain. assert(self.verifyNotCursed(remoteChainSelector as uint128), TokenPool_Error.CursedByRMN); if (self.hooks != null && self.hooks.ensureNotCursed != null) { diff --git a/contracts/contracts/ccip/router/contract.tolk b/contracts/contracts/ccip/router/contract.tolk index 73f2f7862..584ab9fad 100644 --- a/contracts/contracts/ccip/router/contract.tolk +++ b/contracts/contracts/ccip/router/contract.tolk @@ -285,6 +285,22 @@ fun onBouncedMessage(in: InMessageBounced) { ); } } + AskToTransfer => { + // Bounced `Router_WithdrawToTokenPool` withdrawal: the jettons never reached the + // token pool, so the send is stuck and the executor waits for a reply that will + // never come. + // + // TODO: propagate the failure to the OnRamp so it can fail the send and the + // executor can settle. Requires a failure message plus an executor `replyTo` for + // this leg, which the Router does not carry. The withdrawal is being reworked to + // route through an on-ramp deposit account, which will own this failure path. + emit(TOKEN_POOL_WITHDRAW_BOUNCED_TOPIC, TokenPoolWithdrawBounced { + wallet: in.senderAddress, + tokenPool: richMsg.transferRecipient, + queryId: richMsg.queryId, + exitCode: rich.exitCode, + }); + } } return; } diff --git a/contracts/contracts/ccip/router/events.tolk b/contracts/contracts/ccip/router/events.tolk index 8ec2f5b02..10b6e1f54 100644 --- a/contracts/contracts/ccip/router/events.tolk +++ b/contracts/contracts/ccip/router/events.tolk @@ -34,3 +34,14 @@ struct MessageToOffRampBounced { offRamp: address, execId: uint192, } + +/// Emitted when a `Router_WithdrawToTokenPool` jetton transfer bounces back. The send cannot +/// proceed and the executor is waiting, so this is emitted for observability until the failure +/// is propagated to the OnRamp. +const TOKEN_POOL_WITHDRAW_BOUNCED_TOPIC = "TokenPoolWithdrawBounced".crc32(); +struct TokenPoolWithdrawBounced { + wallet: address, + tokenPool: address, + queryId: uint64, + exitCode: int32, +} diff --git a/contracts/contracts/ccip/router/messages.tolk b/contracts/contracts/ccip/router/messages.tolk index 9695f129e..b018656cd 100644 --- a/contracts/contracts/ccip/router/messages.tolk +++ b/contracts/contracts/ccip/router/messages.tolk @@ -45,7 +45,8 @@ type Router_BouncedMessage = type Router_RichBouncedMessage = | TokenPool_LockOrBurn - | TokenPool_ReleaseOrMint; + | TokenPool_ReleaseOrMint + | AskToTransfer; // update multiple chain selectors in batch to the same onramp/offramp address struct (0x7db6745d) Router_ApplyRampUpdates { diff --git a/contracts/wrappers/gen/ccip/Router.ts b/contracts/wrappers/gen/ccip/Router.ts index 30d7dcd77..281011520 100644 --- a/contracts/wrappers/gen/ccip/Router.ts +++ b/contracts/wrappers/gen/ccip/Router.ts @@ -3626,6 +3626,55 @@ export const MessageToOffRampBounced = { } } +/** + > struct TokenPoolWithdrawBounced { + > wallet: address + > tokenPool: address + > queryId: uint64 + > exitCode: int32 + > } + */ +export interface TokenPoolWithdrawBounced { + readonly $: 'TokenPoolWithdrawBounced' + wallet: c.Address + tokenPool: c.Address + queryId: uint64 + exitCode: int32 +} + +export const TokenPoolWithdrawBounced = { + create(args: { + wallet: c.Address + tokenPool: c.Address + queryId?: uint64 + exitCode: int32 + }): TokenPoolWithdrawBounced { + return { + $: 'TokenPoolWithdrawBounced', + ...args, + queryId: args.queryId ?? 0n + } + }, + fromSlice(s: c.Slice): TokenPoolWithdrawBounced { + return { + $: 'TokenPoolWithdrawBounced', + wallet: s.loadAddress(), + tokenPool: s.loadAddress(), + queryId: s.loadUintBig(64), + exitCode: s.loadIntBig(32), + } + }, + store(self: TokenPoolWithdrawBounced, b: c.Builder): void { + b.storeAddress(self.wallet); + b.storeAddress(self.tokenPool); + b.storeUint(self.queryId, 64); + b.storeInt(self.exitCode, 32); + }, + toCell(self: TokenPoolWithdrawBounced): c.Cell { + return makeCellFrom(self, TokenPoolWithdrawBounced.store); + } +} + // ———————————————————————————————————————————— // class Router // @@ -3665,7 +3714,7 @@ function calculateDeployedAddress(code: c.Cell, data: c.Cell, options: DeployedA } export class Router implements c.Contract { - static CodeCell = c.Cell.fromBase64('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'); + static CodeCell = c.Cell.fromBase64('te6ccgECXQEAEjAAART/APSkE/S88sgLAQIBYgIDAgLGICECASAEBQIBIAYHAgEgGBkCASAICQIBIA4PAgEgCgsAG7XFEEAb4ZQEEIH3flCQAgEgDA0ATbBX40GmxpbmsuY2hhaW4udG9uLmNjaXAuUm91dGVygi1MS42LjGIAB3r4R2omg2gOmPmP0kGP0oGP0kGPoCkEAgekM30shHDKkBfSRogWRln4l9KWSoAbeBKJDAIHo+N9L0L4HAAE2sXXaiaGmPmP0kGP0oGP0kGPoA+gLBAG+GrMAgegc30Il5en0kaMACAnEQEQIBIBITABWmO9qJoaY+Y/SQYQAJpQsCBHcAgbOtu1E0NMfMfpIMfpQMfpIMfQB9AHXTND6SDH6UDH0BPQEMdFtIYMG9IZvpTKRAZ1SAm8CURKDBvR8b6Uy6DAxgAgEgFBUAe67+dqJoNoDpj5j9JBj9KBj9JBj6APoCkEAgekM30shHDKkBfSRogWRln4l9KWSoAbeBKJDAIHo+N9L0L4HAAgFmFhcAG6OvtRNDTHzH6SDH6UDCAEeiG7UTQ0x8x+kgx+lAx+kgx9AWCAN8MWYBA9A5voRLy9PpI0YASbrejtRNDTHzH6SDH6UDH6SDH0AfQB10zQ+kgx+lD0BDH0BDHRgCASAaGwIDeOAcHQIBIB4fAA+jMghA7msoAgBHoeO1E0NMfMfpIMfpQMfpIMfQB9AHXTND6SPpQMfQEMfQEMdGAFGy4HtRNDTHzH6SDH6UDH6SDH0AfQB10zQ+kgx+lAx9AT0BDHRAfADs4ABfscn7UTQ0x8x+kgx+lAx+kgx9AVtIYBA9IZvpTKRAZ1SAm8CURKAQPR8b6Uy6DAxgAgHNIiMCA6PSW1wCASAkJQIBIFBRAgEgJicCASBNTgP3PiRkvAE4CDXLCPts6Ls4wLXLCGLtGysjlgxggkxLQCCCdkFwIIQBV1KgIIQBOM4gIILwU3AtgmgghAL68IAoKCgggDfFfiXWL7y9NM/0z/TByHBQfKFAaoC1xjU1PpQ10yCAN8WI9DHAPL0+JL4l/AG4NcsIm61VBTjAoCgpKgLfDT4J28QIW6RMZI1BOIDjqmCAN8OAfLyggDfDVEjvBLy9AFw+wKDBojIz4UIE/pScc8LbhLMyQH7AOCCAN8OIcIA8vSCAN8MUxO58vQCggDfDQShIrwT8vSAQIjIz4UIFPpSWPoCcc8LahLMyQH7AIExMBPQx7UTQ0x/6SPpQ+kj0BPQE10z4koIAwohRF8cF8vQH0z8x0wABltT6UIEAipRtbVhw4gHTAAGW1PpIgQCLlG1tWHDiAdMAAZfU+kgwgQCLlDBtbXDiBpI2NuMNA5IzM+MNkVvjDQbQ+kj6UPQE9AQx0W0pgED0hm+lkCssLS4AbDGCCUBvQIIQBV1KgIIJQG9AgglAb0C2CaCggglAb0CCCUBvQLYJoIIA3xX4l1i+8vTU+JLwBQT6idcnjmsx7UTQAfoA1PpIItAF0x8x+kgx+lAx+kgx9AUF1ywhi7RsrPK/0z8x1ws/+JKCAN8MUCeAQPQOb6EX8vQF+kjRBYIA3xIGxwUV8vTIz5J4hVeyUAP6AswSzsnIz4UIEvpScc8LbszJgED7AODXLCVg7ol04wKJ1ycwMTIzAKgn0JQgxwCzjisg10sBkTCbgTS8AcAB8vTXTNDi0z8obpYLgED0WzCaKMj6UkAMgED0Q+IK6DDIz48YAASCEH4k597PC/dwzwthGMwW+lTJcPsAEEUAwCTQlCDHALOOOCDXSwGRMJuBNLwBwAHy9NdM0OLTP4IA3w9TKIBA9A5voRLy9PpI0YIA3xBRF8cF8vQHgED0WzAG6DDIz48YAASCEFzZFvzPC/dwzwthFcwT+lLJcPsAEgCMIdCUIMcAs44gINdLAZEwm4E0vAHAAfL010zQ4tM/Isj6UkAFgED0QwPoMMjPjxgABIIQMEBnYc8L93DPC2ESzPpSyXD7AAFIiuhbA8j6UhL6VPQA9ADJBcjLHxT6UhL6VPpS9AAS9ADMye1ULwAqAfpI0chAE4EBC/RRMFEagED0fG+lAAgq+xG9ANQx7UTQAdP/1PpIItAF0x8x+kgx+lAx+kgx9AUF1ywhi7RsrPK/0z8x1ws/+JKCAN8MUCeAQPQOb6EX8vQF+kjRBYIA3xIGxwUV8vTIz5OwjxWKE8v/zBLOycjPhYgS+lJxzwtuzMmAQPsAAAj8acULAf6OfDHtRNAB1NO/+kj6ADAj0AXTHzH6SDH6UDH6SDH0BDH0BNdMBtP/MdcLPyCCAN8NA4BA9A5voRPy9AH6SNGCAN8O+JJYxwXy9IIA3xEG0PpIMfpQMfQE9AQx0QHwA7MV8vTIz4WI+lJQA/oCghBbS8emzwuKEsu/zMlx+wDgNAT0idcn4wLXLCDyrd+0jlsxggDfFfiXggkxLQC+8vTXC7/4ku1E0CLIy7/PUNcLPwHTHzH6SDH6UDH6SDH0AfQFggDfDVmAQPQOb6ES8vT6SNHIz4WI+lKCECj0Fm/PC44Sy7/6UsmAQPsA4NcsJ5nEAjTjAtcsIfip0Yw1Njc4AAgZ8AmPAf4x7UTQAdM/0z/XTAPTHzH6SDH6UDH6SDH0BfiSggDfDFEygED0Dm+hM1ry9PpI0QGCAN8SAscF8vQB0PpI+gD6SNdMbW2CEB3NZQADyPQAz1DIz5A+KfqWGMs/UAX6AhP6UhL6VBL0AAH6AhLOycjPhYgS+lLPhBBz+gJxzwtlOQH+Me1E0NMf+kj6UPpI9AT0BNdMINAx+kj6UPQE9ATR+JKCAMKIURXHBfL0CtM/MddM0JQgxwCzjjkg10sBkTCbgTS8AcAB8vTXTNDi03/IVCAkgwb0UzDIz48YAASCEMzoMmPPC/dwzwthEst/yXD7AAHoMALI+lL6VFIQ9ABSgDoE+OMC1ywgXK1SdI4oMdM/1wt/ggHrge1D2PiSyM+FCPpSghAiuoOzzwuOEss/ygDJgED7AODXLCV71NY04wLXLCeaH+DcjjIx7UTQ0x8x+kgw+JKCAMKIAscF8vTTP/pI+gDTAAGS+gCSbQHi1woAghA7msoAVUDwAeCJ1yc7PD0+AAzMyYBA+wAApvQAyQfIyx8W+lIU+lQS+lL0APQAEszJ7VQhgQEL9IJvpTKRAY4qIIIK+vCAyM+FCBL6UgH6AoIQTKG8s88LilIg9ADJcvsAIoEBC/R0b6Uy6F8DAf4x7UTQ0x/6SPpQ+kj0BPQE10wg0DH6SPpQ9AT0BNH4koIAwohRFccF8vQK0z8x10zQlCDHALOONyDXSwGRMJuBNLwBwAHy9NdM0OLTf1ITgwb0WzDIz48YAASCENnrg4XPC/dwzwthEst/yXD7AAHoMALI+lL6VFIQ9ABSgPQAPwCWMe1E0NYf+kj6UPpI9AT0BNdM0PpI+lD0BPQE0fiSEDREC/ACjiAByPpS+lT0ABf0AMkFyM4U+lIS+lT6UvQAEvQAzMntVOCED/LwAAgKqBHtBPaOXTHtRNDTHzH6SDD4koIAwogCxwXy9NM/MddMk/ED6ACT8QPpACDaASP7BCPQ7R7tU+1EQBPaIe1UIfkAAdoBAsjMy//OycjPjxgABIIQoztJjs8L93HPC2HMyXD7AODXLCMon8cM4wLXLCRXEoik4wLXLCN5aAb84wJAQUJDAKLJB8jLHxb6UhT6VBL6UvQA9AASzMntVCGBAQv0gm+lMpEBjiogggr68IDIz4UIEvpSAfoCghBMobyzzwuKUiD0AMly+wAigQEL9HRvpTLoXwMApjHtRNAB0z/T/9M/+kgwBNMfMfpIMfpQMfpIMfQF+JKCAN8MWoBA9A5voRLy9PpI0QGCAN8SAscF8vTIz4UIE/pSghB40PIezwuOyz/L/8mAQPsAAKgx7UTQAdM/0z/6SNcL/wTTHzH6SDH6UDH6SDH0BfiSggDfDFBCgED0Dm+hEvL0+kjRAoIA3xIDxwUS8vTIz4WI+lKCEFpF1DTPC47LP8v/yYBA+wAC/jHtRNAB0z/6SNT6SDAh0NP/MddM0AXTHzH6SDH6UDH6SDH0BPQEMddMBtcLP/iSIYIA3wwEgED0Dm+hFPL0AvpI0QKCAN8SA8cFEvL0BdD6SDH6UDH0BPQEMdFQBfAD4wJtyM+T6faREhTLP8zPkAAAAAIS9AAS+lTJyM+FiBJERQNwidcn4wLXLCObFoTk4wIw7UTQ1h/6SPpQ+JJDMCXwAp40AsjOEvpSEvpUzsntVOBfBIQPAccA8vRGR0gAQDDIz4UIE/pSghC3bjqEzwuOyz/6Us+QAAN8RsmAQPsAACT6Us+EEHP6AnHPC2XMyYBA+wAACLGYYqMC+DHtRNAB0z/TP/pI1NMf+kgwBtMfMfpIMfpQMfpIMfQEMfQE10wlggDfDQOAQPQOb6ET8vQB+kjRggDfDviSIscF8vQj0NP/MddM0PpIMdcLP4IA3xpRF7ry9AHQ+kgx+lAx9AT0BDHRJfAD4wIwM8jPhYgS+lLPhBBz+gJJSgH+MYIJMS0AggnZBcCCEAVdSoCCEATjOICCC8FNwLYJoIIQC+vCAKCgoIIA3xX4l1i+8vTTPzH6APpQ10zQ1ywhi7RsrPK/0z/TP9MHIcFB8oUBqgLXGNTU+lDXTCLQggDfEyHHALPy9CDXSwGRMJuBNLwBwAHy9NdM0OL6APpIMUsAWmwhyM+S5gMtOhTLPxLLPxP6UhL6Us+QAAN8RsnIz4UIEvpScc8LbszJgED7AAAughA1H3fjzwuFE8s/EszLH/pUyYBA+wAARAGCAN8YC7oa8vSCAN8UCccAGfL0+JcQaBBXEEYQNUQw8AYAAAGpO2i7fvXLCeQ2+0MjkTXLCfPFPJUlFtw2zHhggDCiiNus/L0IYIAwooExwUT8vQgbQPXCz+LAgHIyz8V+lIS+lLJyM+HIBTOcc8LYRPMyXD7AOMNf4E8AVwhbpJbcOCCaQAAAAAAAAAAAAAAAAAAASKDBvQOb6Exklt/4AGDBvQOb6ExgAGZsEtM/+kgwggDCiFE0xwUT8vSCAMKJUyPHBbPy9CGLAsjPhyDOcM8LYRLLPxL6Uslw+wACASBSUwH3TtRNDTHzH6SDH6UDH6SPQE9AHXTND6SDH6UDH0BPQEMdEq8AOCAN8RAbPy9CVukjUEkTHiUoCAQPQOb6GOIRAoXwjIz4WI+lKCEFpF1DTPC47LP4IA3wzPC//JgED7AOH6SNHIz5DF2jZWGss/GMs/JtdJIKk4AvJFqwKFoD9Qg1wsfghD////+uo9i1ywn////9PK/1NMHMdcKHwHQ1ywn0+0iJI4y0z/UMdMfMfQB+lAwIG6SXwOOHviSyM+FCBL6UoIQt246hM8LjhLLP/pSyh/JgED7AOLg1ywhqPu/HOMC1ywgfFP1LOMC8j/g0x8x1ywi2l49NIFRVVgL3O1E0FMz0ALTHzH6SDH6UDH6SPQFA9csIYu0bKzyv9Y/0z/TByHBQfKFAaoC1xjU1PpQUlqAQPQOb6GOJV8KyM+TsI8VioIA3wzPC/8TzM7JyM+FiBL6UnHPC27MyYBA+wDhPG6UEGdfB+MNA/pI0cjPknCzMfoUzPpSzoFhZAODTP9TTHzH6UDAgbpJfBI5fAdDT/zHXTNDtRNAB+kgx1ws/AdMfMfpIMfpQMfpIMfQB9AUhggDfDQKAQPQOb6ES8vT6SNH4ksjPkuYDLToVyz8Syz8S+lIS+lISyh/JyM+FCBL6UnHPC27MyYBA+wDiAFjTP/oAMfpIMPiSyPpS+lLLP8ofycjPjxgABIIQ2LyjNc8L93HPC2HMyXD7AALcjlfXC7/4ku1E0NMfMfpIMfpQMfpIMfQEMfQE1DHRIsjLv89Q1ws/ggDfDQKAQPQOb6ES8vT6SNGCCRKogMjPhYgS+lIB+gKCEC3PKkPPC4oSy7/6Uslw+wDg1ywhR6CzfOMC1ywhbnlSHOMC8j9XVwBG1wu/+JLI+lLLv8nIz48YAASCEFjk9mTPC/dxzwthzMlw+wAAUDbIz5DF2jZWFM4Syz8h10kgqTgC8kWrAiDBQfKFzwsHzswSzPpUzskAJMnIz4WIEvpScc8LbszJgED7AABeIMFB8oXPCwcWzhTMEsz6VMzJyM+FiBT6UoIQ3PmTws8LjhPMEvpSAfoCyYBA+wAAHyBTbwBi1MS42LjCMcF8vSAADyLUxLjYuMYg'); static Errors = { 'Common_Error.CrossChainAddressOutOfRange': 5, diff --git a/contracts/wrappers/gen/ccip/pools/BurnMintTokenPool.ts b/contracts/wrappers/gen/ccip/pools/BurnMintTokenPool.ts index 4755460c3..6d783b82f 100644 --- a/contracts/wrappers/gen/ccip/pools/BurnMintTokenPool.ts +++ b/contracts/wrappers/gen/ccip/pools/BurnMintTokenPool.ts @@ -5448,7 +5448,7 @@ function calculateDeployedAddress(code: c.Cell, data: c.Cell, options: DeployedA } export class BurnMintTokenPool implements c.Contract { - static CodeCell = c.Cell.fromBase64('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'); + static CodeCell = c.Cell.fromBase64('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'); static Errors = { 'Common_Error.CrossChainAddressOutOfRange': 5, diff --git a/contracts/wrappers/gen/ccip/pools/LockReleaseLockboxTokenPool.ts b/contracts/wrappers/gen/ccip/pools/LockReleaseLockboxTokenPool.ts index 815fe191a..5eaa75932 100644 --- a/contracts/wrappers/gen/ccip/pools/LockReleaseLockboxTokenPool.ts +++ b/contracts/wrappers/gen/ccip/pools/LockReleaseLockboxTokenPool.ts @@ -5418,7 +5418,7 @@ function calculateDeployedAddress(code: c.Cell, data: c.Cell, options: DeployedA } export class LockReleaseLockboxTokenPool implements c.Contract { - static CodeCell = c.Cell.fromBase64('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'); + static CodeCell = c.Cell.fromBase64('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'); static Errors = { 'Common_Error.CrossChainAddressOutOfRange': 5, diff --git a/contracts/wrappers/gen/ccip/pools/LockReleaseTokenPool.ts b/contracts/wrappers/gen/ccip/pools/LockReleaseTokenPool.ts index 07ff0c1e8..4ec83d876 100644 --- a/contracts/wrappers/gen/ccip/pools/LockReleaseTokenPool.ts +++ b/contracts/wrappers/gen/ccip/pools/LockReleaseTokenPool.ts @@ -5144,7 +5144,7 @@ function calculateDeployedAddress(code: c.Cell, data: c.Cell, options: DeployedA } export class LockReleaseTokenPool implements c.Contract { - static CodeCell = c.Cell.fromBase64('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'); + static CodeCell = c.Cell.fromBase64('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'); static Errors = { 'Common_Error.CrossChainAddressOutOfRange': 5, From 69ce5594529228e653f796ca00d0607f99cddbb2 Mon Sep 17 00:00:00 2001 From: Kristijan Date: Thu, 17 Sep 2026 12:24:42 +0200 Subject: [PATCH 15/23] perf(ccip): lazy-load pool config fields in guards and hot paths Wrap single-field reads of adminConfig/localPolicy/prepared with `lazy` so TVM deserializes only the prefix up to the accessed field instead of full config structs. Applies to onlyRouter, onlyAdvancedPoolHooks, onlyOwnerOr*, curse checks, validators, finalize/refund paths, and preflight/postflight checks. --- .../ccip/pools/lib/token_pool/entrypoint.tolk | 82 +++++++++++-------- 1 file changed, 46 insertions(+), 36 deletions(-) diff --git a/contracts/contracts/ccip/pools/lib/token_pool/entrypoint.tolk b/contracts/contracts/ccip/pools/lib/token_pool/entrypoint.tolk index 0adb5ca51..abbd00899 100644 --- a/contracts/contracts/ccip/pools/lib/token_pool/entrypoint.tolk +++ b/contracts/contracts/ccip/pools/lib/token_pool/entrypoint.tolk @@ -277,12 +277,14 @@ fun TokenPool.getAllowedFinalityConfig(self): uint32 { /// Gets the advanced pool hook contract address used by this pool. @inline fun TokenPool.getAdvancedPoolHooks(self): address? { - return self.data.adminConfig.load().advancedPoolHooks; + val adminConfig = lazy self.data.adminConfig.load(); + return adminConfig.advancedPoolHooks; } @inline fun TokenPool.verifyNotCursed(self, subject: uint128): bool { - return !self.data.localPolicy.load().cursedSubjects.isCursed(subject); + val localPolicy = lazy self.data.localPolicy.load(); + return !localPolicy.cursedSubjects.isCursed(subject); } /// Checks whether a remote chain is supported in the token pool. @@ -942,8 +944,7 @@ fun TokenPool.refundLockOrBurnRateLimit( forwardPayload: TokenPool_LockOrBurnForwardPayload, ): void { val requestMsg = lazy forwardPayload.requestMsg.load(); - val request = lazy requestMsg.request.load(); - val details = lazy request.transfer.details.load(); + val details = lazy requestMsg.request.load().transfer.details.load(); val prepared = lazy forwardPayload.prepared.load(); if (requestMsg.requestedFinalityConfig != TOKEN_POOL_WAIT_FOR_FINALITY_FLAG) { @@ -962,8 +963,7 @@ fun TokenPool.refundReleaseOrMintRateLimit( forwardPayload: TokenPool_ReleaseOrMintForwardPayload, ): void { val requestMsg = lazy forwardPayload.requestMsg.load(); - val request = lazy requestMsg.request.load(); - val details = lazy request.transfer.details.load(); + val details = lazy requestMsg.request.load().transfer.details.load(); val prepared = lazy forwardPayload.prepared.load(); if (requestMsg.requestedFinalityConfig != TOKEN_POOL_WAIT_FOR_FINALITY_FLAG) { @@ -1039,7 +1039,8 @@ fun TokenPool.getFee( requestedFinalityConfig: uint32, _tokenArgs: cell?, ): (coins, uint32, uint32, uint16, bool) { - TokenPool.ensureRequestedFinalityAllowed(requestedFinalityConfig, self.data.adminConfig.load().allowedFinalityConfig); + val adminConfig = lazy self.data.adminConfig.load(); + TokenPool.ensureRequestedFinalityAllowed(requestedFinalityConfig, adminConfig.allowedFinalityConfig); val entry = self.data.tokenTransferFeeConfigs.get(destChainSelector); if (!entry.isFound) { @@ -1194,7 +1195,8 @@ fun TokenPool.validateGetCCVsRequest( remoteChainSelector: uint64, requestedFinalityConfig: uint32, ): void { - TokenPool.ensureRequestedFinalityAllowed(requestedFinalityConfig, self.data.adminConfig.load().allowedFinalityConfig); + val adminConfig = lazy self.data.adminConfig.load(); + TokenPool.ensureRequestedFinalityAllowed(requestedFinalityConfig, adminConfig.allowedFinalityConfig); assert(self.isSupportedToken(localToken), TokenPool_Error.InvalidToken); self.requireSupportedChain(remoteChainSelector); } @@ -1216,7 +1218,8 @@ fun TokenPool.onGetCCVs( fees, }; - val hooks = self.data.adminConfig.load().advancedPoolHooks; + val adminConfig = lazy self.data.adminConfig.load(); + val hooks = adminConfig.advancedPoolHooks; if (hooks != null) { val ccvAmount = self.getCCVAmount(msg.remoteChainSelector, msg.amount, msg.requestedFinalityConfig, msg.direction, msg.extraData); val hooksMsg = createMessage({ @@ -1334,7 +1337,8 @@ fun TokenPool.onQueryCCVsReply( sender: address, msg: TokenPool_QueryCCVsReply, ): void { - val hooks = self.data.adminConfig.load().advancedPoolHooks; + val adminConfig = lazy self.data.adminConfig.load(); + val hooks = adminConfig.advancedPoolHooks; assert(hooks != null && hooks! == sender, TokenPool_Error.Unauthorized); assert(msg.replyPayload != null, TokenPool_Error.MissingForwardPayload); @@ -1382,7 +1386,7 @@ fun TokenPool.validateLockOrBurn( return (wait, prepared); } - val request = msg.request.load(); + val request = lazy msg.request.load(); val details: TokenPool_TransferDetails, coins> = lazy request.transfer.details.load(); assert(self.isSupportedToken(details.localToken), TokenPool_Error.InvalidToken); self.requireSupportedChain(details.remoteChainSelector); @@ -1394,7 +1398,8 @@ fun TokenPool.validateLockOrBurn( // Consume rate limit BEFORE hook check — _consume throws BucketOverfilled // designed to bounce to the original sender, not to the hooks contract. if (msg.requestedFinalityConfig != TOKEN_POOL_WAIT_FOR_FINALITY_FLAG) { - TokenPool.ensureRequestedFinalityAllowed(msg.requestedFinalityConfig, self.data.adminConfig.load().allowedFinalityConfig); + val adminConfig = lazy self.data.adminConfig.load(); + TokenPool.ensureRequestedFinalityAllowed(msg.requestedFinalityConfig, adminConfig.allowedFinalityConfig); self.consumeFastFinalityOutboundRateLimit(details.remoteChainSelector, destTokenAmount); } else { self.consumeOutboundRateLimit(details.remoteChainSelector, destTokenAmount); @@ -1551,8 +1556,8 @@ fun TokenPool.assertAuthorizedDepositInitiator( initiator: address, originalSender: address, ): void { - val adminConfig = self.data.adminConfig.load(); - val dynamicConfig = adminConfig.dynamicConfig.load(); + val adminConfig = lazy self.data.adminConfig.load(); + val dynamicConfig = lazy adminConfig.dynamicConfig.load(); // The Router itself is always a trusted source (standard Router -> pool withdraw path). if (initiator == dynamicConfig.router) { @@ -1590,7 +1595,8 @@ fun TokenPool.deriveDepositAccount( namespace: Namespace, user: address, ): AutoDeployAddress { - val code = self.data.adminConfig.load().deployableCode; + val adminConfig = lazy self.data.adminConfig.load(); + val code = adminConfig.deployableCode; assert(code != null, TokenPool_Error.Unauthorized); return AutoDeployAddress { stateInit: ContractState { @@ -1673,8 +1679,7 @@ fun TokenPool.failLockOrBurnTransfer( /// @dev Sends AskToTransfer to the pool's jetton wallet with original sender as recipient. fun TokenPool.returnTransferLocked(self, forwardPayload: TokenPool_LockOrBurnForwardPayload) { val requestMsg = lazy forwardPayload.requestMsg.load(); - val request = lazy requestMsg.request.load(); - val details = lazy request.transfer.details.load(); + val details = lazy requestMsg.request.load().transfer.details.load(); val returnTransfer = createMessage({ bounce: BounceMode.NoBounce, @@ -1726,8 +1731,8 @@ fun TokenPool.onLockOrBurnTransferFinalize( val requestMsg = lazy fwdPayload.requestMsg.load(); val prepared = lazy fwdPayload.prepared.load(); - val request = requestMsg.request.load(); - val details = request.transfer.details.load(); + val request = lazy requestMsg.request.load(); + val details = lazy request.transfer.details.load(); emit(TOPIC_TOKEN_POOL_LOCKED_OR_BURNED, TokenPool_LockedOrBurned { remoteChainSelector: details.remoteChainSelector, details: TokenPool_LockedOrBurnedDetails { @@ -1778,8 +1783,8 @@ fun TokenPool.validateReleaseOrMint( return (wait, prepared); } - val request = msg.request.load(); - val details = request.transfer.details.load(); + val request = lazy msg.request.load(); + val details = lazy request.transfer.details.load(); assert(self.isSupportedToken(details.localToken), TokenPool_Error.InvalidToken); self.requireSupportedChain(details.remoteChainSelector); self.ensureNotCursed(details.remoteChainSelector); @@ -1792,7 +1797,8 @@ fun TokenPool.validateReleaseOrMint( // Consume rate limit BEFORE hook check — _consume throws BucketOverfilled // designed to bounce to the original sender, not to the hooks contract. if (msg.requestedFinalityConfig != TOKEN_POOL_WAIT_FOR_FINALITY_FLAG) { - TokenPool.ensureRequestedFinalityAllowed(msg.requestedFinalityConfig, self.data.adminConfig.load().allowedFinalityConfig); + val adminConfig = lazy self.data.adminConfig.load(); + TokenPool.ensureRequestedFinalityAllowed(msg.requestedFinalityConfig, adminConfig.allowedFinalityConfig); self.consumeFastFinalityInboundRateLimit(details.remoteChainSelector, localAmount); } else { self.consumeInboundRateLimit(details.remoteChainSelector, localAmount); @@ -1861,8 +1867,8 @@ fun TokenPool.onReleaseOrMintFinalize( msg: TokenPool_ReleaseOrMint, prepared: TokenPool_ReleaseOrMintPrepared, ): void { - val request = msg.request.load(); - val details = request.transfer.details.load(); + val request = lazy msg.request.load(); + val details = lazy request.transfer.details.load(); emit(TOPIC_TOKEN_POOL_RELEASED_OR_MINTED, TokenPool_ReleasedOrMinted { remoteChainSelector: details.remoteChainSelector, details: TokenPool_ReleasedOrMintedDetails { @@ -1946,9 +1952,9 @@ fun TokenPool.requireSupportedChain(self, remoteChainSelector: uint64) { /// Checks whether the msg.sender is either the owner or the rate limit admin. fun TokenPool.onlyOwnerOrRateLimitAdmin(self, sender: address) { - val adminConfig = self.data.adminConfig.load(); - val dynamicConfig = adminConfig.dynamicConfig.load(); - val ownable = adminConfig.ownable.load(); + val adminConfig = lazy self.data.adminConfig.load(); + val dynamicConfig = lazy adminConfig.dynamicConfig.load(); + val ownable = lazy adminConfig.ownable.load(); val senderIsRateLimitAdmin = fun () { return dynamicConfig.rateLimitAdmin != null && sender == dynamicConfig.rateLimitAdmin; @@ -1961,8 +1967,8 @@ fun TokenPool.onlyOwnerOrRateLimitAdmin(self, sender: address) { /// Checks whether the msg.sender is either the owner or the RMN proxy. fun TokenPool.onlyOwnerOrRMNProxy(self, sender: address) { - val adminConfig = self.data.adminConfig.load(); - val ownable = adminConfig.ownable.load(); + val adminConfig = lazy self.data.adminConfig.load(); + val ownable = lazy adminConfig.ownable.load(); assert( sender == ownable.owner || (adminConfig.rmnProxy != null && sender == adminConfig.rmnProxy!), TokenPool_Error.Unauthorized @@ -1972,15 +1978,17 @@ fun TokenPool.onlyOwnerOrRMNProxy(self, sender: address) { /// Restricts CCIP token operations to the configured Router. The Router owns ramp authentication /// and applies its own RMN policy; the pool applies its local cursed-subject policy independently. fun TokenPool.onlyRouter(self, sender: address) { - val router = self.data.adminConfig.load().dynamicConfig.load().router; - assert(sender == router, TokenPool_Error.Unauthorized); + val adminConfig = lazy self.data.adminConfig.load(); + val dynamicConfig = lazy adminConfig.dynamicConfig.load(); + assert(sender == dynamicConfig.router, TokenPool_Error.Unauthorized); } /// Authenticates asynchronous pool-hook continuations. Without this boundary, /// an arbitrary sender could forge a success/failure continuation after the /// Router-authenticated operation returned to the async flow. fun TokenPool.onlyAdvancedPoolHooks(self, sender: address) { - val hooks = self.data.adminConfig.load().advancedPoolHooks; + val adminConfig = lazy self.data.adminConfig.load(); + val hooks = adminConfig.advancedPoolHooks; assert(hooks != null && sender == hooks!, TokenPool_Error.Unauthorized); } @@ -2004,10 +2012,11 @@ fun TokenPool.preflightCheck( } // Check if on-chain async hooks are configured. - val hooks = self.data.adminConfig.load().advancedPoolHooks; + val adminConfig = lazy self.data.adminConfig.load(); + val hooks = adminConfig.advancedPoolHooks; if (hooks != null) { // amountPostFee is already computed in fwdPayload.prepared.destTokenAmount. - val prepared = fwdPayload.prepared.load(); + val prepared = lazy fwdPayload.prepared.load(); // Send async preflight check to hooks with replyPayload for callback resumption. val hooksMsg = createMessage({ @@ -2044,10 +2053,11 @@ fun TokenPool.postflightCheck( } // Check if on-chain async hooks are configured. - val hooks = self.data.adminConfig.load().advancedPoolHooks; + val adminConfig = lazy self.data.adminConfig.load(); + val hooks = adminConfig.advancedPoolHooks; if (hooks != null) { // localAmount is already computed in fwdPayload.prepared.localAmount. - val prepared = fwdPayload.prepared.load(); + val prepared = lazy fwdPayload.prepared.load(); // Send async postflight check to hooks with replyPayload for callback resumption. val hooksMsg = createMessage({ From f9f8543892721c323ea240119f60340a1dc7e92f Mon Sep 17 00:00:00 2001 From: Kristijan Date: Thu, 17 Sep 2026 13:36:32 +0200 Subject: [PATCH 16/23] refactor(cciplib): unify tlbe uint tests, drop dead BigUint Merge boxeduint/uint128 tests into biguint_test.go, remove the unused dynamic-width BigUint (superseded by comparable Uint128/160/256), and fix checkstyle (G115, unused, testifylint, revive). --- cciplib/ton/tlbe/biguint.go | 61 +------- cciplib/ton/tlbe/biguint_test.go | 242 +++++++++++++++++++++++++++++ cciplib/ton/tlbe/boxeduint_test.go | 185 ---------------------- cciplib/ton/tlbe/uint128_test.go | 97 ------------ 4 files changed, 243 insertions(+), 342 deletions(-) delete mode 100644 cciplib/ton/tlbe/boxeduint_test.go delete mode 100644 cciplib/ton/tlbe/uint128_test.go diff --git a/cciplib/ton/tlbe/biguint.go b/cciplib/ton/tlbe/biguint.go index 1a5eb24bb..234fb8620 100644 --- a/cciplib/ton/tlbe/biguint.go +++ b/cciplib/ton/tlbe/biguint.go @@ -2,7 +2,6 @@ package tlbe // tlb extras import ( "encoding/json" - "errors" "fmt" "math/big" "strings" @@ -25,64 +24,6 @@ func AsUnsigned(v *big.Int, sz uint) *big.Int { return new(big.Int).And(v, mask) // interpret as uint sz } -// BigUint stores an unsigned integer with a fixed bit width for TLB encoding. -type BigUint struct { - Bits uint - Value *big.Int -} - -// loadFromCell enforces unsigned semantics for the configured bit width. -func (b *BigUint) loadFromCell(bits uint, loader *cell.Slice) error { - if b == nil { - return errors.New("BigUint pointer is nil") - } - if loader == nil { - return errors.New("cell loader is nil") - } - - width := bits - if width == 0 { - width = b.Bits - } - if width == 0 { - return errors.New("bit width must be greater than zero") - } - - val, err := loader.LoadBigInt(width) - if err != nil { - return fmt.Errorf("failed to load bigint: %w", err) - } - - b.Bits = width - b.Value = AsUnsigned(val, width) - return nil -} - -// toCell serializes the stored number using unsigned semantics for width bits. -func (b BigUint) toCell(bits uint) (*cell.Cell, error) { - width := bits - if width == 0 { - width = b.Bits - } - if width == 0 { - return nil, errors.New("bit width must be greater than zero") - } - - val := b.Value - if val == nil { - val = new(big.Int) - } - - unsigned := AsUnsigned(val, width) - - builder := cell.BeginCell() - if err := builder.StoreBigInt(unsigned, width); err != nil { - return nil, fmt.Errorf("failed to store bigint: %w", err) - } - - return builder.EndCell(), nil -} - // --- Fixed-width unsigned integers --- // // Uint128/Uint160/Uint256 are boxed fixed-width unsigned integers used to model @@ -139,7 +80,7 @@ func uintBytesFromCell(dst []byte, loader *cell.Slice) error { if err != nil { return fmt.Errorf("failed to load byte %d: %w", i, err) } - dst[i] = byte(by) + dst[i] = byte(by) //nolint:gosec // G115: LoadUInt(8) always fits in a byte } return nil diff --git a/cciplib/ton/tlbe/biguint_test.go b/cciplib/ton/tlbe/biguint_test.go index cc6c172d6..2ed4a65d7 100644 --- a/cciplib/ton/tlbe/biguint_test.go +++ b/cciplib/ton/tlbe/biguint_test.go @@ -1,6 +1,7 @@ package tlbe // tlb extras import ( + "encoding/json" "errors" "fmt" "math/big" @@ -28,6 +29,176 @@ type ptrTypedValues struct { Root *Uint256 `tlb:"."` } +// uint128SetHolder guards the generic path used by CursedSubjects: a struct +// field with a tlb:"." tag holding a *Dict[Uint128, struct{}]. +type uint128SetHolder struct { + Subjects *Dict[Uint128, struct{}] `tlb:"."` +} + +// bigFromHex builds a big.Int from a hex string (helper for readable test cases). +func bigFromHex(t *testing.T, s string) *big.Int { + t.Helper() + v, ok := new(big.Int).SetString(s, 16) + require.True(t, ok) + return v +} + +// TestUintWrappers_WireCompatWithRawStore locks in that the byte-based codec +// produces exactly the same cell as a raw fixed-width store, so on-chain data +// stays bit-identical to the previous BigUint/StoreBigInt path. +func TestUintWrappers_WireCompatWithRawStore(t *testing.T) { + v := new(big.Int).Add(new(big.Int).Lsh(big.NewInt(9), 200), big.NewInt(1234567)) + + cases := []struct { + name string + boxed any + raw *cell.Cell + }{ + {"uint128", *NewUint128(v), cell.BeginCell().MustStoreBigInt(AsUnsigned(v, 128), 128).EndCell()}, + {"uint160", *NewUint160(v), cell.BeginCell().MustStoreBigInt(AsUnsigned(v, 160), 160).EndCell()}, + {"uint256", *NewUint256(v), cell.BeginCell().MustStoreBigInt(AsUnsigned(v, 256), 256).EndCell()}, + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + c, err := tlb.ToCell(tc.boxed) + require.NoError(t, err) + require.Equal(t, tc.raw.Hash(), c.Hash(), + "boxed encoding must match the raw fixed-width big-endian store") + }) + } +} + +// TestUint128_Values checks the in-memory layout: big-endian bytes, so a bit set +// at position N lands in the expected word of F. +func TestUint128_Values(t *testing.T) { + // A value above the 64-bit range exercises multiple bytes. + v := new(big.Int).Add(new(big.Int).Lsh(big.NewInt(1), 100), big.NewInt(12345)) + + u := NewUint128(v) + require.Equal(t, v, u.ToBigInt()) + require.Equal(t, uint8(0x0), u.F[0]) // high bytes zero + require.Equal(t, uint8(0x10), u.F[3]) // 2^100 sets bit 4 of byte 3 + + // Zero and max round-trip through the bytes. + require.Equal(t, big.NewInt(0), NewUint128(big.NewInt(0)).ToBigInt()) + + maxVal := new(big.Int).Sub(new(big.Int).Lsh(big.NewInt(1), 128), big.NewInt(1)) + require.Equal(t, maxVal, NewUint128(maxVal).ToBigInt()) +} + +// TestUintWrappers_AreComparable locks in the core property: the boxed fixed-width +// uints are value types with == semantics (unlike a big.Int alias), so they can +// be used as Go map / tlbe.Dict keys. +func TestUintWrappers_AreComparable(t *testing.T) { + v128 := new(big.Int).Lsh(big.NewInt(1), 100) + a128, b128 := *NewUint128(v128), *NewUint128(v128) + require.True(t, a128 == b128, "equal Uint128 values must compare equal with ==") + require.False(t, a128 == *NewUint128(big.NewInt(1)), "different Uint128 values must compare unequal with ==") + + v160 := new(big.Int).Lsh(big.NewInt(1), 159) + a160, b160 := *NewUint160(v160), *NewUint160(v160) + require.True(t, a160 == b160, "equal Uint160 values must compare equal with ==") + require.False(t, a160 == *NewUint160(big.NewInt(1)), "different Uint160 values must compare unequal with ==") + + v256 := new(big.Int).Lsh(big.NewInt(1), 255) + a256, b256 := *NewUint256(v256), *NewUint256(v256) + require.True(t, a256 == b256, "equal Uint256 values must compare equal with ==") + require.False(t, a256 == *NewUint256(big.NewInt(1)), "different Uint256 values must compare unequal with ==") +} + +// TestUintWrappers_DictKeyRoundTrip is the regression test for the pointer-key +// bug: boxed uint keys of every width must survive +// ToCell -> LoadDict -> NewDictFromDictionary (the previous *Uint256 key form +// mis-keyed and panicked in tonutils' reflection path). +func TestUintWrappers_DictKeyRoundTrip(t *testing.T) { + t.Run("uint128", func(t *testing.T) { + d := NewDict[Uint128, struct{}](map[Uint128]struct{}{ + *NewUint128(big.NewInt(5)): {}, + *NewUint128(new(big.Int).Lsh(big.NewInt(1), 127)): {}, + }) + + c, err := d.ToCell() + require.NoError(t, err) + + dict, err := c.BeginParse().LoadDict(128) + require.NoError(t, err) + + restored, err := NewDictFromDictionary[Uint128, struct{}](dict) + require.NoError(t, err) + require.Len(t, restored.AsMap(), 2) + + _, ok := restored.Get(*NewUint128(big.NewInt(5))) + require.True(t, ok) + _, ok = restored.Get(*NewUint128(new(big.Int).Lsh(big.NewInt(1), 127))) + require.True(t, ok) + }) + + t.Run("uint160", func(t *testing.T) { + d := NewDict[Uint160, bool](map[Uint160]bool{ + *NewUint160(big.NewInt(5)): true, + *NewUint160(new(big.Int).Lsh(big.NewInt(1), 159)): false, + *NewUint160(bigFromHex(t, "ffffffffffffffffffffffffffffffffffffffff")): true, + }) + + c, err := d.ToCell() + require.NoError(t, err) + + dict, err := c.BeginParse().LoadDict(160) + require.NoError(t, err) + + restored, err := NewDictFromDictionary[Uint160, bool](dict) + require.NoError(t, err) + require.Len(t, restored.AsMap(), 3) + + v, ok := restored.Get(*NewUint160(big.NewInt(5))) + require.True(t, ok) + require.True(t, v) + + v, ok = restored.Get(*NewUint160(new(big.Int).Lsh(big.NewInt(1), 159))) + require.True(t, ok) + require.False(t, v) + }) + + t.Run("uint256", func(t *testing.T) { + d := NewDict[Uint256, uint64](map[Uint256]uint64{ + *NewUint256(big.NewInt(7)): 42, + *NewUint256(new(big.Int).Lsh(big.NewInt(1), 255)): 99, + }) + + c, err := d.ToCell() + require.NoError(t, err) + + dict, err := c.BeginParse().LoadDict(256) + require.NoError(t, err) + + restored, err := NewDictFromDictionary[Uint256, uint64](dict) + require.NoError(t, err) + require.Len(t, restored.AsMap(), 2) + + v, ok := restored.Get(*NewUint256(new(big.Int).Lsh(big.NewInt(1), 255))) + require.True(t, ok) + require.Equal(t, uint64(99), v) + }) +} + +// TestUint128_DictStructFieldRoundTrip guards the generic dict-in-struct path +// used by CursedSubjects. +func TestUint128_DictStructFieldRoundTrip(t *testing.T) { + original := uint128SetHolder{ + Subjects: NewDict[Uint128, struct{}](map[Uint128]struct{}{ + *NewUint128(big.NewInt(3)): {}, + }), + } + + c, err := tlb.ToCell(original) + require.NoError(t, err) + + var decoded uint128SetHolder + require.NoError(t, tlb.LoadFromCell(&decoded, c.BeginParse())) + require.Len(t, decoded.Subjects.AsMap(), 1) +} + func TestUintWrappers_MaskSignBit(t *testing.T) { testCases := []struct { name string @@ -145,3 +316,74 @@ func encodeFixed(addr, root []byte) (*cell.Cell, error) { return builder.EndCell(), nil } + +// TestUintWrappers_CellRoundTripAndWidth checks each type's cell width and value. +func TestUintWrappers_CellRoundTripAndWidth(t *testing.T) { + testCases := []struct { + name string + build func(*big.Int) (any, uint) + }{ + {"uint128", func(v *big.Int) (any, uint) { return *NewUint128(v), 128 }}, + {"uint160", func(v *big.Int) (any, uint) { return *NewUint160(v), 160 }}, + {"uint256", func(v *big.Int) (any, uint) { return *NewUint256(v), 256 }}, + } + + value := new(big.Int).Add(new(big.Int).Lsh(big.NewInt(3), 120), big.NewInt(7)) + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + original, bits := tc.build(value) + + c, err := tlb.ToCell(original) + require.NoError(t, err) + require.Equal(t, bits, c.BitsSize()) + + switch x := original.(type) { + case Uint128: + var decoded Uint128 + require.NoError(t, decoded.LoadFromCell(c.BeginParse())) + require.Equal(t, x, decoded) + require.Equal(t, x.ToBigInt(), decoded.ToBigInt()) + case Uint160: + var decoded Uint160 + require.NoError(t, decoded.LoadFromCell(c.BeginParse())) + require.Equal(t, x, decoded) + case Uint256: + var decoded Uint256 + require.NoError(t, decoded.LoadFromCell(c.BeginParse())) + require.Equal(t, x, decoded) + } + }) + } +} + +// TestUintWrappers_JSONHexRoundTrip checks canonical hex JSON for all three types. +func TestUintWrappers_JSONHexRoundTrip(t *testing.T) { + for _, jsonCase := range []struct { + value any + want string + }{ + {*NewUint128(big.NewInt(255)), `"0xff"`}, + {*NewUint160(big.NewInt(255)), `"0xff"`}, + {*NewUint256(big.NewInt(255)), `"0xff"`}, + } { + payload, err := json.Marshal(jsonCase.value) + require.NoError(t, err) + require.JSONEq(t, jsonCase.want, string(payload)) + + switch x := jsonCase.value.(type) { + case Uint128: + var d Uint128 + require.NoError(t, json.Unmarshal(payload, &d)) + require.Equal(t, x, d) + case Uint160: + var d Uint160 + require.NoError(t, json.Unmarshal(payload, &d)) + require.Equal(t, x, d) + case Uint256: + var d Uint256 + require.NoError(t, json.Unmarshal(payload, &d)) + require.Equal(t, x, d) + } + } +} diff --git a/cciplib/ton/tlbe/boxeduint_test.go b/cciplib/ton/tlbe/boxeduint_test.go deleted file mode 100644 index f863ae60d..000000000 --- a/cciplib/ton/tlbe/boxeduint_test.go +++ /dev/null @@ -1,185 +0,0 @@ -package tlbe // tlb extras - -import ( - "encoding/json" - "math/big" - "testing" - - "github.com/stretchr/testify/require" - "github.com/xssnick/tonutils-go/tlb" - "github.com/xssnick/tonutils-go/tvm/cell" -) - -// bigFromHex builds a big.Int from a hex string (helper for readable test cases). -// TestBoxedUints_WireCompatWithRawStore locks in that the new byte-based codec -// produces exactly the same cell as the previous BigUint/StoreBigInt path (and as -// a raw fixed-width store), so on-chain data stays bit-identical. -func TestBoxedUints_WireCompatWithRawStore(t *testing.T) { - v := new(big.Int).Add(new(big.Int).Lsh(big.NewInt(9), 200), big.NewInt(1234567)) - - cases := []struct { - name string - boxed any - raw *cell.Cell - }{ - {"uint128", *NewUint128(v), cell.BeginCell().MustStoreBigInt(AsUnsigned(v, 128), 128).EndCell()}, - {"uint160", *NewUint160(v), cell.BeginCell().MustStoreBigInt(AsUnsigned(v, 160), 160).EndCell()}, - {"uint256", *NewUint256(v), cell.BeginCell().MustStoreBigInt(AsUnsigned(v, 256), 256).EndCell()}, - } - - for _, tc := range cases { - t.Run(tc.name, func(t *testing.T) { - c, err := tlb.ToCell(tc.boxed) - require.NoError(t, err) - require.Equal(t, tc.raw.Hash(), c.Hash(), - "boxed encoding must match the raw fixed-width big-endian store") - }) - } -} - -func bigFromHex(t *testing.T, s string) *big.Int { - t.Helper() - v, ok := new(big.Int).SetString(s, 16) - require.True(t, ok) - return v -} - -// TestBoxedUints_AreComparable locks in the core property: the boxed fixed-width -// uints are value types with == semantics (unlike a big.Int alias), so they can -// be used as Go map / tlbe.Dict keys. -func TestBoxedUints_AreComparable(t *testing.T) { - v128 := new(big.Int).Lsh(big.NewInt(1), 100) - require.Equal(t, *NewUint128(v128), *NewUint128(v128)) - require.NotEqual(t, *NewUint128(v128), *NewUint128(big.NewInt(1))) - - v160 := new(big.Int).Lsh(big.NewInt(1), 159) - require.Equal(t, *NewUint160(v160), *NewUint160(v160)) - require.NotEqual(t, *NewUint160(v160), *NewUint160(big.NewInt(1))) - - v256 := new(big.Int).Lsh(big.NewInt(1), 255) - require.Equal(t, *NewUint256(v256), *NewUint256(v256)) - require.NotEqual(t, *NewUint256(v256), *NewUint256(big.NewInt(1))) -} - -// TestBoxedUints_DictKeyRoundTrip is the regression test for the pointer-key bug: -// Uint160/Uint256 keys must survive ToCell -> LoadDict -> NewDictFromDictionary -// (the previous *Uint256 key form panicked in tonutils' reflection path). -func TestBoxedUints_DictKeyRoundTrip(t *testing.T) { - t.Run("uint160", func(t *testing.T) { - d := NewDict[Uint160, bool](map[Uint160]bool{ - *NewUint160(big.NewInt(5)): true, - *NewUint160(new(big.Int).Lsh(big.NewInt(1), 159)): false, - *NewUint160(bigFromHex(t, "ffffffffffffffffffffffffffffffffffffffff")): true, - }) - - c, err := d.ToCell() - require.NoError(t, err) - - dict, err := c.BeginParse().LoadDict(160) - require.NoError(t, err) - - restored, err := NewDictFromDictionary[Uint160, bool](dict) - require.NoError(t, err) - require.Len(t, restored.AsMap(), 3) - - v, ok := restored.Get(*NewUint160(big.NewInt(5))) - require.True(t, ok) - require.True(t, v) - - v, ok = restored.Get(*NewUint160(new(big.Int).Lsh(big.NewInt(1), 159))) - require.True(t, ok) - require.False(t, v) - }) - - t.Run("uint256", func(t *testing.T) { - d := NewDict[Uint256, uint64](map[Uint256]uint64{ - *NewUint256(big.NewInt(7)): 42, - *NewUint256(new(big.Int).Lsh(big.NewInt(1), 255)): 99, - }) - - c, err := d.ToCell() - require.NoError(t, err) - - dict, err := c.BeginParse().LoadDict(256) - require.NoError(t, err) - - restored, err := NewDictFromDictionary[Uint256, uint64](dict) - require.NoError(t, err) - require.Len(t, restored.AsMap(), 2) - - v, ok := restored.Get(*NewUint256(new(big.Int).Lsh(big.NewInt(1), 255))) - require.True(t, ok) - require.Equal(t, uint64(99), v) - }) -} - -// TestBoxedUints_CellRoundTripAndWidth checks each type's cell width and value. -func TestBoxedUints_CellRoundTripAndWidth(t *testing.T) { - testCases := []struct { - name string - build func(*big.Int) (any, uint) - }{ - {"uint128", func(v *big.Int) (any, uint) { return *NewUint128(v), 128 }}, - {"uint160", func(v *big.Int) (any, uint) { return *NewUint160(v), 160 }}, - {"uint256", func(v *big.Int) (any, uint) { return *NewUint256(v), 256 }}, - } - - value := new(big.Int).Add(new(big.Int).Lsh(big.NewInt(3), 120), big.NewInt(7)) - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - original, bits := tc.build(value) - - c, err := tlb.ToCell(original) - require.NoError(t, err) - require.Equal(t, bits, c.BitsSize()) - - switch x := original.(type) { - case Uint128: - var decoded Uint128 - require.NoError(t, decoded.LoadFromCell(c.BeginParse())) - require.Equal(t, x, decoded) - require.Equal(t, x.ToBigInt(), decoded.ToBigInt()) - case Uint160: - var decoded Uint160 - require.NoError(t, decoded.LoadFromCell(c.BeginParse())) - require.Equal(t, x, decoded) - case Uint256: - var decoded Uint256 - require.NoError(t, decoded.LoadFromCell(c.BeginParse())) - require.Equal(t, x, decoded) - } - }) - } -} - -// TestBoxedUints_JSONHexRoundTrip checks canonical hex JSON for all three types. -func TestBoxedUints_JSONHexRoundTrip(t *testing.T) { - for _, jsonCase := range []struct { - value any - want string - }{ - {*NewUint128(big.NewInt(255)), `"0xff"`}, - {*NewUint160(big.NewInt(255)), `"0xff"`}, - {*NewUint256(big.NewInt(255)), `"0xff"`}, - } { - payload, err := json.Marshal(jsonCase.value) - require.NoError(t, err) - require.JSONEq(t, jsonCase.want, string(payload)) - - switch x := jsonCase.value.(type) { - case Uint128: - var d Uint128 - require.NoError(t, json.Unmarshal(payload, &d)) - require.Equal(t, x, d) - case Uint160: - var d Uint160 - require.NoError(t, json.Unmarshal(payload, &d)) - require.Equal(t, x, d) - case Uint256: - var d Uint256 - require.NoError(t, json.Unmarshal(payload, &d)) - require.Equal(t, x, d) - } - } -} diff --git a/cciplib/ton/tlbe/uint128_test.go b/cciplib/ton/tlbe/uint128_test.go deleted file mode 100644 index 23f3cf665..000000000 --- a/cciplib/ton/tlbe/uint128_test.go +++ /dev/null @@ -1,97 +0,0 @@ -package tlbe // tlb extras - -import ( - "encoding/json" - "math/big" - "testing" - - "github.com/stretchr/testify/require" - "github.com/xssnick/tonutils-go/tlb" -) - -func TestUint128_Values(t *testing.T) { - // A value above the 64-bit range exercises multiple bytes. - v := new(big.Int).Add(new(big.Int).Lsh(big.NewInt(1), 100), big.NewInt(12345)) - - u := NewUint128(v) - require.Equal(t, v, u.ToBigInt()) - require.Equal(t, uint8(0x0), u.F[0]) // high bytes zero - require.Equal(t, uint8(0x10), u.F[3]) // 2^100 sets bit 4 of byte 3 - - // Zero and max round-trip through the bytes. - require.Equal(t, big.NewInt(0), NewUint128(big.NewInt(0)).ToBigInt()) - - max := new(big.Int).Sub(new(big.Int).Lsh(big.NewInt(1), 128), big.NewInt(1)) - require.Equal(t, max, NewUint128(max).ToBigInt()) -} - -func TestUint128_CellRoundTrip(t *testing.T) { - v := new(big.Int).Add(new(big.Int).Lsh(big.NewInt(7), 90), big.NewInt(42)) - original := NewUint128(v) - - c, err := original.ToCell() - require.NoError(t, err) - require.Equal(t, uint(128), c.BitsSize()) - - var decoded Uint128 - require.NoError(t, decoded.LoadFromCell(c.BeginParse())) - require.Equal(t, *original, decoded) - require.Equal(t, v, decoded.ToBigInt()) -} - -func TestUint128_UsableAsDictKey(t *testing.T) { - // The whole point: Uint128 is comparable, so it keys a Dict by value and the - // key decodes correctly via NewDictFromDictionary (unlike *Uint256 keys). - d := NewDict[Uint128, struct{}](map[Uint128]struct{}{ - *NewUint128(big.NewInt(5)): {}, - *NewUint128(new(big.Int).Lsh(big.NewInt(1), 127)): {}, - }) - - c, err := d.ToCell() - require.NoError(t, err) - - dict, err := c.BeginParse().LoadDict(128) - require.NoError(t, err) - - restored, err := NewDictFromDictionary[Uint128, struct{}](dict) - require.NoError(t, err) - require.Len(t, restored.AsMap(), 2) - - _, ok := restored.Get(*NewUint128(big.NewInt(5))) - require.True(t, ok) - _, ok = restored.Get(*NewUint128(new(big.Int).Lsh(big.NewInt(1), 127))) - require.True(t, ok) -} - -func TestUint128_JSONRoundTrip(t *testing.T) { - u := NewUint128(new(big.Int).SetUint64(255)) - - payload, err := json.Marshal(u) - require.NoError(t, err) - require.JSONEq(t, `"0xff"`, string(payload)) - - var decoded Uint128 - require.NoError(t, json.Unmarshal(payload, &decoded)) - require.Equal(t, *u, decoded) -} - -// Guards the generic path used by CursedSubjects: a struct field with a -// tlb:"." tag holding a *Dict[Uint128, struct{}]. -type uint128SetHolder struct { - Subjects *Dict[Uint128, struct{}] `tlb:"."` -} - -func TestUint128_DictStructFieldRoundTrip(t *testing.T) { - original := uint128SetHolder{ - Subjects: NewDict[Uint128, struct{}](map[Uint128]struct{}{ - *NewUint128(big.NewInt(3)): {}, - }), - } - - c, err := tlb.ToCell(original) - require.NoError(t, err) - - var decoded uint128SetHolder - require.NoError(t, tlb.LoadFromCell(&decoded, c.BeginParse())) - require.Len(t, decoded.Subjects.AsMap(), 1) -} From 6cbc8ba678a51891b12611375e2f54ca4941552b Mon Sep 17 00:00:00 2001 From: Kristijan Date: Thu, 17 Sep 2026 13:39:07 +0200 Subject: [PATCH 17/23] Fix lint --- contracts/tests/ccip/offramp/OffRamp.execute.spec.ts | 5 ++++- contracts/tests/ccip/pools/BurnMintTokenPool.spec.ts | 2 +- .../tests/ccip/pools/LockReleaseLockboxTokenPool.spec.ts | 1 - 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/contracts/tests/ccip/offramp/OffRamp.execute.spec.ts b/contracts/tests/ccip/offramp/OffRamp.execute.spec.ts index f667b60c0..076cc22d2 100644 --- a/contracts/tests/ccip/offramp/OffRamp.execute.spec.ts +++ b/contracts/tests/ccip/offramp/OffRamp.execute.spec.ts @@ -25,7 +25,10 @@ import * as CCIPLogs from '../../../wrappers/ccip/Logs' import { RMNREMOTE_GLOBAL_CURSE_SUBJECT } from '../../../wrappers/ccip/Router' import * as s from './OffRamp.Setup' -import { OffRampWithTokenPoolTestSetup, PERMISSIONLESS_EXECUTION_THRESHOLD_SECONDS } from './OffRamp.Setup' +import { + OffRampWithTokenPoolTestSetup, + PERMISSIONLESS_EXECUTION_THRESHOLD_SECONDS, +} from './OffRamp.Setup' import { EXECUTE_COST, MIN_TT_GASLIMIT } from '../../../wrappers/ccip/OffRamp' import { codec } from '../../../wrappers/ccip/common/CrossChainAddressCodec' diff --git a/contracts/tests/ccip/pools/BurnMintTokenPool.spec.ts b/contracts/tests/ccip/pools/BurnMintTokenPool.spec.ts index 6d5b8ef38..d91146ee9 100644 --- a/contracts/tests/ccip/pools/BurnMintTokenPool.spec.ts +++ b/contracts/tests/ccip/pools/BurnMintTokenPool.spec.ts @@ -30,7 +30,7 @@ import { TokenPool_TokenTransferFeeConfig, TokenPool_TokenTransferFeeConfigArgs, } from '../../../wrappers/gen/ccip/pools/TokenPool' -import { +import { JettonClient, BurnMintTokenPool, BurnMintTokenPool_BurnContext, diff --git a/contracts/tests/ccip/pools/LockReleaseLockboxTokenPool.spec.ts b/contracts/tests/ccip/pools/LockReleaseLockboxTokenPool.spec.ts index 02020b55b..3d28b85ca 100644 --- a/contracts/tests/ccip/pools/LockReleaseLockboxTokenPool.spec.ts +++ b/contracts/tests/ccip/pools/LockReleaseLockboxTokenPool.spec.ts @@ -49,7 +49,6 @@ import { runTokenPoolAsyncHookBehaviorTests } from './TokenPool.asyncHook.behavi import { runTokenPoolWithdrawFeeTokensBehaviorTests } from './TokenPool.withdrawFeeTokens.behavior' import { runTokenPoolCcvFeesBehaviorTests } from './TokenPool.ccvFees.behavior' - function emptyAccessControlData(): AccessControl_Data { return { $: 'AccessControl_Data', From ac5b89b79b0bf64ebf34cb03891ee883453f6b5a Mon Sep 17 00:00:00 2001 From: Kristijan Date: Thu, 17 Sep 2026 13:55:23 +0200 Subject: [PATCH 18/23] fix(cciplib): use require.Equal/NotEqual in AreComparable (testifylint compares) --- cciplib/ton/tlbe/biguint_test.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/cciplib/ton/tlbe/biguint_test.go b/cciplib/ton/tlbe/biguint_test.go index 2ed4a65d7..46cd4ab89 100644 --- a/cciplib/ton/tlbe/biguint_test.go +++ b/cciplib/ton/tlbe/biguint_test.go @@ -93,18 +93,18 @@ func TestUint128_Values(t *testing.T) { func TestUintWrappers_AreComparable(t *testing.T) { v128 := new(big.Int).Lsh(big.NewInt(1), 100) a128, b128 := *NewUint128(v128), *NewUint128(v128) - require.True(t, a128 == b128, "equal Uint128 values must compare equal with ==") - require.False(t, a128 == *NewUint128(big.NewInt(1)), "different Uint128 values must compare unequal with ==") + require.Equal(t, a128, b128, "equal Uint128 values must compare equal") + require.NotEqual(t, a128, *NewUint128(big.NewInt(1)), "different Uint128 values must compare unequal") v160 := new(big.Int).Lsh(big.NewInt(1), 159) a160, b160 := *NewUint160(v160), *NewUint160(v160) - require.True(t, a160 == b160, "equal Uint160 values must compare equal with ==") - require.False(t, a160 == *NewUint160(big.NewInt(1)), "different Uint160 values must compare unequal with ==") + require.Equal(t, a160, b160, "equal Uint160 values must compare equal") + require.NotEqual(t, a160, *NewUint160(big.NewInt(1)), "different Uint160 values must compare unequal") v256 := new(big.Int).Lsh(big.NewInt(1), 255) a256, b256 := *NewUint256(v256), *NewUint256(v256) - require.True(t, a256 == b256, "equal Uint256 values must compare equal with ==") - require.False(t, a256 == *NewUint256(big.NewInt(1)), "different Uint256 values must compare unequal with ==") + require.Equal(t, a256, b256, "equal Uint256 values must compare equal") + require.NotEqual(t, a256, *NewUint256(big.NewInt(1)), "different Uint256 values must compare unequal") } // TestUintWrappers_DictKeyRoundTrip is the regression test for the pointer-key From 5a9fea4ca7efff6a20713fb0f9e79f1b9b8f253e Mon Sep 17 00:00:00 2001 From: Kristijan Date: Thu, 17 Sep 2026 13:57:21 +0200 Subject: [PATCH 19/23] Fix yarn.lock --- yarn.lock | 7 ------- 1 file changed, 7 deletions(-) diff --git a/yarn.lock b/yarn.lock index f647bc134..8e5fcc9e0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1898,13 +1898,6 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" -brace-expansion@^2.0.1: - version "2.1.4" - resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.1.4.tgz#589dab11c0018d0366be64cd8bf12c8dbecc8326" - integrity sha512-hGfVzPxthbf3+2yjg/RBs60cB0FhqBS/zvdV/4wn4/BmN0bNMMHPc4V/BbFieqf1TKAGGAHnY4eSjajCl0f2Xg== - dependencies: - balanced-match "^1.0.0" - braces@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" From 78c2b909919eb35453c159ce1bd4bd6ca46330d3 Mon Sep 17 00:00:00 2001 From: "app-token-issuer-integrations[bot]" <204793122+app-token-issuer-integrations[bot]@users.noreply.github.com> Date: Thu, 17 Sep 2026 13:35:16 +0000 Subject: [PATCH 20/23] chore(nix): update lock.nix hashes --- contracts/lock.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/lock.nix b/contracts/lock.nix index 636e2ebcc..ee79112fe 100644 --- a/contracts/lock.nix +++ b/contracts/lock.nix @@ -1,6 +1,6 @@ # Notice: `pkgs.lib.fakeHash` can be used as a placeholder, # but `lock-nix-tidy` will only replace actual hashes. {pkgs}: { - contracts = "sha256-N44oIDHzh+gm8wN2tOr1A8mw6Fpbpx/Tf6xddnAgXm4="; + contracts = "sha256-mfyWD81+t5rLUeVQ7V+ZFLiLMjn62J2+BGPv4iEdwBA="; contracts-jetton = "sha256-EZtvTf19MjSKTWNir6pcP9XHwUIpE4ILSlhS+cQD/7w="; } From 09172bde3009f01c412b049b87b1889dd8bcf5a7 Mon Sep 17 00:00:00 2001 From: "app-token-issuer-integrations[bot]" <204793122+app-token-issuer-integrations[bot]@users.noreply.github.com> Date: Tue, 22 Sep 2026 17:57:40 +0000 Subject: [PATCH 21/23] chore(nix): update lock.nix hashes --- contracts/lock.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/lock.nix b/contracts/lock.nix index ee79112fe..ffadbde4f 100644 --- a/contracts/lock.nix +++ b/contracts/lock.nix @@ -1,6 +1,6 @@ # Notice: `pkgs.lib.fakeHash` can be used as a placeholder, # but `lock-nix-tidy` will only replace actual hashes. {pkgs}: { - contracts = "sha256-mfyWD81+t5rLUeVQ7V+ZFLiLMjn62J2+BGPv4iEdwBA="; + contracts = "sha256-J4nYpyBXWj4xe+5O2xq3jtZT4ihl4crzwGLOZGzMQbA="; contracts-jetton = "sha256-EZtvTf19MjSKTWNir6pcP9XHwUIpE4ILSlhS+cQD/7w="; } From ac8258397b2231fd98047e3f86e5bfe987216295 Mon Sep 17 00:00:00 2001 From: Kristijan Date: Tue, 22 Sep 2026 21:27:01 +0200 Subject: [PATCH 22/23] Add ./cciplib local replace (tmp) --- contracts/wrappers/gen/ccip/OffRamp.ts | 2 +- deployment/go.mod | 3 +++ deployment/go.sum | 2 -- devenv/go.mod | 3 +++ devenv/go.sum | 2 -- go.mod | 3 +++ go.sum | 2 -- 7 files changed, 10 insertions(+), 7 deletions(-) diff --git a/contracts/wrappers/gen/ccip/OffRamp.ts b/contracts/wrappers/gen/ccip/OffRamp.ts index 700284dae..836f42f4b 100644 --- a/contracts/wrappers/gen/ccip/OffRamp.ts +++ b/contracts/wrappers/gen/ccip/OffRamp.ts @@ -4326,7 +4326,7 @@ function calculateDeployedAddress(code: c.Cell, data: c.Cell, options: DeployedA } export class OffRamp implements c.Contract { - static CodeCell = c.Cell.fromBase64('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'); + static CodeCell = c.Cell.fromBase64('te6ccgECzgEAK0MAART/APSkE/S88sgLAQIBYgIDAgLGBAUCASBvcAIByQYHAgOj0iYnAgEgCAkCAWIfIAIBIAoLAgEgFBUCASAoKQIBIAwNAgEgDg8CASASEwChDMiwACOHzAxIG6YMG1tbW1tbXDg0NP/0wfTB9IA9AT0BNGBAIXgMQHAAY4dIG6YMG1tbW1tbXDg0NP/0wfTB9IA9AT0BNGBAIXgggDU8vLwgAvcM0h2JPAEggDU8jXDABTy9CWCANTsBroV8vSCANTtUHKBAQv0Cm+hMfL0BI7CA6Qm0IMG+UMwMYE0vCGpOALy8qsCgGCpBIIA1O4CuvL0A8jMI88L/3DPC78kzws/+RZwBtCUIMcAs4roECNfAzMClDA1bCHiyM+PGAAEgEBEA0iDXSwGRMJuBNLwBwAHy9NdM0OLT/9P/0/9UczaDB/QOb6GCANTvAfL00wfRggDU8QbIy/8Vy/8Ty//PUNP/MVRFE/kQE/L0ggDU8IE0vSKDB7ny9CGuKbDAAPL0gTS9IYMHufL0rhexBgAwghBmwjN4zwv3cM8LYcsPEsv/yz/JcPsAAFcIW6SW3DggmkAAAAAAAAAAAAAAAAAAAEigwb0Dm+hMZJbf+ABgwb0Dm+hMYABnO2i7fsQJF8EM8MAlSBus8MAkXDijhrwDyBulYFWZ/Lw4CCbIIFWaAO+EvL02zHgMJEw4oAIBIBYXAgEgXl8CASAYGQIBIBobAEEMsMAlSFus8MAkXDilSHDAMMAkXDimCGBVmgCvvL04DGAAGSVggl9eEDgggqupUCAC9w0bFU1NTUD0NP/0z/TPzHTPzHTPzHU1PpI+gAx9ATRJIFWVQiAQPQOb6EY8vQG+kjSADHTPzHSADHTByHBQfKFAaoC1xgx0SiCCX14QLnjAiiCCW42AKAE0NMHIcFB8oUBqgLXGNEGyMv/Fcs/JddJIKk4AvJFqwIgwUGAcHQL1DdsiAGCEAjw0YC5jsJbbCIyiPgoyPpSz5AAAAAGE8u/yVjIz4TQzMz5FsjPigBAy//PUMjPhQj6UoIQ31hTDs8Ljss/z5LME7N+yYBA+wDgIsjLv89Q1ws/gVZVCIBA9A5voRjy9Ab6SNIAMdM/MdIAMdMHIcFB8oUBghR4BhBZfBjKI+CjI+lLPkAAAAAYSy7/JAcjPhNDMzPkWyM+KAEDL/89QyM+FCPpSghCIVJk7zwuOEss/+lLPhALJgED7AIUAdPKFzwsHFc7MFPQAycjPk/GnFC4Xyz8WzBPLvxL6Ulj6AsnIz4WIE/pSAfoCz4Fz+gJxzwtlzMlw+wAAfqoC1xgx0QLIy7/PUNcLP8jPksZhio4Uyz8Tyz8S+lITzBPLHxL6UsnIz4WIEvpSz4QQc/oCcc8LZczJgED7AAIBICEiAgEgJCUAJwgbpJtcOBvIiBukzFtcOEBgQCOgAacUzGDBvlDMDGBNLwhqTgC8vKrAqsEgS7gIvL0gS7hIoQHu/L0gS7iIYQHu/L0oKWBLuMhhAe78vQgmRA0XwRSAm+BMeFvAHAgk1MDuYroMGxib4GAjANwgriWwIa66jhtTh76egS7kUyG58vRTIW+BAqSXKKRSem+BAuKOI4Eu5CbHALPy9CXXSwGRMJ2BNLwBwAHy9AXXTNAF4gXT/0Fm4lOYvp6BLuRTErny9FMwb4EBpJcppFKLb4EB4lAz8AMTb4wCpABxNAgxwCXMG1tbW1tcOAg10sBkTCbgTS8AcAB8vTXTNDi1PpI+gD0BNP/xwCYXwVtbW1tbXDhgQCPgAB0IG6RbeBvIiBukjFt4QGAAryBTbwBi1MS42LjKMcF8vTQ0x/6SPpQ1PpI1PQE0z/TH/QE0z/RB9D6SPpI1DHUMdQx0QHI+lL6UhPLP8kJyMsfGPpSFvpUF8wS+lLMFPQAEssf9ADLP8mAADyLUxLjcuMIgAgEgKisCASA9PgTpPiRj+fXLCf////08r/U0wcx1wofAdDXLCMmaX6U4wLXLCXSMyI84wLXLCfjTihc4wLXLCWMwxUcji7TP9M/MfpIMdQx0x8x+kgwyM+FCPpSghDfWFMOzwuOyz/PktwwqmrKH8mAQPsA4PI/4CDXLCTqGMgsgLC0uLwGpO2i7fvXLCeQ2+0MjkTXLCfPFPJUlFtw2zHhggDCiiNus/L0IYIAwooExwUT8vQgbQPXCz+LAgHIyz8V+lIS+lLJyM+HIBTOcc8LYRPMyXD7AOMNf4DwA8jHTPzH6ADH6SNM/0z/XC//4ksj6UlJA+lIjzws/ycjPjxgABIIQjcSKPM8L93HPC2HMyXD7AIIITEtAyM+FCBX6UlAE+gKCCZ9M0s8LiiLPCz/PhA7JcfsAyM+PGAAEghBMlMNgzwv3cM8LYcs/yz/L/8+EDslw+wAC/jHUMddM+JLIz48YAASCEECKqW/PC/dwzwth+lLJcPsA+A/Q+kgx1PpI078x9AQx0wEx+gAx0z8x0z8x0QHQ0//TP9M/MdM/0z8x1DHUMfpIMfoAMfQEMdGCCExLQMjPhQgV+lJQBPoCggmfTNLPC4ojzws/z4QOyXH7AMiJzxYwMQHUMdM/1DHTv/pIMPiSyPpSIs8Lv8nIz48YAASCEJwoj+rPC/dxzwthzMlw+wCI+CjI+lLPkAAAAAYTy7/JWMjPhNDMzPkWyM+KAEDL/89QyM+FCPpSghCIVJk7zwuOEss/+lLPhArJgED7AIUENuMC1ywhPe1hnOMC1ywmOerUVOMC1ywixn5YFDIzNDUABcYAAQA2ghBMlMNgzwv3cM8LYcs/Ess/y//PhA7JcPsAAf4x0z8x0//Wv9M/9ATU10z4kviX7UTQJNDHALOBVmQnbrORf5MhwwDi8vRtbW1tbXAmjjdfBiXQINdLAZEwm4E0vAHAAfL010zQ4tM/0wchwUHyhQGqAtcY0z/TP9P/gQCLgVZiAscAEvL03gazgVZaAfAJGb4Y8vQF0x/6SPpQPwP8MdM/0//Wv9M/0z/UbQHUAdCUIMcAs44e1G0B1AHQlCDHALOZ1NTRUANvAgLQ6DDRUANvAgLQ6DDU1wv/+JL4l+1E0NMfMfpIMfpQMdQx+kgx1PQEMdMfMfQEMdM/MdHQ0wf0BPQE0XEqyMs/Ks8UiCqTIG6ziugwzxQozxQnjzY3Av4x7UTQAdM/1NP/0//TAAGf0wABkvoAkm0B4vQEgQCMlG1tWHDiAdMHIcID8kVtAddM0JQgxwCzjh3UbQHUAdCUIMcAs5nU1NFQA28CAtDoMNFYbwIB0OgwCdMf+kj6UNT6SNT0BNMf9ATXCz/4koj4KMj6Us+QAAAAClYSzwv/hTgE4I7UMe1E0AHTP9TTv/oAMATTH/pI+lDU+kjU9ATTH/QE1ws/+JKI+CjI+lLPkAAAAAYtzwu/yYFWVALIz4TQzMz5FsjPigBAy//PUFjHBfL0EJ1VOPAK4NcsI+9Xg7TjAtcsJQA8LnzjAtcsIVvBrPyFOTo7ATQByMwBbyKIkyJus5jIzAJvIgPMyegyAszJAY8BRs8L/8mIEFkQSBA3EDYQJRBPED4QLfAFRlBtUFJtUEJwAvAMjwB+yYFWVALIz4TQzMz5FsjPigBAy//PUFjHBfL0+JIKERMKCRESCQgREQgHERAHEG8QXhBNEDxLoPGADYAVcNs4Abox7UTQAdM/07/6SPoA0x/XTAbTH/pI+lDU+kjU9ATTH/QE1ws/+JKI+CjI+lLPkAAAAAZWEM8Lv8mBVlQCyM+E0MzM+RbIz4oAQMv/z1BYxwXy9PiSChEQClVZ8AuFAKox0z/TP9RtAdQB0JQgxwCzjh7UbQHUAdCUIMcAs5nU1NFQA28CAtDoMNFQA28CAtDoMNTT/9MAAZL6AJJtAeL0BfiXEHgQZxBWEEUQNEEwgQCMAvAMBNbjAtcsIRWnguSOzzHtRNDTHzH6SDD4koIAwogCxwXy9NM/MddM7UTQAdAB1h/6SPpQ1PpI1PQE1h/0BJQqxwCziug6CMjOF/pSFfpUE8z6Usz0AM70AM7J7VTg1ywiZQ3lnOMC1ywhR6CzfENERUYAZmwS0z/6SDCCAMKIUTTHBRPy9IIAwolTI8cFs/L0IYsCyM+HIM5wzwthEss/EvpSyXD7AALfDT4J28QIW6RMZI1BOIDjqmCAN8OAfLyggDfDVEjvBLy9AFw+wKDBojIz4UIE/pScc8LbhLMyQH7AOCCAN8OIcIA8vSCAN8MUxO58vQCggDfDQShIrwT8vSAQIjIz4UIFPpSWPoCcc8LahLMyQH7AII+PADsXLmdccjL/xLL/8v/cfkEA+BxyMv/y//L/3H5BAOAC/tT6SNT0BNMf9ATXCz8t4wBWE26OUFYT0NTU0QHQxwCV0McAwwCSMHDijjlWFFy5jjAxggiYloBWFNDU1NHIz5N6FKxuEszMVhIB+lTJyM+FiFKA+lJY+gJxzwtqzMlx+wCRMOLf3wnIyx8Y+lIW+lQUzBL6UiHPFBL0ABLLHxJAQQH8gVZVU9KAQPQOb6ES8vT6SNIA0z/SANMHIcFB8oUBqgLXGNGBVlUk8vSBVlspVhPwBrPy9IFWXlYUVhGhwUDy9IFWYyFWEscF8vSBVmEDVhC6l1YTVhC+wwCRcOIT8vSBVmVWFPL0VhKkBMj6UhPKABPLP8oAIddJIKk4AvJFQgDi9AASyz/J7VTQ0wf0BPQE0XAtyPQAHczJEDlIcBBqEFwEERAEED9OC/AFyAKOIAHPg8s/IddJIKk4AvJFqwIgwUHyhc8LB84Uyz/LP8v/ljAxbDLPgeL0AMnIz48YAASCECfTvOjPC/dxzwthzMlw+wAC+KsCIMFB8oXPCwfOVCDTgED0SzCCCTEtAIj4KMj6Us+QAAAAClYSzwv/yYj4KPgjVhXIy/8S+lLLPy/PCz9WE88LP3DPC4/JyM+S6RmRHhLMzMnIz4mIAVMjyM+E0MzM+RbPC/9QBPoCz4Fz+gKBAI3PC2sSzMzMyXD7AAGFgwH+Me1E0NMfMfpIMPiSggDCiALHBfL00z8x0//TD9MH0gDU10ztRNDWH/pI+lDU+kjU9ATWH/QE1ws/BNDTB/QE9ATRggDU5FYQwgDy9FRyEFYT8AQxNQSYXwRwIHBtVSDfIpsyggDU5SJWE7ry9JUwMVYQAeIvgwb5QTAxgTS8IUcC/CrXSwGRMJ2BNLwBwAHy9ArXTNAK4grTP/pI0gDTPzHSADHTByHBQfKFAaoC1xhTRYBA9A5voY4eMHF/yM+PGAAEghCYmqU+zwv3cM8LYSfPCz/JcPsA4w0lyPpSJc8KACLPCz8hzwoAJNdJIKk4AvJFqwIgwUHyhc8LByTPFk1OAKIx7UTQ10yBVlz4kgLQ+kj6SDHTPzHREscF8vT0Be1E0NMf+kj6UNT6SNT0BDHTH/QE0z/RCMjLHxf6UhX6VBPM+lLMFPQAE8sfEvQAyz/J7VQENuMC1ywhbnlSHOMC1ywlzAZadOMC1ywizysLhE9QUVID/oEBC6kI8vKBAQupBIIA1OghhAe78vSCANTpIcIA8vRWEo7OMTIv0IMG+UMwMYE0vCGpOALy8qsCqwSCANTzIcIA8vSCANTmIYQHu/L0ggDU51YTpwMiufL0IIIA1OgEvhPy9G1WENBwlCHHALOK6FsCkTDibVYQ0HCUIccAs4pISUoAaiHXSwGRMJ2BNLwBwAHy9AHXTNAB4gHT/4IA1OpTJIMH9A5voTGz8vQCpCDIywdABIMH9EMCAG4h10sBkTCdgTS8AcAB8vQB10zQAeIB+kiCANTrUySBAQv0Cm+hMbPy9AKkIMjLB0AEgQEL9EECAvzoW1YUjh5WFMABjhQ0VhTIy/9WE88LB8sHygD0APQAyZJfBOKOFjVWFMjL/1YTzwsHywfKAPQAEvQAyQHiyM+PGAAEghAG17Ekzwv3cM8LYVYRzwsPARESAcv/HcwbzB3LB8lw+wAsnDI7gVZfUAny9BB5cOMNBsjLBxf0ABpLTAAeDMABmIFWYAqzGvL0kTniADr0AMkDyM4S+lL6VBfMEvpSFcz0ABLO9ADLP8ntVABU+kgx0gAx0z/SANMHIcFB8oUBqgLXGNGBVlkjwAGSMX+WURXHBcMA4vL0AIxUIHmAQPRDBsjLPxX6UhPKABPLPxTKACHXSSCpOALyRasCIMFB8oXPCwfOycjPjxgABIIQcen9MM8L93HPC2HMyXD7AFAKAvwx7UTQAdM/07/6SDAD0x8x+kgx+lAx1DH6SDHUMfQEMdMfMfQFIcjLv89Q1ws/+JKBVlVQI4BA9A5voRPy9AH6SNIAMdM/MdIAMdMHIcFB8oUBqgLXGDHRAYFWXALHBfL0iPgoyPpSz5AAAAAGEsu/ycjPiYgBUxLIz4TQzMyFUwH+Me1E0AHTv/pIMALTHzH6SDH6UDHUMfpIMdQx9AQx0x8x9AUhyMu/z1DXCz/4koFWVVAjgED0Dm+hE/L0AfpI0gAx0z8x0gAx0wchwUHyhQGqAtcYMdEBgVZcAscF8vTtRNDTHzH6SDH6UDHUMfpIMdQx9AQx0x8x9AQx0z8x0VQA9jHtRNAB0z/TP/pI+kgx1wofBNMfMfpIMfpQMdQx+kgx1DH0BDHTHzH0BfiSgVZVUEKAQPQOb6ES8vT6SNIAMdM/MdIAMdMHIcFB8oUBqgLXGDHRAoFWXAPHBRLy9MjPhQj6UoIQ31hTDs8Ljss/z5LcMKpqyh/JgED7AASu4wLXLCC79egc4wLXLCSt4tLk4wLXLCeaH+DcjjIx7UTQ0x8x+kgw+JKCAMKIAscF8vTTP/pI+gDTAAGS+gCSbQHi1woAghEqBfIAVUDwAuDXLCBVQI9sVVZXWAA6+RbPC/+BAIzPC3QSzMzPk8K9xxbLP/pSyYBA+wABioj4KMj6Us+QAAAABhLLv8nIz4kIAVMSyM+E0MzM+RbPC/+BAIzPC3QSzMyLyIVJk7AAAAAAAAAACM8W+lLPhAbJgED7AIUC/jHTPzHU07/6SDD4koj4KMj6Us+QAAAABhTLv8mBVlQEyM+E0MzM+RbIz4oAQMv/z1DHBRLy9AHQ0//TP9M/MdcLP4IITEtAyM+FCBX6UlAE+gKCCZ9M0s8LiiPPCz/PhArJcfsAyM+PGAAEghBMlMNgzwv3cM8LYcs/Ess/y/+FWQL+MdM/MdTTv/pIMPiSiPgoyPpSz5AAAAAGFMu/yYFWVATIz4TQzMz5FsjPigBAy//PUMcFEvL0AdDT/9M/0z8x1ws/gghMS0DIz4UIFfpSUAT6AoIJn0zSzwuKI88LP8+EDslx+wDIz48YAASCEEyUw2DPC/dwzwthyz8Syz/L/4VbAOAx7UTQ0x8x+kgw+JKCAMKIAscF8vTTPzH6SNcLH+1E0NMf+kj6UNT6SDHU9ATTHzH0BNM/0VOYCcjLHxj6Uhb6VBTMFfpSzBP0ABPLH/QAyz/J7VTIz48YAASCEK12qTPPC/dwzwthEvpSyx/JcPsAAfiOXTHtRNDTHzH6SDD4koIAwogCxwXy9NM/MddMk/ED6ACT8QPpACDaASP7BCPQ7R7tU+1EQBPaIe1UIfkAAdoBAsjMy//OycjPjxgABIIQoztJjs8L93HPC2HMyXD7AOAw7UTQ1h/6SPpQ+JJDMCXwAeMCXwSEDwHHAPL0XQEOic8WyXD7AFoAAgIBDonPFslw+wBcAAIDABw0AsjOEvpSEvpUzsntVAIBIGBhAgEgbG0C9yBVloCghAFValgvhLy9O1E0NMfMfpIMfpQMdT6SDHUMfQE0x/0BNM/MdFRLPAGgVZbAbPy9IFWVivQxwCz8vQq0NP/0z/TP9M/0z/U1PpI+gD0BNFWE/AQbBKVgVZp8vDhIW6zlyHQxwCzwwCRcOKXgVZpAW7y9OMNVhWBiYwH3O2i7fs3B9DT/9M/0z/TP9M/1NT6SPoA9ATRyM+PGAAEghBMlMNgzwv3cM8LYSnPCz8nzws/Ks8L/8+EBslw+wCNCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAICrIy/9SQPpSKM8LPyP6AifPCz/JyCLXS4GcAEIFWaQFus/L0Af5QDIBA9A5voYFWVQHy9PpIMdIA0z8x0gAx0wchwUHyhQGqAtcY0YFWVVjy9CzQ+kgx+kgx0z/RyCLXSSCpOALyRasCIMFB8oXPCwcSzsnIjQg0BkdPHHRRFZhwGPNnZolAzVLTyAPbZISrRK+qS2oo76DPFlYXzws/Ess/zPkWZAH+gVZXDdD6SDH6SDHTP9EYuhzy9AaBVlgRFLoBERMB8vRvAI0IAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgB8jL/xb6UhPLP1AI+gIXyz/JyCTXS/JJgwe68okUziHPC/8TzBXMHcwS9AD5FhJvjHAhb4gJ0BQQOWUE/FAI8BFwdPsCiPgoyPpSz5AAAAAKEsv/ycjPkA47ekYWyz8YzBXLHxfL/wOOFALPgyJulGwSz4GVz4NY+gLiFPQAlDA0z4HiiJMibrOOmMjMAm8iiJMibrOYyMwCbyIDzMnoMgPMyegyzMnIz4mIAV3Iz4TQzMz5Fs8L/4EAjYWPj2YAGs8LdBLMEszMyYMG+wAEtPJJgwe68okSzgEREAHL/x/MJM8UI88UUuD0APkWyMv/z1AoyMs/AdcLf88Lf89Q1wu/iPgoyPpSz5AAAAAGIs8Lv8kMlDgVXwXjDm1UcUtUdRiK7eO6dH/tEYVoaWoB7IIImJaAiPgoLcjL/y3PCz8cyz8qzws/Gcs/F8wVzBP6UiH6AlLg9ADJbQjI+lLMUvD6UhLLvxb0AHDPC4XJyM+S6RmRHhTME8zJyM+JiAFTg8jPhNDMzPkWzwv/WPoCz4Fz+gKBAI3PC2sizxQnzxTMyXH7AAKEAIxbgghMS0DIz4UIFfpSUAT6AoIJn0zSzwuKIs8LP8+EDslx+wDIz48YAASCEEyUw2DPC/dwzwthyz/LP8v/z4QOyXD7ANsxAaCK7UHt8QHy/3B0+wLIz5GTNL9KF8s/UAj6AhP6UhbLPxLLPxTL//QAycjPiYgBUyPIz4TQzMz5Fs8L/8+EEHP6AoEAjc8LaxPMzMzJgwb7AGsAnGwhDPAQbBKVgVZp8vDhVGmQUpTwCA8RFw8OERYODREVDQwRFAwLERMLChESCgkREQkIERAIBxEXBwYRFgYFERIFAxERAwIREAIRFwHwDgP3DRsVTU2NjYgbo4UMDFsIoFWZwGUAW7DAJIxf+Ly9G3g8BKVgVZm8vDhEDhHUFRkmVN58AcgbpWBVmfy8OBtB/ATMSBulYFWafLw4IhSEPkAAfkAvZE3kTDiA9D6SDH6SNM/MdGIAcj6Us+QAAAADlJg+lLJAcjPhNDMzII+FbgBHNAgxwCSMG3gINdLAZEwm4E0vAHAAfL010zQ4voAxwCSMG3hgADr5FsjPigBAy//PUMj6UswU+lIB+gIS9ADL//QAyQIBIHFyAgEgm5wCASBzdAIBIHl6AgEgdXYAGbXFECrKlAQQgfd+UJACAW53eABPsFfjQbbGluay5jaGFpbi50b24uY2NpcC5PZmZSYW1wgi1MS43LjCIAA3pd3aiaGmPmP0kGP0oGOoY/SQY6hj6AOmPmPoCwBvpzHaiaGmPmP0kGP0oGOoY/SQY6hj6AOmPmPoCtpDAIHpDN9KZSIDOqQE3gSiJQCB6PjfSmXQYGMCAUh7fAIBIH+AAgFYfX4Afa36dqJoaY+Y/SQY/SgY6hj9JBjqGPoA6Y+Y+gLAqyqswCB6BzfQiXl6fSRpAGmf6QBpg5DgoPlCgNUBa4xowAAVpjvaiaGmPmP0kGEACaULAgG7AgFYgYIAHbK6+1E0NMfMfpIMfpQMIAMWqRaI+QCI+QCI+QCDhIUAZqq27UTQ0x8x+kgx+lAx1DH6SDHUMfQFbSGDBvSGb6UykQGdUgJvAlESgwb0fG+lMugwMQEU/wD0pBP0vPLIC4YBFP8A9KQT9LzyyAulART/APSkE/S88sgLlAIBYoeIAkDQ+JHyQCDXLCAcdvSM4wLXLCAM+maU4wIwhA8BxwDy9ImKAgFIkJEB/jHtRNDT//pI0z/TP9M/03/XCw+BSKn4kifHBfL0B9M/1NMf0//TAAGf0wABkvoAkm0B4vQEgQCKlG1tWHDibQLXTNCUIMcAs44e1G0B1AHQlCDHALOZ1NTRUANvAgLQ6DDRUANvAgLQ6DAG0CDT/zHTPzHTPzHXCz+BSK1THL6LAf4x7UTQ0//6SNM/0z/TP9N/1wsPgUip+JInxwXy9AfTP9cLByDCA/JFgUitUyW+lVMku8MAkXDi8vRTFKGBSK0hwUDy9HMhqgCsJLABqgCtgUisAcMC8vSBSKwhwAKRf5UhwAPDAOLy9IFIrVMlvpVTJLvDAJFw4vL0URShgUitjgH+lVMbu8MAkXDi8vRTC6GBSK0hwUDy9HMhqgCsK7ABqgCtgUirIcADkX+VIcAAwwDi8vQowwCOFvgjLqFQCLyBSKoBkX+VJ8ADwwDi8vSXN4FIqCfy8uKBSK1THL6VUxu7wwCRcOLy9CuhgUitIcFA8vRzIaoArLMasAmqAK4ZsYwD/gjIzsnIz5Mc9WoqGMs/F8wszwv/E8v/BI4VA8+DI26UMwLPgZbPg1AD+gLiEvQAlFsBz4HiyweIkyJus46YyMwCbyKIkyJus5jIzAJvIgPMyegyA8zJ6DLMycjPhYhSYPpScc8LbszJgED7AAXIy/8U+lISyz/LP8s/y3/LD8mPj40ABO1UAZwhwUDy9HMhqgCssxOwAqoAUhCsErEBwAKTBqQG3lMSoaQnuo6TiMjPhYhSYPpScc8LbszJgwb7AN4FyMv/FPpSEss/yz/LP8t/yw/J7VSPAAACASCSkwALuGhYEAuoAFW2K/Gg82NLc1lzG0MLS3Fzo3txcxsbS4FyayuTW2Mqk3t7pBFqYlxsXGMQABm1xRApFRQEEIH3flCQAgFilZYApND4kfJA7UTQ+kgwgSPw+JJYxwXy9NcsJdIzIjyY1NdMAfsE7VTg1ywlh2KKvI4g1NT6ANdMA/sEAe1U+CjIz4UI+lIB+gJxzwtqzMlx+wDg8j8CAUiXmAIBIJmaAAm4aFgFyABTtivxoOtjS3NZcxtDC0txc6N7cXNjSxFyIyuDY3vLCxNjLBFqYlxgXGEQABm1xRAkfhQEEIH3flCQAgEgnZ4CASCfoABdtk29qJoaY+Y/SQY/SgY6n0kahj6AOuFj5FofSQY/SQY6Z/ogeh9JBj9JGmfmOjAAP7f3HaiaGmPmP0kGP0oGOoY/SQY6hj6AOmPmPoA64WfwAgEgoaICAUijpAARsbMghEqBfIAgACOwQftRNDUMddM0NMH9AT0BNGAAI6x49qJoa6ZofSR9JBjpn5jowAA3rcD2omhpj5j9JBj9KBjqGP0kGOoY+gKA+ANZwAIBYqanAgLNqKkCAUjKywIBIKqrAgFIx8gCASCsrQIBIL2+A/c+JHyQCDXLCMmaX6UjmAx7UTQ+kjU+kjTv/QE0wH6ANM/0z/RggCS5PiSKscF8vQJ0z/6APpI0z/TP9P/9AX4lw8REA8Q7xDeEM0QvBCrEJoQifACCMj6UhfMFfpSE8u/9ADLAQH6Ass/yz/J7VTg1ywnhXuOLOMCidcngrq+wAF8J44XWzoDyMwS+lIB+gL0ABbL/8lUNVRUdUPgBsjMFfpSUAP6AvQAy//JAm2BAImAB/jHtRND6SNT6SNO/9ATTAfoA0z/TP9GCAJLk+JIqxwXy9IIAkuAkwAE1UATy9AjTPzH6SDAm0NP/0z/TP9M/0z/6SDAGggCS4wfHBRby9APIy/8Syz/LP8s/yz/JyM+RZ5WFwinPCz/MJM8Lv1JQ+lLJyM+FiFKA+lJxzwtuzMmxAAgKWOZ4AvyOejHtRND6SNT6SNO/9ATTAfoA0z/TP9Ek8AWCAJLmAcMAl4EAiiK6wwCRcOLy9IIAkuT4kiXHBfL0DtM/+kj6UNcLHxEQEREREA8REA8Q7xDeEM0QvBCrEJoQiRA4VULwAwjI+lIXzBX6UhPLv/QAywEB+gLLP8s/ye1U4ImyswA+gwb7AAbI+lIVzBP6Usu/9ADPh4BY+gISyz/LP8ntVAAI4OiC9QP+1yeOdTHtRND6SNT6SNO/9ATTAfoA0z/TP9Ek8AWCAJLnAcMAl4EAiyK6wwCRcOLy9IIAkuT4kiPHBfL0+AAO0z/XTBDvEN4QzRC8EKsQmhCJEHgQZxBWEEUQNBAj8AQIyPpSF8wV+lITy7/0AMsBAfoCyz/LP8ntVOCJ1yfjArS1tgAI7wyzbgH+W+1E0PpI1PpI07/0BNMB+gDTP9M/0STwBYIAkuc7wwCYgQCLIboxwwCSMHDiGfL0ggCS5PiSKccF8vT4AALIzPpS9ADPhsAV+lLJJ9DT/9M/0z/TP9cLPwTIy/8Tyz/LP8s/yz/JyM+QXfr0DiPPCz/MJs8Lv1Jw+lLJyM+FiLcDLInXJ+MC1ywkQqTJ3OMCMIQPAccA8vS4uboAUlKg+lJxzwtuzMmAQPsACMj6UhfMFfpSE8u/FfQAywEB+gLLP8s/ye1UAAjfWFMOAf5b7UTQ+kjU+kjTv/QE0wH6ANM/0z/RggCS5PiSKscF8vQk8AWCAJLnO8MAmIEAiyG6McMAkjBw4hny9ALIzPpS9ADPhsAV+lLJJ9DT/9M/0z/TP9cLPwTIy/8Tyz/LP8s/yz/JyM+QXfr0DiPPCz/MJs8Lv1Jw+lLJyM+FiFKguwH+Me1E0PpI1PpI07/0BNMB+gDTP9M/0YIAkuT4kirHBfL0ggCS4CTAATVQBPL0CNM/MfpI1wsHIMICMfJFJtDT/9M/0z/TP9M/+kgwBoIAkuMHxwUW8vQDyMv/Ess/yz/LP8s/ycjPkF369A4pzws/zCTPC79SUPpSycjPhYhSgLwATvpScc8LbszJgED7AAjI+lIXzBX6UhPLvxX0AMsBAfoCyz/LP8ntVABO+lJxzwtuzMmAQPsABsj6UhXME/pSy7/0AM+GgFj6AhLLP8s/ye1UA9E7aLt+1CpXwYp0NP/0z/TP9M/1ws/JYIJ94pAoCm8jjg4OALIy//LP8s/Fcs/E8s/ycjPkF369A4jzws/zCbPC79ScPpSycjPhYhSoPpScc8LbszJgED7AOApbpVfBTRsIeMOIuMPUDOC/wMEB9xbMzQ0OCBujlAwKdACyMz6Uhb0AM+FwMkF0//TP9M/0z/XCz8EyMv/E8s/yz/LP8s/ycjPkF369A4jzws/zCbPC79ScPpSycjPhYhSoPpScc8LbszJgED7AOBTAsjME/pSUoD0AM+GQBL6UskC0CrQAdT6SPoA9ATXC/+DGAf4J0CvwBQb6SNT6SPoA9ATT//QFVhGCCfeKQKAkoIIJMS0AoAERFQG5jjxfDDcCyMv/yz/LPxTLPxTLP8nIz5Bd+vQOJM8LP8wmzwu/UnD6UsnIz4WIUqD6UnHPC27MyYBA+wAS2zHgPDw8PFcQEFwQSxA6SYAQZxBvEDVEME8OwgCkIsABloIAkuHy8OAiwAKOEBAnXwfAA5aCAJLi8vDg8gXhMvgjcYIJuoFAI6DIz4WIUqD6UgH6AoIQWM/LAs8LiiTPCz8ozxQmzwu/I/oCySH7AABiMvgjcYIJuoFAI6DIz4WIUqD6UgH6AoIQWM/LAs8LiiTPCz8ozxQmzwu/I/oCySH7AAK68AFsVTWBAI0luo9OOYEAiSS6jsKBAI4kuo45MzfIzFJg+lL0AM+FQMnIz4WIFvpSjQaAAAAAAAAAAAAAAAAAAD13phaAAAAAAAAAAEDPFsmAQPsA4w7jDdsx4V8Gw8QB/IEAjCS6jhcQO18LgQCKMrqWggCS4fLw4IIAkuHy8OEzU3HIzBL6UlIw9ADPhkD6UskB0CrQAdT6SPoA9ATXC/8F0//TP9M/MdM/MdM/MdT6SDAlggkxLQCgAcj6UhPLP8wXy/8U+lLJA8jL/xPME8z0ABT0AMnIz5H3q8HaJsUAcjM3yMxSYPpS9ADPhUDJyM+FiBb6Uo0GgAAAAAAAAAAAAAAAAAA9d6YWgAAAAAAAAABAzxbJgED7AABWzws/Ks8Lvxn6UlAD+gLPkAAAAAIXzMnIz4WIUrD6Ulj6AnHPC2rMyXH7AADUBdP/0z/TPzHTPzHTPzHU+kgwJYIJMS0AoAHI+lITyz/MF8v/FPpSyQPIy/8TzBPM9AAZ9ADJyM+R96vB2ibPCz8qzwu/E/pSUAj6As+QAAAAAszJyM+FiFKw+lJQB/oCcc8LahbMyXH7AAHxF8ENjbIzBX6UhP0AM+EQMkm0NP/0z/TP9M/0z/UMddM0McAjjpzBcjL/xTLPxLLP8s/yz/JyM+RZ5WFwiXPCz/MJs8Lv1Jw+lLJyM+FiFKg+lJxzwtuzMmDBvsAUDME4F8FM/gjcYIJuoFAI6DIz4WIUqD6UgH6AoMkAwwgbpcwbW1tbW1w4NDU+kj0BNcsCICUbYEAjY4+1ywJgJRtgQCJjjLXLAqAlG2BAIqOJtcsC4CUbYEAjo4a1ywMgJX6SIEAi53XLA2AkvI/4fpIgQCM4hLi4uLiAtEBgQCPgADqCEFjPywLPC4okzws/KM8UJs8LvyP6Askh+wBQMwIBIMzNAAu4aFgQF4gAX7Yr8aEbY0tzWXMbQwtLcXOje3FzGxtLgXKTKxsrS7MqK8MrG6uje5QRamJcblxhEAAbtcUQQBJcFAQQgfd+UJA='); static Errors = { 'MerkleMultiProof_Error.InvalidProofLeavesCannotBeEmpty': 12000, diff --git a/deployment/go.mod b/deployment/go.mod index 9b34e084e..8723bac22 100644 --- a/deployment/go.mod +++ b/deployment/go.mod @@ -4,6 +4,9 @@ go 1.26.6 replace github.com/smartcontractkit/chainlink-ton => ../ +// TMP: remove in follow up PR +replace github.com/smartcontractkit/chainlink-ton/cciplib => ../cciplib + require ( github.com/Masterminds/semver/v3 v3.5.0 github.com/gagliardetto/binary v0.8.0 diff --git a/deployment/go.sum b/deployment/go.sum index 6bcc01db9..1cd951095 100644 --- a/deployment/go.sum +++ b/deployment/go.sum @@ -692,8 +692,6 @@ github.com/smartcontractkit/chainlink-testing-framework/framework v0.16.6 h1:2cW github.com/smartcontractkit/chainlink-testing-framework/framework v0.16.6/go.mod h1:nyOjn4ADJGqRMe3+4ZXSV+J/7nWb1H2Vx8Qk57eLRYA= github.com/smartcontractkit/chainlink-testing-framework/seth v1.51.5 h1:RwZXxdIAOyjp6cwc9Quxgr38k8r7ACz+Lxh9o/A6oH0= github.com/smartcontractkit/chainlink-testing-framework/seth v1.51.5/go.mod h1:kHYJnZUqiPF7/xN5273prV+srrLJkS77GbBXHLKQpx0= -github.com/smartcontractkit/chainlink-ton/cciplib v0.1.1-0.20260917154632-2b04f920494a h1:TpYTnFTO3JZlhDeyn4R45EFGzeBCaWiEYeOtskzF3aQ= -github.com/smartcontractkit/chainlink-ton/cciplib v0.1.1-0.20260917154632-2b04f920494a/go.mod h1:SOshBOF1ZxrLJlqtcJv9qpg/8soV6fCFqU5xg+imXZI= github.com/smartcontractkit/chainlink-tron/relayer v0.0.11-0.20251014143056-a0c6328c91e9 h1:7Ut0g+Pdm+gcu2J/Xv8OpQOVf7uLGErMX8yhC4b4tIA= github.com/smartcontractkit/chainlink-tron/relayer v0.0.11-0.20251014143056-a0c6328c91e9/go.mod h1:h9hMs6K4hT1+mjYnJD3/SW1o7yC/sKjNi0Qh8hLfiCE= github.com/smartcontractkit/chainlink-tron/relayer/gotron-sdk v0.0.5-0.20250422175525-b7575d96bd4d h1:qLmSOOtB/Ogn79eIDkuujOu8M5Jd747V1H7Brk/nTvo= diff --git a/devenv/go.mod b/devenv/go.mod index d1805dc44..f3e7aba41 100644 --- a/devenv/go.mod +++ b/devenv/go.mod @@ -6,6 +6,9 @@ replace ( github.com/fbsobreira/gotron-sdk => github.com/smartcontractkit/chainlink-tron/relayer/gotron-sdk v0.0.5-0.20250528121202-292529af39df github.com/smartcontractkit/chainlink-ton => ../ + + // TMP: remove in follow up PR + github.com/smartcontractkit/chainlink-ton/cciplib => ../cciplib github.com/smartcontractkit/chainlink-ton/deployment => ../deployment ) diff --git a/devenv/go.sum b/devenv/go.sum index dc99c5aed..d9d8fa288 100644 --- a/devenv/go.sum +++ b/devenv/go.sum @@ -686,8 +686,6 @@ github.com/smartcontractkit/chainlink-testing-framework/framework v0.16.6 h1:2cW github.com/smartcontractkit/chainlink-testing-framework/framework v0.16.6/go.mod h1:nyOjn4ADJGqRMe3+4ZXSV+J/7nWb1H2Vx8Qk57eLRYA= github.com/smartcontractkit/chainlink-testing-framework/seth v1.51.5 h1:RwZXxdIAOyjp6cwc9Quxgr38k8r7ACz+Lxh9o/A6oH0= github.com/smartcontractkit/chainlink-testing-framework/seth v1.51.5/go.mod h1:kHYJnZUqiPF7/xN5273prV+srrLJkS77GbBXHLKQpx0= -github.com/smartcontractkit/chainlink-ton/cciplib v0.1.1-0.20260917154632-2b04f920494a h1:TpYTnFTO3JZlhDeyn4R45EFGzeBCaWiEYeOtskzF3aQ= -github.com/smartcontractkit/chainlink-ton/cciplib v0.1.1-0.20260917154632-2b04f920494a/go.mod h1:SOshBOF1ZxrLJlqtcJv9qpg/8soV6fCFqU5xg+imXZI= github.com/smartcontractkit/chainlink-tron/relayer v0.0.11-0.20251014143056-a0c6328c91e9 h1:7Ut0g+Pdm+gcu2J/Xv8OpQOVf7uLGErMX8yhC4b4tIA= github.com/smartcontractkit/chainlink-tron/relayer v0.0.11-0.20251014143056-a0c6328c91e9/go.mod h1:h9hMs6K4hT1+mjYnJD3/SW1o7yC/sKjNi0Qh8hLfiCE= github.com/smartcontractkit/chainlink-tron/relayer/gotron-sdk v0.0.5-0.20250528121202-292529af39df h1:36e3ROIZyV/qE8SvFOACXtXfMOMd9vG4+zY2v2ScXkI= diff --git a/go.mod b/go.mod index 784ac9262..84687e773 100644 --- a/go.mod +++ b/go.mod @@ -148,6 +148,9 @@ require ( replace github.com/fbsobreira/gotron-sdk => github.com/smartcontractkit/chainlink-tron/relayer/gotron-sdk v0.0.5-0.20250422175525-b7575d96bd4d +// TMP: remove in follow up PR +replace github.com/smartcontractkit/chainlink-ton/cciplib => ./cciplib + tool ( github.com/jmank88/gomods github.com/jmank88/modgraph diff --git a/go.sum b/go.sum index fd23c596d..f9952e628 100644 --- a/go.sum +++ b/go.sum @@ -276,8 +276,6 @@ github.com/smartcontractkit/chainlink-protos/metering/go v0.0.0-20260710151514-2 github.com/smartcontractkit/chainlink-protos/metering/go v0.0.0-20260710151514-27b5a126dabe/go.mod h1:z7lx7wI3XZ4u9kmUtAVdwn1BCC9T8aieWSDcuDgPTdQ= github.com/smartcontractkit/chainlink-protos/node-platform v0.0.0-20260709145319-7782fb89eb16 h1:/vkKPJoweLkRd56V4YHGRAtTG4+/JAlgklGEfvH6l4c= github.com/smartcontractkit/chainlink-protos/node-platform v0.0.0-20260709145319-7782fb89eb16/go.mod h1:dkR2uYg9XYJuT1JASkPzWE51jjFkVb86P7a/yXe5/GM= -github.com/smartcontractkit/chainlink-ton/cciplib v0.1.1-0.20260917154632-2b04f920494a h1:TpYTnFTO3JZlhDeyn4R45EFGzeBCaWiEYeOtskzF3aQ= -github.com/smartcontractkit/chainlink-ton/cciplib v0.1.1-0.20260917154632-2b04f920494a/go.mod h1:SOshBOF1ZxrLJlqtcJv9qpg/8soV6fCFqU5xg+imXZI= github.com/smartcontractkit/freeport v0.1.3-0.20250828155247-add56fa28aad h1:lgHxTHuzJIF3Vj6LSMOnjhqKgRqYW+0MV2SExtCYL1Q= github.com/smartcontractkit/freeport v0.1.3-0.20250828155247-add56fa28aad/go.mod h1:T4zH9R8R8lVWKfU7tUvYz2o2jMv1OpGCdpY2j2QZXzU= github.com/smartcontractkit/grpc-proxy v0.0.0-20240830132753-a7e17fec5ab7 h1:12ijqMM9tvYVEm+nR826WsrNi6zCKpwBhuApq127wHs= From 6ada85cc59f3204f7f06f8c04e1d387e608e98d7 Mon Sep 17 00:00:00 2001 From: "app-token-issuer-integrations[bot]" <204793122+app-token-issuer-integrations[bot]@users.noreply.github.com> Date: Tue, 22 Sep 2026 19:32:07 +0000 Subject: [PATCH 23/23] chore(nix): update lock.nix hashes --- cmd/chainlink-ton-extras/lock.nix | 2 +- cmd/chainlink-ton/lock.nix | 2 +- scripts/oplint/lock.nix | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/cmd/chainlink-ton-extras/lock.nix b/cmd/chainlink-ton-extras/lock.nix index ac6444869..c413761db 100644 --- a/cmd/chainlink-ton-extras/lock.nix +++ b/cmd/chainlink-ton-extras/lock.nix @@ -1,5 +1,5 @@ # Notice: `pkgs.lib.fakeHash` can be used as a placeholder, # but `lock-nix-tidy` will only replace actual hashes. {pkgs}: { - chainlink-ton-extras = "sha256-lHYNeIUSxyJyHgoJcd/VjwLOynH2AP5Fp8nK4YpKhhU="; + chainlink-ton-extras = "sha256-CvAHD2AeJq51erMWhXj+u2FHFBIyREuGX7LjGbQagXk="; } diff --git a/cmd/chainlink-ton/lock.nix b/cmd/chainlink-ton/lock.nix index ee7495eb3..3bb66eba0 100644 --- a/cmd/chainlink-ton/lock.nix +++ b/cmd/chainlink-ton/lock.nix @@ -1,5 +1,5 @@ # Notice: `pkgs.lib.fakeHash` can be used as a placeholder, # but `lock-nix-tidy` will only replace actual hashes. {pkgs}: { - chainlink-ton = "sha256-lHYNeIUSxyJyHgoJcd/VjwLOynH2AP5Fp8nK4YpKhhU="; + chainlink-ton = "sha256-CvAHD2AeJq51erMWhXj+u2FHFBIyREuGX7LjGbQagXk="; } diff --git a/scripts/oplint/lock.nix b/scripts/oplint/lock.nix index 0047cead7..d6250aec4 100644 --- a/scripts/oplint/lock.nix +++ b/scripts/oplint/lock.nix @@ -1,3 +1,3 @@ {pkgs}: { - oplint = "sha256-lHYNeIUSxyJyHgoJcd/VjwLOynH2AP5Fp8nK4YpKhhU="; + oplint = "sha256-CvAHD2AeJq51erMWhXj+u2FHFBIyREuGX7LjGbQagXk="; }