From bc1ea95db16a52774ed84b443a918f8925e9a88f Mon Sep 17 00:00:00 2001 From: vicente Date: Mon, 1 Jun 2026 18:07:48 -0300 Subject: [PATCH 01/14] add tokenRegistry to storages --- .../ccip/ccipsend_executor/types.tolk | 2 ++ contracts/contracts/ccip/onramp/contract.tolk | 14 ++++++++++ contracts/contracts/ccip/router/contract.tolk | 26 +++++++++++++++++++ contracts/contracts/ccip/router/errors.tolk | 1 + contracts/contracts/ccip/router/messages.tolk | 1 + 5 files changed, 44 insertions(+) diff --git a/contracts/contracts/ccip/ccipsend_executor/types.tolk b/contracts/contracts/ccip/ccipsend_executor/types.tolk index be18d795b..d57158374 100644 --- a/contracts/contracts/ccip/ccipsend_executor/types.tolk +++ b/contracts/contracts/ccip/ccipsend_executor/types.tolk @@ -21,6 +21,7 @@ struct CCIPSendExecutor_Data { struct CCIPSendExecutor_Addresses { onramp: address, feeQuoter: address, + tokenRegistry: address, } type CCIPSendExecutor_State = @@ -39,6 +40,7 @@ struct CCIPSendExecutor_State_Finalized { struct CCIPSendExecutor_Config { feeQuoter: address, + tokenRegistry: address, } diff --git a/contracts/contracts/ccip/onramp/contract.tolk b/contracts/contracts/ccip/onramp/contract.tolk index 8f96aff7e..b3a9c6242 100644 --- a/contracts/contracts/ccip/onramp/contract.tolk +++ b/contracts/contracts/ccip/onramp/contract.tolk @@ -240,6 +240,14 @@ fun onSend(st: OnRamp_Storage, destChainConfig: OnRamp_DestChainConfig, payload: val config = st.config.load(); + var tokenRegistry: address? = null; + + val msg = payload.msg.load(); + var tokenAmounts = msg.tokenAmounts.iter(); + if (!tokenAmounts.empty()) { + tokenRegistry = calculateTokenRegistryAddress(st, tokenAmounts.next().token); + } + val executorId = generateRandomSendExecutorId(); val executeMsg = createMessage({ bounce: true, @@ -259,6 +267,7 @@ fun onSend(st: OnRamp_Storage, destChainConfig: OnRamp_DestChainConfig, payload: onrampSend: payload, config: CCIPSendExecutor_Config { feeQuoter: config.feeQuoter, + tokenRegistry, }.toCell(), }.toCell(), }, @@ -270,6 +279,11 @@ fun onSend(st: OnRamp_Storage, destChainConfig: OnRamp_DestChainConfig, payload: st.store(); } +fun calculateTokenRegistryAddress(st: OnRamp_Storage, token: address): address { + // TODO: calculate token registry address + return createAddressNone() +} + /* Handles successful completion of a CCIPSendExecutor. Assigns a new sequence number and notifies the Router of the successful send. diff --git a/contracts/contracts/ccip/router/contract.tolk b/contracts/contracts/ccip/router/contract.tolk index abd40bd99..2f672c8c0 100644 --- a/contracts/contracts/ccip/router/contract.tolk +++ b/contracts/contracts/ccip/router/contract.tolk @@ -139,6 +139,29 @@ fun onInternalMessage(in: InMessage) { onSendNACK(msg) } + // Sender must be a Jetton Wallet owned by the Router + Common_JettonTransferNotification => { + //TODO: Validate sender is owned jetton transfer + + // TODO: catch errors, if different message type than CCIPSend + val sendMsg = Router_CCIPSend.fromCell(transferNotification.forwardPayload!); + + var tokenAmounts = sendMsg.tokenAmounts.iter(); + assert (!tokenAmounts.empty()) throw Router_Error.MissingTokenAmounts; + + val transferedJetton = tokenAmounts.next(); + assert (transferedJetton.amount == transferNotification.amount) throw 5; // TODO: if transfered token is link, extract fee before this check + assert (tokenAmounts.empty()) throw Router_Error.NoMultiTokenTransfers; + + val onRamp = st.onRamps.mustGet(sendMsg.destChainSelector, Router_Error.DestChainNotEnabled as int); + val onRampSend = createMessage({ + bounce: true, + value: 0, + dest: onRamp, + body: OnRamp_Send { msg: sendMsg.toCell(), metadata: Metadata{ sender: transferNotification.sender, value: transferNotification.amount } }, + }); + onRampSend.send(SEND_MODE_CARRY_ALL_REMAINING_MESSAGE_VALUE); + } else => { // attempt to handle Ownable messages var st = lazy Storage.load(); @@ -466,6 +489,9 @@ fun onCCIPSend(msg: Router_CCIPSend, sender: address, value: coins) { msg.feeToken = st.wrappedNative } + // Token transfer messages can only come in through jetton transfer notifications + assert(msg.tokenAmounts.empty()) throw Router_Error.TokenTransferNotThroughNotification; //TBD shuold this be sendMessageRejected instead of throw? + val onRampResult = st.onRamps.get(msg.destChainSelector); if (!onRampResult.isFound) { return sendMessageRejected(sender, msg.queryID, Router_Error.DestChainNotEnabled as uint256); diff --git a/contracts/contracts/ccip/router/errors.tolk b/contracts/contracts/ccip/router/errors.tolk index a8e1d2192..0f95b0e4c 100644 --- a/contracts/contracts/ccip/router/errors.tolk +++ b/contracts/contracts/ccip/router/errors.tolk @@ -12,4 +12,5 @@ enum Router_Error { MissingTokenAmounts NoMultiTokenTransfers InsufficientFee + TokenTransferNotThroughNotification } diff --git a/contracts/contracts/ccip/router/messages.tolk b/contracts/contracts/ccip/router/messages.tolk index c1ce77bb6..aee4d9666 100644 --- a/contracts/contracts/ccip/router/messages.tolk +++ b/contracts/contracts/ccip/router/messages.tolk @@ -26,6 +26,7 @@ type Router_InMsg = | Router_MessageSent | Router_MessageRejected | Router_RMNOwnableMessage + | Common_JettonTransferNotification ; type Router_BouncedMessage = From 2edcda962df960fb4c6b45ad9addb2854e0b82c5 Mon Sep 17 00:00:00 2001 From: vicente Date: Mon, 8 Jun 2026 11:04:58 -0300 Subject: [PATCH 02/14] complete messaging skeleton, build failing --- .../ccip/ccipsend_executor/contract.tolk | 76 ++++++++++++++++++- .../ccip/ccipsend_executor/errors.tolk | 1 + .../ccip/ccipsend_executor/messages.tolk | 5 +- .../ccip/ccipsend_executor/types.tolk | 14 ++++ contracts/contracts/ccip/onramp/contract.tolk | 22 ++++++ contracts/contracts/ccip/onramp/messages.tolk | 8 +- contracts/contracts/ccip/onramp/types.tolk | 2 +- contracts/contracts/ccip/router/contract.tolk | 19 +++++ contracts/contracts/ccip/router/messages.tolk | 8 ++ .../ccip/test/tokenPool/contract.tolk | 17 +++++ .../ccip/token_registry/contract.tolk | 28 +++++++ .../ccip/token_registry/messages.tolk | 13 ++++ .../ccip/token_registry/storage.tolk | 13 ++++ .../contracts/ccip/token_registry/types.tolk | 5 ++ .../ccip.test.mockTokenPool.compile.ts | 10 +++ 15 files changed, 236 insertions(+), 5 deletions(-) create mode 100644 contracts/contracts/ccip/test/tokenPool/contract.tolk create mode 100644 contracts/contracts/ccip/token_registry/contract.tolk create mode 100644 contracts/contracts/ccip/token_registry/messages.tolk create mode 100644 contracts/contracts/ccip/token_registry/storage.tolk create mode 100644 contracts/contracts/ccip/token_registry/types.tolk create mode 100644 contracts/wrappers/ccip.test.mockTokenPool.compile.ts diff --git a/contracts/contracts/ccip/ccipsend_executor/contract.tolk b/contracts/contracts/ccip/ccipsend_executor/contract.tolk index 8b6cdec0a..42498cd3b 100644 --- a/contracts/contracts/ccip/ccipsend_executor/contract.tolk +++ b/contracts/contracts/ccip/ccipsend_executor/contract.tolk @@ -10,6 +10,7 @@ import "../onramp/errors" import "../router/messages" import "../fee_quoter/types" import "@stdlib/gas-payments" +import "../common/types" const CONTRACT_VERSION = "1.6.0"; @@ -35,6 +36,17 @@ fun onInternalMessage(in: InMessage) { assert(this.addresses.load().feeQuoter == in.senderAddress, CCIPSendExecutor_Error.Unauthorized); this.onMessageValidationFailed(msg); } + // Sender must be TokenRegistry + TokenRegistry_ReturnTokenInfo => { + var this = CCIPSendExecutor.load(); + assert(this.addresses.load().tokenRegistry == in.senderAddress, CCIPSendExecutor_Error.Unauthorized); + this.onTokenInfoReceived(msg); + } + MockTokenPool_NotifySuccessfulLockOrBurn => { + var this = CCIPSendExecutor.load(); + assert(this.state.load().tokenPool == in.senderAddress, CCIPSendExecutor_Error.Unauthorized); + this.onConfirmLockOrBurn(msg); + } else => { assert (in.body.isEmpty()) throw 0xFFFF; }, @@ -59,6 +71,7 @@ fun init(onrampSend: OnRamp_Send, config: CCIPSendExecutor_Config): CCIPSendExec addresses: CCIPSendExecutor_Addresses { onramp: st.onramp, feeQuoter: config.feeQuoter, + tokenRegistry: config.tokenRegistry }.toCell(), state: CCIPSendExecutor_State_Initialized{ }.toCell(), @@ -91,13 +104,72 @@ fun getValidatedFee(feeQuoter: address, onrampSend: OnRamp_Send) { } fun CCIPSendExecutor.onMessageValidated(mutate self, msg: FeeQuoter_MessageValidated) { + val message = Router_CCIPSend.FromCell(self.onrampSend.msg); + val tokenAmounts = message.tokenAmounts; if (msg.fee.feeTokenAmount + Router_Costs.CCIPSend() > self.onrampSend.metadata.value) { self.exitWithError(CCIPSendExecutor_Error.InsufficientFunds as int); return; } + // If token amounts is empty finalize the message + if (tokenAmounts.empty()) { + setGasLimitToMaximum(); + self.exitSuccessfully(msg.fee); + } + + // Else if there are token transfers continue querying the tokenRegistry + val tokenRegistry = self.state.load().tokenRegistry; + val queryMsg = createMessage({ + bounce: true, + value: 0, + dest: tokenRegistry, + body: TokenRegistry_GetTokenInfo { + } + }); + queryMsg.send(SEND_MODE_CARRY_ALL_REMAINING_MESSAGE_VALUE); + val newState = CCIPSendExecutor { + id: self.id, + messageId: self.messageId, + onrampSend: self.onrampSend, + addresses: self.addresses, + state: CCIPSendExecutor_State_TokenRegistryAccess { + fee: msg.fee, + }.toCell(), + }; + newState.store(); +} + +fun CCIPSendExecutor.onTokenInfoReceived(mutate self, msg: TokenRegistry_ReturnTokenInfo) { + //TODO validate sender wallet address by querying the jettonMinter + assert(msg.tokenInfo.enabled) throw CCIPSendExecutor_Error.TokenNotEnabled; + val onrampSend = self.onrampSend.msg.load(); + val tokenAmount = onrampSend.tokenAmounts.iter().next(); + val requestLockOrBurn = createMessage({ + bounce: true, + value: 0, + dest: self.state.load().addresses.onramp, + body: OnRamp_ExecutorRequestsLockOrBurn { + tokenAmount, + tokenPool: msg.info.tokenPool, + destChainSelector: onrampSend.destChainSelector, + } + }); + requestLockOrBurn.send(SEND_MODE_CARRY_ALL_REMAINING_MESSAGE_VALUE); + val newState = CCIPSendExecutor { + id: self.id, + messageId: self.messageId, + onrampSend: self.onrampSend, + addresses: self.addresses, + state: CCIPSendExecutor_State_TokenTransfer { + tokenPool: msg.info.tokenPool, + fee: self.state.load().fee, + }.toCell(), + }; + newState.store(); +} + +fun CCIPSendExecutor.onConfirmLockOrBurn(mutate self, msg: MockTokenPool_NotifySuccessfulLockOrBurn) { setGasLimitToMaximum(); - - self.exitSuccessfully(msg.fee); + self.exitSuccessfully(self.state.load().fee); } fun CCIPSendExecutor.exitSuccessfully(self, fee: Fee) { diff --git a/contracts/contracts/ccip/ccipsend_executor/errors.tolk b/contracts/contracts/ccip/ccipsend_executor/errors.tolk index d6a7b9fc1..bf0e3dd02 100644 --- a/contracts/contracts/ccip/ccipsend_executor/errors.tolk +++ b/contracts/contracts/ccip/ccipsend_executor/errors.tolk @@ -7,4 +7,5 @@ enum CCIPSendExecutor_Error { InsufficientFunds InsufficientFee FeeQuoterBounce + TokenNotEnabled } diff --git a/contracts/contracts/ccip/ccipsend_executor/messages.tolk b/contracts/contracts/ccip/ccipsend_executor/messages.tolk index 6487abb3f..b6aa84473 100644 --- a/contracts/contracts/ccip/ccipsend_executor/messages.tolk +++ b/contracts/contracts/ccip/ccipsend_executor/messages.tolk @@ -6,11 +6,14 @@ import "../../lib/versioning/upgradeable" import "../onramp/messages" import "../router/messages" import "../fee_quoter/messages" +import "../token_registry/messages" +import "../common/types" type CCIPSendExecutor_InMessage = | CCIPSendExecutor_Execute | FeeQuoter_MessageValidated | FeeQuoter_MessageValidationFailed + | TokenRegistry_ReturnTokenInfo ; // crc32('CCIPSendExecutor_Execute') @@ -58,4 +61,4 @@ fun SendExecutor_Costs.MessageValidationFailed(): int { type CCIPSendExecutor_BouncedMessage = | FeeQuoter_GetValidatedFee - ; \ No newline at end of file + ; diff --git a/contracts/contracts/ccip/ccipsend_executor/types.tolk b/contracts/contracts/ccip/ccipsend_executor/types.tolk index d57158374..96e7a3886 100644 --- a/contracts/contracts/ccip/ccipsend_executor/types.tolk +++ b/contracts/contracts/ccip/ccipsend_executor/types.tolk @@ -1,5 +1,6 @@ // SPDX-License-Identifier: BUSL-1.1 import "../onramp/messages.tolk"; +import "../fee_quoter/types" const CCIPSendExecutor_FACILITY_NAME = "link.chain.ton.ccip.CCIPSendExecutor"; const CCIPSendExecutor_FACILITY_ID = 178; // (crc32() % 640) + 10 @@ -35,6 +36,19 @@ struct CCIPSendExecutor_State_Initialized { struct CCIPSendExecutor_State_OnGoingFeeValidation { } +struct CCIPSendExecutor_State_TokenRegistryAccess { + fee: Fee, +} + +//TODO Impl wallet address validation through JettonMinter/ stored wallet code +struct CCIPSendExecutor_State_WalletAddressValidation { +} + +struct CCIPSendExecutor_State_TokenTransfer { + tokenPool: address, + fee: Fee, +} + struct CCIPSendExecutor_State_Finalized { } diff --git a/contracts/contracts/ccip/onramp/contract.tolk b/contracts/contracts/ccip/onramp/contract.tolk index b3a9c6242..9d22236e1 100644 --- a/contracts/contracts/ccip/onramp/contract.tolk +++ b/contracts/contracts/ccip/onramp/contract.tolk @@ -60,6 +60,12 @@ fun onInternalMessage(in: InMessage) { assert(destChainConfig.router == in.senderAddress, Error.Unauthorized); onSend(st, destChainConfig, msg) } + OnRamp_ExecutorRequestsLockOrBurn => { + // Sender must be Send Executor + var st = lazy OnRamp_Storage.load(); + assert(st.executor.autoDeployAddress(msg.executorID).addressMatches(in.senderAddress), Error.Unauthorized); + onExecutorRequestsLockOrBurn(st, msg, in.senderAddress); + } // Sender must be Send Executor OnRamp_ExecutorFinishedSuccessfully => { var st = lazy OnRamp_Storage.load(); @@ -284,6 +290,22 @@ fun calculateTokenRegistryAddress(st: OnRamp_Storage, token: address): address { return createAddressNone() } +fun onExecutorRequestsLockOrBurn(st: OnRamp_Storage, msg: OnRamp_ExecutorRequestsLockOrBurn, sender: address) { + var destChainConfig = st.destChainConfigs.mustGet(msg.destChainSelector, Error.UnknownDestChainSelector as int); + routerLockOrBurn = createMessage({ + bounce: true, + value: 0, + dest: destChainConfig.router, + body: Router_LockOrBurn { + tokenPool: msg.tokenPool, + tokenAmount: msg.tokenAmount, + destChainSelector: msg.destChainSelector, + executorAddress: sender, + } + }); + routerLockOrBurn.send(SEND_MODE_CARRY_ALL_REMAINING_MESSAGE_VALUE); +} + /* Handles successful completion of a CCIPSendExecutor. Assigns a new sequence number and notifies the Router of the successful send. diff --git a/contracts/contracts/ccip/onramp/messages.tolk b/contracts/contracts/ccip/onramp/messages.tolk index 89b761e7e..2bd43d27d 100644 --- a/contracts/contracts/ccip/onramp/messages.tolk +++ b/contracts/contracts/ccip/onramp/messages.tolk @@ -39,6 +39,12 @@ struct (0x9c2ccc7e) OnRamp_GetValidatedFee { context: T; } +struct (0x12312312) OnRamp_ExecutorRequestsLockOrBurn { + tokenAmount: TokenAmount, + tokenPool: address, + destChainSelector: uint64, +} + struct OnRamp_GetValidatedFeeContext { onrampContext: address; // router address userContext: RemainingBitsOrRef, @@ -169,4 +175,4 @@ fun OnRamp_Costs.WithdrawFeeTokens(): int { + ton("0.019") // feeTokens fwdFee + ton("0.05") // feeCollector computeFee ; -} \ No newline at end of file +} diff --git a/contracts/contracts/ccip/onramp/types.tolk b/contracts/contracts/ccip/onramp/types.tolk index b11c9f012..fdddddc0e 100644 --- a/contracts/contracts/ccip/onramp/types.tolk +++ b/contracts/contracts/ccip/onramp/types.tolk @@ -70,7 +70,7 @@ struct TVM2AnyRampMessageBody { receiver: Cell; data: cell; extraArgs: cell; - tokenAmounts: cell; + tokenAmounts: SnakedCell; feeToken: address; feeTokenAmount: uint256; } diff --git a/contracts/contracts/ccip/router/contract.tolk b/contracts/contracts/ccip/router/contract.tolk index 2f672c8c0..da9537db6 100644 --- a/contracts/contracts/ccip/router/contract.tolk +++ b/contracts/contracts/ccip/router/contract.tolk @@ -139,6 +139,11 @@ fun onInternalMessage(in: InMessage) { onSendNACK(msg) } + Router_LockOrBurn => { + val st = lazy Storage.load(); + assertSenderIsOnRamp(st, msg.destChainSelector, in.senderAddress); + onLockOrBurn(msg); + } // Sender must be a Jetton Wallet owned by the Router Common_JettonTransferNotification => { //TODO: Validate sender is owned jetton transfer @@ -629,6 +634,20 @@ fun sendMessageRejected(sender: address, queryID: uint64, error: uint256) { nackMsg.send(SEND_MODE_CARRY_ALL_REMAINING_MESSAGE_VALUE); } +//TODO Should be a jetton transfer to the TokenPool wallet, and the LockOrBurn message should go in the forwardPayload of that jetton transfer +fun onLockOrBurn(msg: Router_LockOrBurn) { + tokenPoolLockOrBurn = createMessage({ + bounce: true, + value: 0, + dest: msg.tokenPool, + body: MockTokenPool_LockOrBurn { + tokenAmount: msg.tokenAmount, + notify: msg.executorAddress, + } + }); + tokenPoolLockOrBurn.send(SEND_MODE_CARRY_ALL_REMAINING_MESSAGE_VALUE); +} + /* Handles contract upgrade requests using the Upgradeable pattern. Invokes the upgrade process with the current migrate function and version metadata. diff --git a/contracts/contracts/ccip/router/messages.tolk b/contracts/contracts/ccip/router/messages.tolk index aee4d9666..2d5b8f56e 100644 --- a/contracts/contracts/ccip/router/messages.tolk +++ b/contracts/contracts/ccip/router/messages.tolk @@ -25,6 +25,7 @@ type Router_InMsg = | Router_RMNRemoteVerifyNotCursed | Router_MessageSent | Router_MessageRejected + | Router_LockOrBurn | Router_RMNOwnableMessage | Common_JettonTransferNotification ; @@ -119,6 +120,13 @@ struct (0x4dd6aa82) Router_GetValidatedFee { context: T; } +struct (0x45645645) Router_LockOrBurn { + tokenPool: address, + tokenAmount: TokenAmount, + destChainSelector: uint64, + executorAddress: address, +} + struct Router_GetValidatedFeeContext { routerContext: address; // sender userContext: RemainingBitsOrRef, diff --git a/contracts/contracts/ccip/test/tokenPool/contract.tolk b/contracts/contracts/ccip/test/tokenPool/contract.tolk new file mode 100644 index 000000000..1b079e274 --- /dev/null +++ b/contracts/contracts/ccip/test/tokenPool/contract.tolk @@ -0,0 +1,17 @@ +struct (0x98769876) MockTokenPool_LockOrBurn { + tokenAmount: TokenAmount, + notify: address, +} + +struct (0x87658765) MockTokenPool_NotifySuccessfulLockOrBurn {} + +fun onInternalMessage(in: InMessage) { + val msg = lazy MockTokenPool_LockOrBurn.fromSlice(in.body); + notification = createMessage({ + bounce: false, + value: 0, + dest: msg.notify, + body: MockTokenPool_NotifySuccessfulLockOrBurn {}, + }); + notification.send(SEND_MODE_CARRY_ALL_BALANCE); +} diff --git a/contracts/contracts/ccip/token_registry/contract.tolk b/contracts/contracts/ccip/token_registry/contract.tolk new file mode 100644 index 000000000..750250b6d --- /dev/null +++ b/contracts/contracts/ccip/token_registry/contract.tolk @@ -0,0 +1,28 @@ +import "messages" +import "storage" + +fun onInternalMessage(in: InMessage) { + val msg = lazy TokenRegistry_InMessage.fromSlice(in.body); + + match (msg) { + TokenRegistry_GetTokenInfo => { + onGetTokenInfo(msg, in.senderAddress); + } + else => { + assert (in.body.isEmpty()) throw 0xFFFF; + } + } +} + +fun onGetTokenInfo(msg: TokenRegistry_GetTokenInfo, sender: address) { + val st = TokenRegistry_Storage.load(); + val response = createMessage({ + dest: sender, + value: 0, + bounce: false, + body: TokenRegistry_TokenPoolInfo { + tokenInfo: st.info, + } + }); + response.send(SEND_MODE_CARRY_ALL_REMAINING_MESSAGE_VALUE); +} diff --git a/contracts/contracts/ccip/token_registry/messages.tolk b/contracts/contracts/ccip/token_registry/messages.tolk new file mode 100644 index 000000000..a6b4c0862 --- /dev/null +++ b/contracts/contracts/ccip/token_registry/messages.tolk @@ -0,0 +1,13 @@ +import "types" + +type TokenRegistry_InMessage = + | TokenRegistry_GetTokenInfo; + +// crc32('TokenRegistry_GetTokenInfo') +struct (0xDD5D5127) TokenRegistry_GetTokenInfo { +} + +// Outgoing messages +struct (0xB8F88A81) TokenRegistry_ReturnTokenInfo { + tokenInfo: TokenRegistry_TokenInfo, +} diff --git a/contracts/contracts/ccip/token_registry/storage.tolk b/contracts/contracts/ccip/token_registry/storage.tolk new file mode 100644 index 000000000..8dc569970 --- /dev/null +++ b/contracts/contracts/ccip/token_registry/storage.tolk @@ -0,0 +1,13 @@ +struct TokenRegistry_Storage { + info: TokenRegistry_TokenInfo +} + +fun TokenRegistry_Storage.load(): TokenRegistry_Storage { + return TokenRegistry_Storage.fromCell(contract.getData()); +} + +fun TokenRegistry_Storage.store(self) { + contract.setData(TokenRegistry_Storage{ + info: self.info, + }.toCell()); +} diff --git a/contracts/contracts/ccip/token_registry/types.tolk b/contracts/contracts/ccip/token_registry/types.tolk new file mode 100644 index 000000000..8ebddf3ca --- /dev/null +++ b/contracts/contracts/ccip/token_registry/types.tolk @@ -0,0 +1,5 @@ +struct TokenRegistry_TokenInfo { + tokenPool: address + minterAddress: address + enabled: bool +} diff --git a/contracts/wrappers/ccip.test.mockTokenPool.compile.ts b/contracts/wrappers/ccip.test.mockTokenPool.compile.ts new file mode 100644 index 000000000..872f6058a --- /dev/null +++ b/contracts/wrappers/ccip.test.mockTokenPool.compile.ts @@ -0,0 +1,10 @@ +import { CompilerConfig } from '@ton/blueprint' + +// NOTE: Receiver contract moved from examples/ to ccip/test/ so it gets included +// in published release artifacts (examples.* contracts are excluded from releases). +// See: .github/workflows/contracts-publish-compiled-artifacts.yml +export const compile: CompilerConfig = { + lang: 'tolk', + entrypoint: 'contracts/ccip/test/tokenPool/contract.tolk', + withStackComments: true, +} From bd48c104a46a791b0aef0526437a5478ac454a89 Mon Sep 17 00:00:00 2001 From: vicente Date: Mon, 8 Jun 2026 11:22:38 -0300 Subject: [PATCH 03/14] get sendExecutor to build --- .../contracts/ccip/ccipsend_executor/contract.tolk | 14 +++++++------- .../contracts/ccip/ccipsend_executor/messages.tolk | 2 ++ .../contracts/ccip/ccipsend_executor/types.tolk | 2 ++ contracts/contracts/ccip/onramp/messages.tolk | 1 + contracts/contracts/ccip/router/messages.tolk | 1 + .../contracts/ccip/test/tokenPool/contract.tolk | 12 +++++++----- 6 files changed, 20 insertions(+), 12 deletions(-) diff --git a/contracts/contracts/ccip/ccipsend_executor/contract.tolk b/contracts/contracts/ccip/ccipsend_executor/contract.tolk index 65278f4ad..655c73ead 100644 --- a/contracts/contracts/ccip/ccipsend_executor/contract.tolk +++ b/contracts/contracts/ccip/ccipsend_executor/contract.tolk @@ -10,6 +10,8 @@ import "../router/messages" import "../fee_quoter/types" import "@stdlib/gas-payments" import "../common/types" +import "../token_registry/messages" +import "../test/tokenPool/messages" tolk 1.4.1 @@ -115,7 +117,7 @@ fun getValidatedFee(feeQuoter: address, onrampSend: OnRamp_Send) { } fun CCIPSendExecutor.onMessageValidated(mutate self, msg: FeeQuoter_MessageValidated) { - val message = Router_CCIPSend.FromCell(self.onrampSend.msg); + val message = Router_CCIPSend.fromCell(self.onrampSend.msg); val tokenAmounts = message.tokenAmounts; if (msg.fee.feeTokenAmount + Router_Costs.CCIPSend() > self.onrampSend.metadata.value) { self.exitWithError(CCIPSendExecutor_Error.InsufficientFunds); @@ -128,7 +130,7 @@ fun CCIPSendExecutor.onMessageValid } // Else if there are token transfers continue querying the tokenRegistry - val tokenRegistry = self.state.load().tokenRegistry; + val tokenRegistry = self.addresses.load().tokenRegistry; val queryMsg = createMessage({ bounce: true, value: 0, @@ -139,7 +141,6 @@ fun CCIPSendExecutor.onMessageValid queryMsg.send(SEND_MODE_CARRY_ALL_REMAINING_MESSAGE_VALUE); val newState = CCIPSendExecutor { id: self.id, - messageId: self.messageId, onrampSend: self.onrampSend, addresses: self.addresses, state: CCIPSendExecutor_State_TokenRegistryAccess { @@ -157,21 +158,20 @@ fun CCIPSendExecutor.onTokenInfoRece val requestLockOrBurn = createMessage({ bounce: true, value: 0, - dest: self.state.load().addresses.onramp, + dest: self.addresses.load().onramp, body: OnRamp_ExecutorRequestsLockOrBurn { tokenAmount, - tokenPool: msg.info.tokenPool, + tokenPool: msg.tokenInfo.tokenPool, destChainSelector: onrampSend.destChainSelector, } }); requestLockOrBurn.send(SEND_MODE_CARRY_ALL_REMAINING_MESSAGE_VALUE); val newState = CCIPSendExecutor { id: self.id, - messageId: self.messageId, onrampSend: self.onrampSend, addresses: self.addresses, state: CCIPSendExecutor_State_TokenTransfer { - tokenPool: msg.info.tokenPool, + tokenPool: msg.tokenInfo.tokenPool, fee: self.state.load().fee, }.toCell(), }; diff --git a/contracts/contracts/ccip/ccipsend_executor/messages.tolk b/contracts/contracts/ccip/ccipsend_executor/messages.tolk index 13f3045ee..8fb43ba36 100644 --- a/contracts/contracts/ccip/ccipsend_executor/messages.tolk +++ b/contracts/contracts/ccip/ccipsend_executor/messages.tolk @@ -5,12 +5,14 @@ import "../onramp/messages" import "../fee_quoter/messages" import "../token_registry/messages" import "../common/types" +import "../test/tokenPool/messages" type CCIPSendExecutor_InMessage = | CCIPSendExecutor_Execute | FeeQuoter_MessageValidated | FeeQuoter_MessageValidationFailed | TokenRegistry_ReturnTokenInfo + | MockTokenPool_NotifySuccessfulLockOrBurn ; // crc32('CCIPSendExecutor_Execute') diff --git a/contracts/contracts/ccip/ccipsend_executor/types.tolk b/contracts/contracts/ccip/ccipsend_executor/types.tolk index e431b3db8..4406ecb39 100644 --- a/contracts/contracts/ccip/ccipsend_executor/types.tolk +++ b/contracts/contracts/ccip/ccipsend_executor/types.tolk @@ -29,6 +29,8 @@ struct CCIPSendExecutor_Addresses { type CCIPSendExecutor_State = | Cell | Cell + | Cell + | Cell | Cell struct CCIPSendExecutor_State_Initialized { diff --git a/contracts/contracts/ccip/onramp/messages.tolk b/contracts/contracts/ccip/onramp/messages.tolk index 17ee9b855..2679e2486 100644 --- a/contracts/contracts/ccip/onramp/messages.tolk +++ b/contracts/contracts/ccip/onramp/messages.tolk @@ -7,6 +7,7 @@ import "../ccipsend_executor/messages" import "../fee_quoter/messages" import "../ccipsend_executor/types" import "../fee_quoter/types" +import "../common/types" type OnRamp_InMessage = | OnRamp_Send diff --git a/contracts/contracts/ccip/router/messages.tolk b/contracts/contracts/ccip/router/messages.tolk index a726c4aac..2d4b812a0 100644 --- a/contracts/contracts/ccip/router/messages.tolk +++ b/contracts/contracts/ccip/router/messages.tolk @@ -9,6 +9,7 @@ import "../../lib/receiver/messages" import "../offramp/types" import "../offramp/messages" import "../onramp/messages" +import "../common/messages" type Router_InMsg = | Router_CCIPSend diff --git a/contracts/contracts/ccip/test/tokenPool/contract.tolk b/contracts/contracts/ccip/test/tokenPool/contract.tolk index 1b079e274..f56b9d03d 100644 --- a/contracts/contracts/ccip/test/tokenPool/contract.tolk +++ b/contracts/contracts/ccip/test/tokenPool/contract.tolk @@ -1,9 +1,11 @@ -struct (0x98769876) MockTokenPool_LockOrBurn { - tokenAmount: TokenAmount, - notify: address, -} +import "messages" -struct (0x87658765) MockTokenPool_NotifySuccessfulLockOrBurn {} +contract MockTokenPool { + author: "SmartContract Chainlink Limited SEZC" + version: "1.6.1" + description: "link.chain.ton.ccip.test.TokenPool" + incomingMessages: MockTokenPool_LockOrBurn +} fun onInternalMessage(in: InMessage) { val msg = lazy MockTokenPool_LockOrBurn.fromSlice(in.body); From 91507919c6735f4a304ddb0191c729ffb3ed1405 Mon Sep 17 00:00:00 2001 From: vicente Date: Mon, 8 Jun 2026 11:24:40 -0300 Subject: [PATCH 04/14] fix mockTokenPool missing messages.tolk file --- contracts/contracts/ccip/test/tokenPool/messages.tolk | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 contracts/contracts/ccip/test/tokenPool/messages.tolk diff --git a/contracts/contracts/ccip/test/tokenPool/messages.tolk b/contracts/contracts/ccip/test/tokenPool/messages.tolk new file mode 100644 index 000000000..9b7943378 --- /dev/null +++ b/contracts/contracts/ccip/test/tokenPool/messages.tolk @@ -0,0 +1,10 @@ +import "../../common/types" + +struct (0x98769876) MockTokenPool_LockOrBurn { + tokenAmount: TokenAmount, + notify: address, +} + +struct (0x87658765) MockTokenPool_NotifySuccessfulLockOrBurn {} + + From 0d9fe92179a7385ea871ca3f99fcb6dd25151050 Mon Sep 17 00:00:00 2001 From: vicente Date: Mon, 8 Jun 2026 19:50:51 -0300 Subject: [PATCH 05/14] fix some compilation errors in the contracts --- contracts/contracts/ccip/ccipsend_executor/contract.tolk | 1 + contracts/contracts/ccip/ccipsend_executor/types.tolk | 2 +- contracts/contracts/ccip/onramp/contract.tolk | 2 +- contracts/contracts/ccip/onramp/messages.tolk | 2 ++ 4 files changed, 5 insertions(+), 2 deletions(-) diff --git a/contracts/contracts/ccip/ccipsend_executor/contract.tolk b/contracts/contracts/ccip/ccipsend_executor/contract.tolk index 655c73ead..69c58f194 100644 --- a/contracts/contracts/ccip/ccipsend_executor/contract.tolk +++ b/contracts/contracts/ccip/ccipsend_executor/contract.tolk @@ -163,6 +163,7 @@ fun CCIPSendExecutor.onTokenInfoRece tokenAmount, tokenPool: msg.tokenInfo.tokenPool, destChainSelector: onrampSend.destChainSelector, + executorID: self.id, } }); requestLockOrBurn.send(SEND_MODE_CARRY_ALL_REMAINING_MESSAGE_VALUE); diff --git a/contracts/contracts/ccip/ccipsend_executor/types.tolk b/contracts/contracts/ccip/ccipsend_executor/types.tolk index 4406ecb39..916425743 100644 --- a/contracts/contracts/ccip/ccipsend_executor/types.tolk +++ b/contracts/contracts/ccip/ccipsend_executor/types.tolk @@ -57,7 +57,7 @@ struct CCIPSendExecutor_State_Finalized { struct CCIPSendExecutor_Config { feeQuoter: address, - tokenRegistry: address, + tokenRegistry: address?, } diff --git a/contracts/contracts/ccip/onramp/contract.tolk b/contracts/contracts/ccip/onramp/contract.tolk index 514d66759..dc5c30e04 100644 --- a/contracts/contracts/ccip/onramp/contract.tolk +++ b/contracts/contracts/ccip/onramp/contract.tolk @@ -304,7 +304,7 @@ fun calculateTokenRegistryAddress(st: OnRamp_Storage, token: address): address { fun onExecutorRequestsLockOrBurn(st: OnRamp_Storage, msg: OnRamp_ExecutorRequestsLockOrBurn, sender: address) { var destChainConfig = st.destChainConfigs.mustGet(msg.destChainSelector, Error.UnknownDestChainSelector as int); - routerLockOrBurn = createMessage({ + val routerLockOrBurn = createMessage({ bounce: true, value: 0, dest: destChainConfig.router, diff --git a/contracts/contracts/ccip/onramp/messages.tolk b/contracts/contracts/ccip/onramp/messages.tolk index 2679e2486..8f0577b7d 100644 --- a/contracts/contracts/ccip/onramp/messages.tolk +++ b/contracts/contracts/ccip/onramp/messages.tolk @@ -14,6 +14,7 @@ type OnRamp_InMessage = | OnRamp_GetValidatedFee | FeeQuoter_MessageValidated | FeeQuoter_MessageValidationFailed + | OnRamp_ExecutorRequestsLockOrBurn | OnRamp_ExecutorFinishedSuccessfully | OnRamp_ExecutorFinishedWithError | OnRamp_SetDynamicConfig @@ -43,6 +44,7 @@ struct (0x12312312) OnRamp_ExecutorRequestsLockOrBurn { tokenAmount: TokenAmount, tokenPool: address, destChainSelector: uint64, + executorID: CCIPSendExecutor_ID, } struct OnRamp_GetValidatedFeeContext { From 11f137b42ef1d7090228862e5be2bdbfac9ac802 Mon Sep 17 00:00:00 2001 From: vicente Date: Mon, 8 Jun 2026 20:06:32 -0300 Subject: [PATCH 06/14] fix all compilation errors --- .../contracts/ccip/ccipsend_executor/contract.tolk | 5 +++-- contracts/contracts/ccip/ccipsend_executor/types.tolk | 2 +- contracts/contracts/ccip/onramp/contract.tolk | 2 +- contracts/contracts/ccip/router/contract.tolk | 11 +++++++---- contracts/contracts/ccip/test/tokenPool/contract.tolk | 2 +- 5 files changed, 13 insertions(+), 9 deletions(-) diff --git a/contracts/contracts/ccip/ccipsend_executor/contract.tolk b/contracts/contracts/ccip/ccipsend_executor/contract.tolk index 69c58f194..0512651b1 100644 --- a/contracts/contracts/ccip/ccipsend_executor/contract.tolk +++ b/contracts/contracts/ccip/ccipsend_executor/contract.tolk @@ -52,7 +52,7 @@ fun onInternalMessage(in: InMessage) { // Sender must be TokenRegistry TokenRegistry_ReturnTokenInfo => { var this = CCIPSendExecutor.load(); - assert(this.addresses.load().tokenRegistry == in.senderAddress, CCIPSendExecutor_Error.Unauthorized); + assert(this.addresses.load().tokenRegistry! == in.senderAddress, CCIPSendExecutor_Error.Unauthorized); this.onTokenInfoReceived(msg); } MockTokenPool_NotifySuccessfulLockOrBurn => { @@ -127,10 +127,11 @@ fun CCIPSendExecutor.onMessageValid if (tokenAmounts.empty()) { setGasLimitToMaximum(); self.exitSuccessfully(msg.fee); + return; } // Else if there are token transfers continue querying the tokenRegistry - val tokenRegistry = self.addresses.load().tokenRegistry; + val tokenRegistry = self.addresses.load().tokenRegistry!; val queryMsg = createMessage({ bounce: true, value: 0, diff --git a/contracts/contracts/ccip/ccipsend_executor/types.tolk b/contracts/contracts/ccip/ccipsend_executor/types.tolk index 916425743..9905145cb 100644 --- a/contracts/contracts/ccip/ccipsend_executor/types.tolk +++ b/contracts/contracts/ccip/ccipsend_executor/types.tolk @@ -23,7 +23,7 @@ struct CCIPSendExecutor_Data { struct CCIPSendExecutor_Addresses { onramp: address, feeQuoter: address, - tokenRegistry: address, + tokenRegistry: address?, } type CCIPSendExecutor_State = diff --git a/contracts/contracts/ccip/onramp/contract.tolk b/contracts/contracts/ccip/onramp/contract.tolk index dc5c30e04..d80503330 100644 --- a/contracts/contracts/ccip/onramp/contract.tolk +++ b/contracts/contracts/ccip/onramp/contract.tolk @@ -299,7 +299,7 @@ fun onSend(st: OnRamp_Storage, destChainConfig: OnRamp_DestChainConfig, payload: fun calculateTokenRegistryAddress(st: OnRamp_Storage, token: address): address { // TODO: calculate token registry address - return createAddressNone() + return createAddressNone() as address } fun onExecutorRequestsLockOrBurn(st: OnRamp_Storage, msg: OnRamp_ExecutorRequestsLockOrBurn, sender: address) { diff --git a/contracts/contracts/ccip/router/contract.tolk b/contracts/contracts/ccip/router/contract.tolk index b32f042b2..46bf98bda 100644 --- a/contracts/contracts/ccip/router/contract.tolk +++ b/contracts/contracts/ccip/router/contract.tolk @@ -13,6 +13,8 @@ import "../onramp/messages" import "../onramp/types" import "../offramp/messages" import "../offramp/types" +import "../common/messages" +import "../test/tokenPool/messages" import "types" import "messages" @@ -163,15 +165,16 @@ fun onInternalMessage(in: InMessage) { // Sender must be a Jetton Wallet owned by the Router Common_JettonTransferNotification => { //TODO: Validate sender is owned jetton transfer + val st = lazy Storage.load(); // TODO: catch errors, if different message type than CCIPSend - val sendMsg = Router_CCIPSend.fromCell(transferNotification.forwardPayload!); + val sendMsg = Router_CCIPSend.fromCell(msg.forwardPayload!); var tokenAmounts = sendMsg.tokenAmounts.iter(); assert (!tokenAmounts.empty()) throw Router_Error.MissingTokenAmounts; val transferedJetton = tokenAmounts.next(); - assert (transferedJetton.amount == transferNotification.amount) throw 5; // TODO: if transfered token is link, extract fee before this check + assert (transferedJetton.amount == msg.amount) throw 5; // TODO: if transfered token is link, extract fee before this check assert (tokenAmounts.empty()) throw Router_Error.NoMultiTokenTransfers; val onRamp = st.onRamps.mustGet(sendMsg.destChainSelector, Router_Error.DestChainNotEnabled as int); @@ -179,7 +182,7 @@ fun onInternalMessage(in: InMessage) { bounce: true, value: 0, dest: onRamp, - body: OnRamp_Send { msg: sendMsg.toCell(), metadata: Metadata{ sender: transferNotification.sender, value: transferNotification.amount } }, + body: OnRamp_Send { msg: sendMsg.toCell(), metadata: Metadata{ sender: msg.sender, value: msg.amount } }, }); onRampSend.send(SEND_MODE_CARRY_ALL_REMAINING_MESSAGE_VALUE); } @@ -652,7 +655,7 @@ fun sendMessageRejected(sender: address, queryID: uint64, error: uint256) { //TODO Should be a jetton transfer to the TokenPool wallet, and the LockOrBurn message should go in the forwardPayload of that jetton transfer fun onLockOrBurn(msg: Router_LockOrBurn) { - tokenPoolLockOrBurn = createMessage({ + val tokenPoolLockOrBurn = createMessage({ bounce: true, value: 0, dest: msg.tokenPool, diff --git a/contracts/contracts/ccip/test/tokenPool/contract.tolk b/contracts/contracts/ccip/test/tokenPool/contract.tolk index f56b9d03d..13c48caf8 100644 --- a/contracts/contracts/ccip/test/tokenPool/contract.tolk +++ b/contracts/contracts/ccip/test/tokenPool/contract.tolk @@ -9,7 +9,7 @@ contract MockTokenPool { fun onInternalMessage(in: InMessage) { val msg = lazy MockTokenPool_LockOrBurn.fromSlice(in.body); - notification = createMessage({ + val notification = createMessage({ bounce: false, value: 0, dest: msg.notify, From f198c41d50c5c73a4d4cf00661727d119ea09d9f Mon Sep 17 00:00:00 2001 From: vicente Date: Mon, 8 Jun 2026 21:41:15 -0300 Subject: [PATCH 07/14] test onramp flow token transfers skeleton --- .../contracts/ccip/fee_quoter/contract.tolk | 8 +- contracts/contracts/ccip/onramp/contract.tolk | 5 +- contracts/contracts/ccip/onramp/storage.tolk | 4 + contracts/contracts/ccip/router/contract.tolk | 5 +- .../ccip/token_registry/contract.tolk | 14 +- .../ccip/token_registry/storage.tolk | 2 + contracts/tests/Logs.ts | 17 +- .../e2e/CCIPSendWithTokenTransfer.spec.ts | 296 ++++++++++++++++++ .../FeeQuoter.getValidatedFee.spec.ts | 64 +--- contracts/tests/ccip/router/Router.Setup.ts | 12 +- .../wrappers/ccip.TokenRegistry.compile.ts | 7 + contracts/wrappers/ccip/CCIPSendExecutor.ts | 15 +- contracts/wrappers/ccip/MockTokenPool.ts | 43 +++ contracts/wrappers/ccip/OnRamp.ts | 5 + contracts/wrappers/ccip/TokenRegistry.ts | 60 ++++ 15 files changed, 495 insertions(+), 62 deletions(-) create mode 100644 contracts/tests/ccip/e2e/CCIPSendWithTokenTransfer.spec.ts create mode 100644 contracts/wrappers/ccip.TokenRegistry.compile.ts create mode 100644 contracts/wrappers/ccip/MockTokenPool.ts create mode 100644 contracts/wrappers/ccip/TokenRegistry.ts diff --git a/contracts/contracts/ccip/fee_quoter/contract.tolk b/contracts/contracts/ccip/fee_quoter/contract.tolk index 42afd8095..724d12b86 100644 --- a/contracts/contracts/ccip/fee_quoter/contract.tolk +++ b/contracts/contracts/ccip/fee_quoter/contract.tolk @@ -277,9 +277,10 @@ fun calculateValidatedFee(msg: Router_CCIPSend): Fee { val (executionGasPrice: uint112, dataAvailabilityGasPrice: uint112) = destChainConfig.getValidatedGasPrice(); - val tokensIter = msg.tokenAmounts.iter(); val premiumFeeUsdWei = mustProd(destChainConfig.config.networkFeeUsdCents, VAL_1E16, FeeQuoter_Error.PremiumFeeOverflow); - assert (tokensIter.empty()) throw FeeQuoter_Error.UnsupportedNumberOfTokens; + // NOTE: token transfers are currently priced as if the message carried no tokens + // (the extra token-transfer fee is ignored). The blocking empty-tokens assert was removed + // to enable the token-transfer send flow. val dataAvailabilityCost = _dataAvailabilityCost( destChainConfig, @@ -366,8 +367,7 @@ fun _dataAvailabilityCost( fun validateMessageAndResolveGasLimitForDestination(extraArgs: cell, config: FeeQuoterDestChainConfig, message: Router_CCIPSend, msgDataLen: uint256): int { // Check that payload is formed correctly. assert (msgDataLen <= config.maxDataBytes) throw FeeQuoter_Error.MsgDataTooLarge; - val tokenAmounts = message.tokenAmounts.iter(); - assert (tokenAmounts.empty()) throw FeeQuoter_Error.UnsupportedNumberOfTokens; + // NOTE: token transfers are allowed; their extra fee is currently ignored (priced as a plain message). // NOTE: we could deploy distinct contracts to cut down on code if (config.chainFamilySelector == CHAIN_FAMILY_SELECTOR_EVM || diff --git a/contracts/contracts/ccip/onramp/contract.tolk b/contracts/contracts/ccip/onramp/contract.tolk index d80503330..54d4f7420 100644 --- a/contracts/contracts/ccip/onramp/contract.tolk +++ b/contracts/contracts/ccip/onramp/contract.tolk @@ -298,8 +298,9 @@ fun onSend(st: OnRamp_Storage, destChainConfig: OnRamp_DestChainConfig, payload: } fun calculateTokenRegistryAddress(st: OnRamp_Storage, token: address): address { - // TODO: calculate token registry address - return createAddressNone() as address + // TODO: resolve a per-token registry address. For now the OnRamp stores a single + // TokenRegistry address that is used for every token transfer. + return st.tokenRegistry! } fun onExecutorRequestsLockOrBurn(st: OnRamp_Storage, msg: OnRamp_ExecutorRequestsLockOrBurn, sender: address) { diff --git a/contracts/contracts/ccip/onramp/storage.tolk b/contracts/contracts/ccip/onramp/storage.tolk index 505563a88..3e50402e5 100644 --- a/contracts/contracts/ccip/onramp/storage.tolk +++ b/contracts/contracts/ccip/onramp/storage.tolk @@ -14,6 +14,10 @@ struct OnRamp_Storage { destChainConfigs: map; // chainSelector -> DestChainConfig executor: ExecutorDeployment; + + // Address of the TokenRegistry queried by the CCIPSendExecutor during token transfers. + // Null until token transfers are configured. TODO: replace with per-token registry resolution. + tokenRegistry: address?; } fun OnRamp_Storage.load(): OnRamp_Storage { diff --git a/contracts/contracts/ccip/router/contract.tolk b/contracts/contracts/ccip/router/contract.tolk index 46bf98bda..08089d5a4 100644 --- a/contracts/contracts/ccip/router/contract.tolk +++ b/contracts/contracts/ccip/router/contract.tolk @@ -178,11 +178,14 @@ fun onInternalMessage(in: InMessage) { assert (tokenAmounts.empty()) throw Router_Error.NoMultiTokenTransfers; val onRamp = st.onRamps.mustGet(sendMsg.destChainSelector, Router_Error.DestChainNotEnabled as int); + // Fees are paid in native TON, not in the transferred token. metadata.value must be the + // native TON attached to the transfer notification (used downstream to cover fee + + // execution costs), mirroring the plain-message path which uses in.valueCoins. val onRampSend = createMessage({ bounce: true, value: 0, dest: onRamp, - body: OnRamp_Send { msg: sendMsg.toCell(), metadata: Metadata{ sender: msg.sender, value: msg.amount } }, + body: OnRamp_Send { msg: sendMsg.toCell(), metadata: Metadata{ sender: msg.sender, value: in.valueCoins } }, }); onRampSend.send(SEND_MODE_CARRY_ALL_REMAINING_MESSAGE_VALUE); } diff --git a/contracts/contracts/ccip/token_registry/contract.tolk b/contracts/contracts/ccip/token_registry/contract.tolk index 750250b6d..b79aecc54 100644 --- a/contracts/contracts/ccip/token_registry/contract.tolk +++ b/contracts/contracts/ccip/token_registry/contract.tolk @@ -1,6 +1,18 @@ +// SPDX-License-Identifier: BUSL-1.1 import "messages" import "storage" +tolk 1.4.1 + +contract TokenRegistry { + author: "SmartContract Chainlink Limited SEZC" + version: "1.6.1" + description: "link.chain.ton.ccip.TokenRegistry" + + storage: TokenRegistry_Storage + incomingMessages: TokenRegistry_InMessage +} + fun onInternalMessage(in: InMessage) { val msg = lazy TokenRegistry_InMessage.fromSlice(in.body); @@ -20,7 +32,7 @@ fun onGetTokenInfo(msg: TokenRegistry_GetTokenInfo, sender: address) { dest: sender, value: 0, bounce: false, - body: TokenRegistry_TokenPoolInfo { + body: TokenRegistry_ReturnTokenInfo { tokenInfo: st.info, } }); diff --git a/contracts/contracts/ccip/token_registry/storage.tolk b/contracts/contracts/ccip/token_registry/storage.tolk index 8dc569970..5c1064339 100644 --- a/contracts/contracts/ccip/token_registry/storage.tolk +++ b/contracts/contracts/ccip/token_registry/storage.tolk @@ -1,3 +1,5 @@ +import "types" + struct TokenRegistry_Storage { info: TokenRegistry_TokenInfo } diff --git a/contracts/tests/Logs.ts b/contracts/tests/Logs.ts index eb17f269b..46b56f508 100644 --- a/contracts/tests/Logs.ts +++ b/contracts/tests/Logs.ts @@ -7,6 +7,7 @@ import * as offRamp from '../wrappers/ccip/OffRamp' import { prettifyAddressesMap } from './utils/prettyPrint' import { crc32 } from 'zlib' import * as onramp from '../wrappers/ccip/OnRamp' +import * as router from '../wrappers/ccip/Router' // https://github.com/ton-blockchain/liquid-staking-contract/blob/1f4e9badbed52a4cf80cc58e4bb36ed375c6c8e7/utils.ts#L269-L294 export const getExternals = (transactions: BlockchainTransaction[]) => { @@ -226,11 +227,23 @@ export const testLogCCIPMessageSent = ( const msg: onramp.CCIPMessageSent = onramp.builder.events.ccipMessageSent.load(x.beginParse()) const sender = msg.message.sender + // Decode tokenAmounts from its raw Cell into an array so matches can use plain objects. + const decodedMessage = { + ...msg.message, + body: { + ...msg.message.body, + tokenAmounts: fromSnakeData( + msg.message.body.tokenAmounts, + router.builder.data.tokenAmount.load, + ), + }, + } + // Check other fields using toMatchObject (excluding sender to avoid object comparison) - const { sender: _, ...messageWithoutSender } = msg.message + const { sender: _, ...messageWithoutSender } = decodedMessage const { sender: __, ...matchWithoutSender } = match.message || {} - matchesObject(messageWithoutSender, matchWithoutSender) + matchesObject(messageWithoutSender, matchWithoutSender as object) // Check sender address using .equals() if specified in match if (match.message?.sender && match.message.sender instanceof Address) { diff --git a/contracts/tests/ccip/e2e/CCIPSendWithTokenTransfer.spec.ts b/contracts/tests/ccip/e2e/CCIPSendWithTokenTransfer.spec.ts new file mode 100644 index 000000000..0d4e53c54 --- /dev/null +++ b/contracts/tests/ccip/e2e/CCIPSendWithTokenTransfer.spec.ts @@ -0,0 +1,296 @@ +import '@ton/test-utils' +import { compile } from '@ton/blueprint' +import { toNano, Cell, Address, beginCell } from '@ton/core' +import { Blockchain, SandboxContract, TreasuryContract } from '@ton/sandbox' + +import { LogTypes } from '../../../wrappers/ccip/Logs' +import { assertLog } from '../../Logs' +import { WRAPPED_NATIVE } from '../../../src/utils' + +import * as fq from '../../../wrappers/ccip/FeeQuoter' +import * as or from '../../../wrappers/ccip/OnRamp' +import * as rt from '../../../wrappers/ccip/Router' +import { TokenRegistry } from '../../../wrappers/ccip/TokenRegistry' +import { MockTokenPool } from '../../../wrappers/ccip/MockTokenPool' +import { JettonMinter } from '../../../wrappers/jetton/JettonMinter' +import { JettonWallet } from '../../../wrappers/jetton/JettonWallet' +import { WTON_MINT_OPCODE } from '../../../wrappers/wton' + +import { setup, CHAINSEL_EVM_TEST_90000001, EVM_ADDRESS } from '../router/Router.Setup' + +const JETTON_CONTENT = beginCell().storeStringTail('wton.e2e').endCell() + +// Amount of wTON the user transfers (also the CCIP tokenAmount). Deliberately different from +// FORWARD_TON_AMOUNT so the test can prove metadata.value is the attached native TON, not the +// transferred token amount (fees are paid in native TON, not in the transferred token). +const TOKEN_AMOUNT = toNano('5') + +// Native TON attached to the transfer notification, used to pay fees + execution costs. +const FORWARD_TON_AMOUNT = toNano('1') + +describe('CCIPSend with token transfer (e2e)', () => { + let blockchain: Blockchain + + let minterCode: Cell + let walletCode: Cell + + let deployer: SandboxContract + let sender: SandboxContract + + let minter: SandboxContract + let mockTokenPool: SandboxContract + let tokenRegistry: SandboxContract + + let router: SandboxContract + let feeQuoter: SandboxContract + let onRamp: SandboxContract + + beforeAll(async () => { + minterCode = await compile('wton.JettonMinter') + walletCode = await compile('wton.JettonWallet') + }) + + beforeEach(async () => { + blockchain = await Blockchain.create() + blockchain.verbosity = { + print: true, + blockchainLogs: false, + vmLogs: 'none', + debugLogs: true, + } + + deployer = await blockchain.treasury('deployer') + sender = await blockchain.treasury('sender') + + // 1. Deploy the wTON jetton minter. + minter = blockchain.openContract( + JettonMinter.createFromConfig( + { + admin: null, + transferAdmin: null, + walletCode, + jettonContent: JETTON_CONTENT, + totalSupply: 0n, + }, + minterCode, + ), + ) + await minter.sendTopUpTons(deployer.getSender(), toNano('0.01')) + + // 2. Mint wTON to the user (deploys the user's wallet with a balance). + await minter.sendMint(deployer.getSender(), { + value: TOKEN_AMOUNT + toNano('1') + toNano('0.3'), + mintOpcode: WTON_MINT_OPCODE, + message: { + queryId: 0n, + destination: sender.address, + tonAmount: toNano('1'), + jettonAmount: TOKEN_AMOUNT, + from: null, + responseDestination: sender.address, + forwardTonAmount: 0n, + customPayload: null, + }, + }) + + // 3. Deploy the MockTokenPool that performs the (mock) lock/burn. + const mockTokenPoolCode = await MockTokenPool.code() + mockTokenPool = blockchain.openContract(MockTokenPool.createFromConfig(mockTokenPoolCode)) + await mockTokenPool.sendDeploy(deployer.getSender(), toNano('0.05')) + + // 4. Deploy the TokenRegistry, hard-coded to return the MockTokenPool address. + const tokenRegistryCode = await TokenRegistry.code() + tokenRegistry = blockchain.openContract( + TokenRegistry.createFromConfig( + { + info: { + tokenPool: mockTokenPool.address, + minterAddress: minter.address, + enabled: true, + }, + }, + tokenRegistryCode, + ), + ) + await tokenRegistry.sendDeploy(deployer.getSender(), toNano('0.05')) + + // 5. Deploy router/feeQuoter/onRamp/offRamp, storing the TokenRegistry in the OnRamp. + ;({ router, feeQuoter, onRamp } = await setup(blockchain, { + deployer, + sender, + tokenRegistry: tokenRegistry.address, + })) + }) + + it('propagates a token-transfer-initiated CCIP send end to end', async () => { + const ccipSend: rt.CCIPSend = { + queryID: 1, + destChainSelector: CHAINSEL_EVM_TEST_90000001, + receiver: EVM_ADDRESS, + data: Cell.EMPTY, + tokenAmounts: [{ amount: TOKEN_AMOUNT, token: minter.address }], + feeToken: WRAPPED_NATIVE, + extraArgs: rt.builder.data.extraArgs + .encode({ + kind: 'generic-v2', + gasLimit: 100n, + allowOutOfOrderExecution: true, + }) + .asCell(), + } + + // The CCIPSend payload travels as the forward payload of the jetton transfer. + const forwardPayload = rt.builder.message.in.ccipSend.encode(ccipSend).endCell() + + const routerWalletAddress = await minter.getWalletAddress(router.address) + const senderWallet = blockchain.openContract( + JettonWallet.createFromAddress(await minter.getWalletAddress(sender.address)), + ) + + // User transfers wTON to the router-owned wallet, carrying the CCIPSend payload. + const result = await senderWallet.sendTransfer(sender.getSender(), { + value: FORWARD_TON_AMOUNT + toNano('2'), + message: { + queryId: 1, + jettonAmount: TOKEN_AMOUNT, + destination: router.address, + responseDestination: sender.address, + customPayload: null, + forwardTonAmount: FORWARD_TON_AMOUNT, + forwardPayload, + }, + }) + + // Discover the deployed CCIPSendExecutor (first message emitted by the OnRamp). + const executorAddress = ((): Address => { + for (const tx of result.transactions) { + const inMsg = tx.inMessage + if ( + inMsg?.info.type === 'internal' && + inMsg.info.src instanceof Address && + inMsg.info.src.equals(onRamp.address) && + inMsg.info.dest instanceof Address + ) { + return inMsg.info.dest + } + } + throw new Error('Executor address not found') + })() + + // --- jetton transfer leg --- + // user -> user wallet + expect(result.transactions).toHaveTransaction({ + from: sender.address, + to: senderWallet.address, + success: true, + }) + // user wallet -> router wallet (deploys it) + expect(result.transactions).toHaveTransaction({ + from: senderWallet.address, + to: routerWalletAddress, + deploy: true, + success: true, + }) + // router wallet -> router (transfer notification) + expect(result.transactions).toHaveTransaction({ + from: routerWalletAddress, + to: router.address, + success: true, + }) + + // --- ccip send leg --- + // router -> onRamp + expect(result.transactions).toHaveTransaction({ + from: router.address, + to: onRamp.address, + success: true, + }) + // onRamp deploys the executor + expect(result.transactions).toHaveTransaction({ + from: onRamp.address, + to: executorAddress, + deploy: true, + success: true, + }) + // executor -> feeQuoter and back + expect(result.transactions).toHaveTransaction({ + from: executorAddress, + to: feeQuoter.address, + success: true, + }) + expect(result.transactions).toHaveTransaction({ + from: feeQuoter.address, + to: executorAddress, + success: true, + }) + // executor -> tokenRegistry and back + expect(result.transactions).toHaveTransaction({ + from: executorAddress, + to: tokenRegistry.address, + success: true, + }) + expect(result.transactions).toHaveTransaction({ + from: tokenRegistry.address, + to: executorAddress, + success: true, + }) + // executor -> onRamp (requests lock/burn) + expect(result.transactions).toHaveTransaction({ + from: executorAddress, + to: onRamp.address, + success: true, + }) + // onRamp -> router (forwards lock/burn) + expect(result.transactions).toHaveTransaction({ + from: onRamp.address, + to: router.address, + success: true, + }) + // router -> mockTokenPool (lock/burn) and back to the executor (confirmation) + expect(result.transactions).toHaveTransaction({ + from: router.address, + to: mockTokenPool.address, + success: true, + }) + expect(result.transactions).toHaveTransaction({ + from: mockTokenPool.address, + to: executorAddress, + success: true, + }) + // executor -> onRamp (finished successfully) and self-destructs + expect(result.transactions).toHaveTransaction({ + from: executorAddress, + to: onRamp.address, + success: true, + }) + + // OnRamp emits the CCIPMessageSent log. Verify the token-transfer amount equals TOKEN_AMOUNT (wTON). + assertLog(result.transactions, onRamp.address, LogTypes.CCIPMessageSent, { + message: { + header: { + destChainSelector: CHAINSEL_EVM_TEST_90000001, + }, + sender: sender.address, + body: { + tokenAmounts: [{ amount: TOKEN_AMOUNT, token: minter.address }], + }, + }, + } as any) + + // OnRamp -> router (Router_MessageSent) + expect(result.transactions).toHaveTransaction({ + from: onRamp.address, + to: router.address, + op: rt.opcodes.in.messageSent, + success: true, + }) + + // router -> user (CCIPSendACK) + expect(result.transactions).toHaveTransaction({ + from: router.address, + to: sender.address, + op: rt.opcodes.out.ccipSendACK, + success: true, + }) + }) +}) diff --git a/contracts/tests/ccip/feequoter/FeeQuoter.getValidatedFee.spec.ts b/contracts/tests/ccip/feequoter/FeeQuoter.getValidatedFee.spec.ts index d29c99852..74c49150a 100644 --- a/contracts/tests/ccip/feequoter/FeeQuoter.getValidatedFee.spec.ts +++ b/contracts/tests/ccip/feequoter/FeeQuoter.getValidatedFee.spec.ts @@ -313,57 +313,23 @@ describe('FeeQuoter GetValidatedFee', () => { }) }) - it('should revert when too many tokens', async () => { - const tooManyTokens = [FeeQuoterSetup.SOURCE_FEE_TOKEN] // We don't support token transfers in TON yet - - const message: rt.CCIPSend = { - destChainSelector: FeeQuoterSetup.DEST_CHAIN_SELECTOR_EVM, - receiver: FeeQuoterSetup.DEST_ADDRESS, - data: beginCell().endCell(), - tokenAmounts: tooManyTokens.map((token) => ({ - token: token.token, - amount: toNano('100'), - })), - feeToken: FeeQuoterSetup.NATIVE_TON.token, - extraArgs: rt.builder.data.extraArgs - .encode({ - kind: 'generic-v2', - gasLimit: BigInt(FeeQuoterSetup.GAS_LIMIT), - allowOutOfOrderExecution: false, - }) - .endCell(), - } + it('accepts a token transfer and prices it like a token-less message', async () => { + // Token transfers are now allowed; the extra token-transfer fee is currently ignored, + // so a single-token message is priced exactly like the equivalent token-less message. + const feeToken = FeeQuoterSetup.NATIVE_TON.token + + const withToken = setup.generateSingleTokenMessage({ + token: FeeQuoterSetup.SOURCE_FEE_TOKEN.token, + amount: toNano('100'), + feeToken, + }) + const withoutToken = setup.generateEmptyMessage({ feeToken }) - const result = await setup.bind.feeQuoter.sendGetValidatedFee( - setup.acc.externalCaller.getSender(), - { - value: toNano('1'), - msg: { msg: message, context: beginCell().asSlice() }, - }, - ) + // getValidatedFee throws if validation fails, so reaching the assertion proves acceptance. + const tokenFee = await setup.getValidatedFee(withToken) + const emptyFee = await setup.getValidatedFee(withoutToken) - // Should return failure - destination chain not configured - expect(result.transactions).toHaveTransaction({ - from: setup.acc.externalCaller.getSender().address, - to: setup.bind.feeQuoter.address, - success: true, - }) - expect(result.transactions).toHaveTransaction({ - from: setup.bind.feeQuoter.address, - op: sx.opcodes.in.messageValidationFailed, - success: true, - body(x) { - return verifyBodyMessage( - x, - sx.builder.message.in.messageValidationFailed, - [ - (msg) => { - return msg.error === BigInt(feeQuoter.errors.UnsupportedNumberOfTokens) - }, - ], - ) - }, - }) + expect(tokenFee.fee.feeTokenAmount).toEqual(emptyFee.fee.feeTokenAmount) }) it('should revert when gas limit too high', async () => { diff --git a/contracts/tests/ccip/router/Router.Setup.ts b/contracts/tests/ccip/router/Router.Setup.ts index 0f0a47f41..fb0af4fc1 100644 --- a/contracts/tests/ccip/router/Router.Setup.ts +++ b/contracts/tests/ccip/router/Router.Setup.ts @@ -20,6 +20,8 @@ type RouterSetupOptionsCommon = { receiver?: SandboxContract router?: SandboxContract skipRouterOnRampConfig?: boolean + // Optional TokenRegistry address stored in the OnRamp, used for token-transfer sends. + tokenRegistry?: Address } type RouterSetupOverrides = Partial<{ feeQuoter: SandboxContract | SandboxContract @@ -80,7 +82,13 @@ export async function setup( const feeQuoter = opts.feeQuoter ?? (await deployFeeQuoterInstance(blockchain, deployer)) const onRamp = opts.onRamp ?? - (await deployOnRampInstance(blockchain, deployer, router.address, feeQuoter.address)) + (await deployOnRampInstance( + blockchain, + deployer, + router.address, + feeQuoter.address, + opts.tokenRegistry, + )) const offRamp = opts.offRamp ?? @@ -262,6 +270,7 @@ async function deployOnRampInstance( deployer: SandboxContract, router: Address, feeQuoter: Address, + tokenRegistry?: Address, ) { const code = await contractCode.ccip.local('OnRamp') const data: or.OnRampStorage = { @@ -282,6 +291,7 @@ async function deployOnRampInstance( deployableCode: await contractCode.ccip.local('Deployable'), executorCode: await contractCode.ccip.local('CCIPSendExecutor'), }, + tokenRegistry: tokenRegistry ?? null, } const onRamp = blockchain.openContract(or.OnRamp.createFromConfig(data, code)) diff --git a/contracts/wrappers/ccip.TokenRegistry.compile.ts b/contracts/wrappers/ccip.TokenRegistry.compile.ts new file mode 100644 index 000000000..4a752e2f9 --- /dev/null +++ b/contracts/wrappers/ccip.TokenRegistry.compile.ts @@ -0,0 +1,7 @@ +import { CompilerConfig } from '@ton/blueprint' + +export const compile: CompilerConfig = { + lang: 'tolk', + entrypoint: 'contracts/ccip/token_registry/contract.tolk', + withStackComments: true, +} diff --git a/contracts/wrappers/ccip/CCIPSendExecutor.ts b/contracts/wrappers/ccip/CCIPSendExecutor.ts index ed95d315d..4c20a4a61 100644 --- a/contracts/wrappers/ccip/CCIPSendExecutor.ts +++ b/contracts/wrappers/ccip/CCIPSendExecutor.ts @@ -48,6 +48,8 @@ export type Data = { export type Addresses = { onramp: Address feeQuoter: Address + // Null when the send carries no token transfers. + tokenRegistry?: Address | null } export type State = Initialized | OnGoingFeeValidation @@ -62,6 +64,8 @@ export type OnGoingFeeValidation = { export type Config = { feeQuoter: Address + // Null when the send carries no token transfers. + tokenRegistry?: Address | null } export type Execute = { @@ -85,12 +89,16 @@ export const builder = (() => { const addresses: CellCodec = { encode: (data: Addresses): Builder => { - return beginCell().storeAddress(data.onramp).storeAddress(data.feeQuoter) + return beginCell() + .storeAddress(data.onramp) + .storeAddress(data.feeQuoter) + .storeAddress(data.tokenRegistry ?? null) }, load: (src: Slice): Addresses => { return { onramp: src.loadAddress(), feeQuoter: src.loadAddress(), + tokenRegistry: src.loadMaybeAddress(), } }, } @@ -119,11 +127,14 @@ export const builder = (() => { const config: CellCodec = { encode: (data: Config): Builder => { - return beginCell().storeAddress(data.feeQuoter) + return beginCell() + .storeAddress(data.feeQuoter) + .storeAddress(data.tokenRegistry ?? null) }, load: (src: Slice): Config => { return { feeQuoter: src.loadAddress(), + tokenRegistry: src.loadMaybeAddress(), } }, } diff --git a/contracts/wrappers/ccip/MockTokenPool.ts b/contracts/wrappers/ccip/MockTokenPool.ts new file mode 100644 index 000000000..e54cd9ae0 --- /dev/null +++ b/contracts/wrappers/ccip/MockTokenPool.ts @@ -0,0 +1,43 @@ +import { + Address, + beginCell, + Cell, + Contract, + contractAddress, + ContractProvider, + Sender, + SendMode, +} from '@ton/core' +import { compile } from '@ton/blueprint' + +export const ARTIFACT_NAME = 'ccip.test.mockTokenPool' + +// The MockTokenPool contract declares no storage, so its data cell is empty. +export class MockTokenPool implements Contract { + constructor( + readonly address: Address, + readonly init?: { code: Cell; data: Cell }, + ) {} + + static createFromAddress(address: Address) { + return new MockTokenPool(address) + } + + static createFromConfig(code: Cell, workchain = 0) { + const data = beginCell().endCell() + const init = { code, data } + return new MockTokenPool(contractAddress(workchain, init), init) + } + + static code(): Promise { + return compile(ARTIFACT_NAME) + } + + async sendDeploy(provider: ContractProvider, via: Sender, value: bigint) { + await provider.internal(via, { + value, + sendMode: SendMode.PAY_GAS_SEPARATELY, + body: Cell.EMPTY, + }) + } +} diff --git a/contracts/wrappers/ccip/OnRamp.ts b/contracts/wrappers/ccip/OnRamp.ts index 67cc76628..9cc2f259c 100644 --- a/contracts/wrappers/ccip/OnRamp.ts +++ b/contracts/wrappers/ccip/OnRamp.ts @@ -42,6 +42,8 @@ export type OnRampStorage = { config: DynamicConfig destChainConfigs: Dictionary executor: ExecutorDeployment + // Address of the TokenRegistry queried during token transfers. Null when not configured. + tokenRegistry?: Address | null } export type ExecutorDeployment = { @@ -229,6 +231,7 @@ export const builder = (() => { .storeRef(dynamicConfig.encode(data.config).asCell()) .storeDict(data.destChainConfigs) .storeBuilder(executor.encode(data.executor)) + .storeAddress(data.tokenRegistry ?? null) }, load: function (src: Slice): OnRampStorage { const id = src.loadUintBig(32) @@ -237,6 +240,7 @@ export const builder = (() => { const config = dynamicConfig.load(src.loadRef().beginParse()) const destChainConfigs = src.loadDict(Dictionary.Keys.BigUint(64), Dictionary.Values.Cell()) const executorData = executor.load(src) + const tokenRegistry = src.loadMaybeAddress() return { id, ownable, @@ -244,6 +248,7 @@ export const builder = (() => { config, destChainConfigs, executor: executorData, + tokenRegistry, } }, } diff --git a/contracts/wrappers/ccip/TokenRegistry.ts b/contracts/wrappers/ccip/TokenRegistry.ts new file mode 100644 index 000000000..a574cc207 --- /dev/null +++ b/contracts/wrappers/ccip/TokenRegistry.ts @@ -0,0 +1,60 @@ +import { + Address, + beginCell, + Cell, + Contract, + contractAddress, + ContractProvider, + Sender, + SendMode, +} from '@ton/core' +import { compile } from '@ton/blueprint' + +export const ARTIFACT_NAME = 'ccip.TokenRegistry' + +export type TokenInfo = { + tokenPool: Address + minterAddress: Address + enabled: boolean +} + +export type TokenRegistryStorage = { + info: TokenInfo +} + +export function storageToCell(data: TokenRegistryStorage): Cell { + return beginCell() + .storeAddress(data.info.tokenPool) + .storeAddress(data.info.minterAddress) + .storeBit(data.info.enabled) + .endCell() +} + +export class TokenRegistry implements Contract { + constructor( + readonly address: Address, + readonly init?: { code: Cell; data: Cell }, + ) {} + + static createFromAddress(address: Address) { + return new TokenRegistry(address) + } + + static createFromConfig(config: TokenRegistryStorage, code: Cell, workchain = 0) { + const data = storageToCell(config) + const init = { code, data } + return new TokenRegistry(contractAddress(workchain, init), init) + } + + static code(): Promise { + return compile(ARTIFACT_NAME) + } + + async sendDeploy(provider: ContractProvider, via: Sender, value: bigint) { + await provider.internal(via, { + value, + sendMode: SendMode.PAY_GAS_SEPARATELY, + body: Cell.EMPTY, + }) + } +} From 8b19471a268f5fc18d8c0fc5f3675172256f0ba8 Mon Sep 17 00:00:00 2001 From: vicente Date: Mon, 8 Jun 2026 23:28:50 -0300 Subject: [PATCH 08/14] fix opcodes oplint --- contracts/contracts/ccip/onramp/messages.tolk | 2 +- contracts/contracts/ccip/router/messages.tolk | 2 +- .../ccip/test/tokenPool/messages.tolk | 4 +- .../ccip/token_registry/messages.tolk | 2 +- contracts/wrappers/ccip/CCIPSendExecutor.ts | 2 + contracts/wrappers/ccip/MockTokenPool.ts | 9 + contracts/wrappers/ccip/OnRamp.ts | 1 + contracts/wrappers/ccip/Router.ts | 1 + contracts/wrappers/ccip/TokenRegistry.ts | 6 + .../wrappers/gen/ccip/CCIPSendExecutor.ts | 410 ++++++++++++++++-- contracts/wrappers/gen/ccip/FeeQuoter.ts | 3 +- contracts/wrappers/gen/ccip/OnRamp.ts | 140 +++++- contracts/wrappers/gen/ccip/Router.ts | 201 ++++++++- 13 files changed, 723 insertions(+), 60 deletions(-) diff --git a/contracts/contracts/ccip/onramp/messages.tolk b/contracts/contracts/ccip/onramp/messages.tolk index 8f0577b7d..a24959b34 100644 --- a/contracts/contracts/ccip/onramp/messages.tolk +++ b/contracts/contracts/ccip/onramp/messages.tolk @@ -40,7 +40,7 @@ struct (0x9c2ccc7e) OnRamp_GetValidatedFee { context: T; } -struct (0x12312312) OnRamp_ExecutorRequestsLockOrBurn { +struct (0x9be1fb61) OnRamp_ExecutorRequestsLockOrBurn { tokenAmount: TokenAmount, tokenPool: address, destChainSelector: uint64, diff --git a/contracts/contracts/ccip/router/messages.tolk b/contracts/contracts/ccip/router/messages.tolk index 2d4b812a0..bd163e876 100644 --- a/contracts/contracts/ccip/router/messages.tolk +++ b/contracts/contracts/ccip/router/messages.tolk @@ -126,7 +126,7 @@ struct (0x4dd6aa82) Router_GetValidatedFee { context: T; } -struct (0x45645645) Router_LockOrBurn { +struct (0x6f2d00df) Router_LockOrBurn { tokenPool: address, tokenAmount: TokenAmount, destChainSelector: uint64, diff --git a/contracts/contracts/ccip/test/tokenPool/messages.tolk b/contracts/contracts/ccip/test/tokenPool/messages.tolk index 9b7943378..1476613ae 100644 --- a/contracts/contracts/ccip/test/tokenPool/messages.tolk +++ b/contracts/contracts/ccip/test/tokenPool/messages.tolk @@ -1,10 +1,10 @@ import "../../common/types" -struct (0x98769876) MockTokenPool_LockOrBurn { +struct (0x7dd8f942) MockTokenPool_LockOrBurn { tokenAmount: TokenAmount, notify: address, } -struct (0x87658765) MockTokenPool_NotifySuccessfulLockOrBurn {} +struct (0x7adb20bb) MockTokenPool_NotifySuccessfulLockOrBurn {} diff --git a/contracts/contracts/ccip/token_registry/messages.tolk b/contracts/contracts/ccip/token_registry/messages.tolk index a6b4c0862..ead3d1667 100644 --- a/contracts/contracts/ccip/token_registry/messages.tolk +++ b/contracts/contracts/ccip/token_registry/messages.tolk @@ -8,6 +8,6 @@ struct (0xDD5D5127) TokenRegistry_GetTokenInfo { } // Outgoing messages -struct (0xB8F88A81) TokenRegistry_ReturnTokenInfo { +struct (0xddccddb5) TokenRegistry_ReturnTokenInfo { tokenInfo: TokenRegistry_TokenInfo, } diff --git a/contracts/wrappers/ccip/CCIPSendExecutor.ts b/contracts/wrappers/ccip/CCIPSendExecutor.ts index 4c20a4a61..6c0c0bc10 100644 --- a/contracts/wrappers/ccip/CCIPSendExecutor.ts +++ b/contracts/wrappers/ccip/CCIPSendExecutor.ts @@ -204,6 +204,8 @@ export const opcodes = { execute: 0xaf3c62b3, messageValidated: fq.opcodes.out.messageValidated, messageValidationFailed: fq.opcodes.out.messageValidationFailed, + tokenRegistryReturnTokenInfo: 0xddccddb5, + mockTokenPoolNotifySuccessfulLockOrBurn: 0x7adb20bb, }, } diff --git a/contracts/wrappers/ccip/MockTokenPool.ts b/contracts/wrappers/ccip/MockTokenPool.ts index e54cd9ae0..ea60027f2 100644 --- a/contracts/wrappers/ccip/MockTokenPool.ts +++ b/contracts/wrappers/ccip/MockTokenPool.ts @@ -41,3 +41,12 @@ export class MockTokenPool implements Contract { }) } } + +export const opcodes = { + in: { + lockOrBurn: 0x7dd8f942, + }, + out: { + notifySuccessfulLockOrBurn: 0x7adb20bb, + }, +} diff --git a/contracts/wrappers/ccip/OnRamp.ts b/contracts/wrappers/ccip/OnRamp.ts index 9cc2f259c..8d6964294 100644 --- a/contracts/wrappers/ccip/OnRamp.ts +++ b/contracts/wrappers/ccip/OnRamp.ts @@ -651,6 +651,7 @@ export const opcodes = { get messageValidationFailed() { return fq.opcodes.out.messageValidationFailed }, + executorRequestsLockOrBurn: 0x9be1fb61, executorFinishedSuccessfully: 0xcfa6b336, executorFinishedWithError: 0xc4068e21, setDynamicConfig: 0xa178c62e, diff --git a/contracts/wrappers/ccip/Router.ts b/contracts/wrappers/ccip/Router.ts index 19118aabb..a62e51c7f 100644 --- a/contracts/wrappers/ccip/Router.ts +++ b/contracts/wrappers/ccip/Router.ts @@ -72,6 +72,7 @@ export const opcodes = { messageSent: 0x6513f8e1, messageRejected: 0x8ae25114, getValidatedFee: 0x4dd6aa82, + lockOrBurn: 0x6f2d00df, rmnOwnableMessage: 0xaf7a9ac6, }, out: { diff --git a/contracts/wrappers/ccip/TokenRegistry.ts b/contracts/wrappers/ccip/TokenRegistry.ts index a574cc207..01f99b65a 100644 --- a/contracts/wrappers/ccip/TokenRegistry.ts +++ b/contracts/wrappers/ccip/TokenRegistry.ts @@ -58,3 +58,9 @@ export class TokenRegistry implements Contract { }) } } + +export const opcodes = { + out: { + returnTokenInfo: 0xddccddb5, + }, +} diff --git a/contracts/wrappers/gen/ccip/CCIPSendExecutor.ts b/contracts/wrappers/gen/ccip/CCIPSendExecutor.ts index 3a41d7b76..aeed5c22b 100644 --- a/contracts/wrappers/gen/ccip/CCIPSendExecutor.ts +++ b/contracts/wrappers/gen/ccip/CCIPSendExecutor.ts @@ -277,18 +277,21 @@ export const CCIPSendExecutor_Data = { > struct CCIPSendExecutor_Addresses { > onramp: address > feeQuoter: address + > tokenRegistry: address? > } */ export interface CCIPSendExecutor_Addresses { readonly $: 'CCIPSendExecutor_Addresses' onramp: c.Address feeQuoter: c.Address + tokenRegistry: c.Address | null } export const CCIPSendExecutor_Addresses = { create(args: { onramp: c.Address feeQuoter: c.Address + tokenRegistry: c.Address | null }): CCIPSendExecutor_Addresses { return { $: 'CCIPSendExecutor_Addresses', @@ -300,11 +303,13 @@ export const CCIPSendExecutor_Addresses = { $: 'CCIPSendExecutor_Addresses', onramp: s.loadAddress(), feeQuoter: s.loadAddress(), + tokenRegistry: s.loadMaybeAddress(), } }, store(self: CCIPSendExecutor_Addresses, b: c.Builder): void { b.storeAddress(self.onramp); b.storeAddress(self.feeQuoter); + b.storeAddress(self.tokenRegistry); }, toCell(self: CCIPSendExecutor_Addresses): c.Cell { return makeCellFrom(self, CCIPSendExecutor_Addresses.store); @@ -312,32 +317,44 @@ export const CCIPSendExecutor_Addresses = { } /** - > type CCIPSendExecutor_State = Cell | Cell | Cell + > type CCIPSendExecutor_State = Cell | Cell | Cell | Cell | Cell */ export type CCIPSendExecutor_State = | { $: 'Cell', value: CellRef } | { $: 'Cell', value: CellRef } + | { $: 'Cell', value: CellRef } + | { $: 'Cell', value: CellRef } | { $: 'Cell', value: CellRef } export const CCIPSendExecutor_State = { fromSlice(s: c.Slice): CCIPSendExecutor_State { - return lookupPrefixAndEat(s, 0b00, 2) ? { $: 'Cell', value: loadCellRef(s, CCIPSendExecutor_State_Initialized.fromSlice) } : - lookupPrefixAndEat(s, 0b01, 2) ? { $: 'Cell', value: loadCellRef(s, CCIPSendExecutor_State_OnGoingFeeValidation.fromSlice) } : - lookupPrefixAndEat(s, 0b10, 2) ? { $: 'Cell', value: loadCellRef(s, CCIPSendExecutor_State_Finalized.fromSlice) } : + return lookupPrefixAndEat(s, 0b000, 3) ? { $: 'Cell', value: loadCellRef(s, CCIPSendExecutor_State_Initialized.fromSlice) } : + lookupPrefixAndEat(s, 0b001, 3) ? { $: 'Cell', value: loadCellRef(s, CCIPSendExecutor_State_OnGoingFeeValidation.fromSlice) } : + lookupPrefixAndEat(s, 0b010, 3) ? { $: 'Cell', value: loadCellRef(s, CCIPSendExecutor_State_TokenRegistryAccess.fromSlice) } : + lookupPrefixAndEat(s, 0b011, 3) ? { $: 'Cell', value: loadCellRef(s, CCIPSendExecutor_State_TokenTransfer.fromSlice) } : + lookupPrefixAndEat(s, 0b100, 3) ? { $: 'Cell', value: loadCellRef(s, CCIPSendExecutor_State_Finalized.fromSlice) } : throwNonePrefixMatch('CCIPSendExecutor_State'); }, store(self: CCIPSendExecutor_State, b: c.Builder): void { switch (self.$) { case 'Cell': - b.storeUint(0b00, 2); + b.storeUint(0b000, 3); storeCellRef(self.value, b, CCIPSendExecutor_State_Initialized.store); break; case 'Cell': - b.storeUint(0b01, 2); + b.storeUint(0b001, 3); storeCellRef(self.value, b, CCIPSendExecutor_State_OnGoingFeeValidation.store); break; + case 'Cell': + b.storeUint(0b010, 3); + storeCellRef(self.value, b, CCIPSendExecutor_State_TokenRegistryAccess.store); + break; + case 'Cell': + b.storeUint(0b011, 3); + storeCellRef(self.value, b, CCIPSendExecutor_State_TokenTransfer.store); + break; case 'Cell': - b.storeUint(0b10, 2); + b.storeUint(0b100, 3); storeCellRef(self.value, b, CCIPSendExecutor_State_Finalized.store); break; } @@ -399,6 +416,77 @@ export const CCIPSendExecutor_State_OnGoingFeeValidation = { } } +/** + > struct CCIPSendExecutor_State_TokenRegistryAccess { + > fee: Fee + > } + */ +export interface CCIPSendExecutor_State_TokenRegistryAccess { + readonly $: 'CCIPSendExecutor_State_TokenRegistryAccess' + fee: Fee +} + +export const CCIPSendExecutor_State_TokenRegistryAccess = { + create(args: { + fee: Fee + }): CCIPSendExecutor_State_TokenRegistryAccess { + return { + $: 'CCIPSendExecutor_State_TokenRegistryAccess', + ...args + } + }, + fromSlice(s: c.Slice): CCIPSendExecutor_State_TokenRegistryAccess { + return { + $: 'CCIPSendExecutor_State_TokenRegistryAccess', + fee: Fee.fromSlice(s), + } + }, + store(self: CCIPSendExecutor_State_TokenRegistryAccess, b: c.Builder): void { + Fee.store(self.fee, b); + }, + toCell(self: CCIPSendExecutor_State_TokenRegistryAccess): c.Cell { + return makeCellFrom(self, CCIPSendExecutor_State_TokenRegistryAccess.store); + } +} + +/** + > struct CCIPSendExecutor_State_TokenTransfer { + > tokenPool: address + > fee: Fee + > } + */ +export interface CCIPSendExecutor_State_TokenTransfer { + readonly $: 'CCIPSendExecutor_State_TokenTransfer' + tokenPool: c.Address + fee: Fee +} + +export const CCIPSendExecutor_State_TokenTransfer = { + create(args: { + tokenPool: c.Address + fee: Fee + }): CCIPSendExecutor_State_TokenTransfer { + return { + $: 'CCIPSendExecutor_State_TokenTransfer', + ...args + } + }, + fromSlice(s: c.Slice): CCIPSendExecutor_State_TokenTransfer { + return { + $: 'CCIPSendExecutor_State_TokenTransfer', + tokenPool: s.loadAddress(), + fee: Fee.fromSlice(s), + } + }, + store(self: CCIPSendExecutor_State_TokenTransfer, b: c.Builder): void { + b.storeAddress(self.tokenPool); + Fee.store(self.fee, b); + }, + toCell(self: CCIPSendExecutor_State_TokenTransfer): c.Cell { + return makeCellFrom(self, CCIPSendExecutor_State_TokenTransfer.store); + } +} + /** > struct CCIPSendExecutor_State_Finalized { > } @@ -428,16 +516,19 @@ export const CCIPSendExecutor_State_Finalized = { /** > struct CCIPSendExecutor_Config { > feeQuoter: address + > tokenRegistry: address? > } */ export interface CCIPSendExecutor_Config { readonly $: 'CCIPSendExecutor_Config' feeQuoter: c.Address + tokenRegistry: c.Address | null } export const CCIPSendExecutor_Config = { create(args: { feeQuoter: c.Address + tokenRegistry: c.Address | null }): CCIPSendExecutor_Config { return { $: 'CCIPSendExecutor_Config', @@ -448,10 +539,12 @@ export const CCIPSendExecutor_Config = { return { $: 'CCIPSendExecutor_Config', feeQuoter: s.loadAddress(), + tokenRegistry: s.loadMaybeAddress(), } }, store(self: CCIPSendExecutor_Config, b: c.Builder): void { b.storeAddress(self.feeQuoter); + b.storeAddress(self.tokenRegistry); }, toCell(self: CCIPSendExecutor_Config): c.Cell { return makeCellFrom(self, CCIPSendExecutor_Config.store); @@ -626,6 +719,58 @@ export const OnRamp_Send = { } } +/** + > struct (0x9be1fb61) OnRamp_ExecutorRequestsLockOrBurn { + > tokenAmount: TokenAmount + > tokenPool: address + > destChainSelector: uint64 + > executorID: CCIPSendExecutor_ID + > } + */ +export interface OnRamp_ExecutorRequestsLockOrBurn { + readonly $: 'OnRamp_ExecutorRequestsLockOrBurn' + tokenAmount: TokenAmount + tokenPool: c.Address + destChainSelector: uint64 + executorID: CCIPSendExecutor_ID +} + +export const OnRamp_ExecutorRequestsLockOrBurn = { + PREFIX: 0x9be1fb61, + + create(args: { + tokenAmount: TokenAmount + tokenPool: c.Address + destChainSelector: uint64 + executorID: CCIPSendExecutor_ID + }): OnRamp_ExecutorRequestsLockOrBurn { + return { + $: 'OnRamp_ExecutorRequestsLockOrBurn', + ...args + } + }, + fromSlice(s: c.Slice): OnRamp_ExecutorRequestsLockOrBurn { + loadAndCheckPrefix32(s, 0x9be1fb61, 'OnRamp_ExecutorRequestsLockOrBurn'); + return { + $: 'OnRamp_ExecutorRequestsLockOrBurn', + tokenAmount: TokenAmount.fromSlice(s), + tokenPool: s.loadAddress(), + destChainSelector: s.loadUintBig(64), + executorID: CCIPSendExecutor_ID.fromSlice(s), + } + }, + store(self: OnRamp_ExecutorRequestsLockOrBurn, b: c.Builder): void { + b.storeUint(0x9be1fb61, 32); + TokenAmount.store(self.tokenAmount, b); + b.storeAddress(self.tokenPool); + b.storeUint(self.destChainSelector, 64); + CCIPSendExecutor_ID.store(self.executorID, b); + }, + toCell(self: OnRamp_ExecutorRequestsLockOrBurn): c.Cell { + return makeCellFrom(self, OnRamp_ExecutorRequestsLockOrBurn.store); + } +} + /** > struct (0xcfa6b336) OnRamp_ExecutorFinishedSuccessfully { > executorID: CCIPSendExecutor_ID @@ -857,44 +1002,6 @@ export const Fee = { } } -/** - > struct Metadata { - > sender: address - > value: coins - > } - */ -export interface Metadata { - readonly $: 'Metadata' - sender: c.Address - value: coins -} - -export const Metadata = { - create(args: { - sender: c.Address - value: coins - }): Metadata { - return { - $: 'Metadata', - ...args - } - }, - fromSlice(s: c.Slice): Metadata { - return { - $: 'Metadata', - sender: s.loadAddress(), - value: s.loadCoins(), - } - }, - store(self: Metadata, b: c.Builder): void { - b.storeAddress(self.sender); - b.storeCoins(self.value); - }, - toCell(self: Metadata): c.Cell { - return makeCellFrom(self, Metadata.store); - } -} - /** > type CrossChainAddress = slice */ @@ -1103,6 +1210,184 @@ export const TokenAmount = { } } +/** + > struct (0xdd5d5127) TokenRegistry_GetTokenInfo { + > } + */ +export interface TokenRegistry_GetTokenInfo { + readonly $: 'TokenRegistry_GetTokenInfo' +} + +export const TokenRegistry_GetTokenInfo = { + PREFIX: 0xdd5d5127, + + create(): TokenRegistry_GetTokenInfo { + return { + $: 'TokenRegistry_GetTokenInfo', + } + }, + fromSlice(s: c.Slice): TokenRegistry_GetTokenInfo { + loadAndCheckPrefix32(s, 0xdd5d5127, 'TokenRegistry_GetTokenInfo'); + return { + $: 'TokenRegistry_GetTokenInfo', + } + }, + store(self: TokenRegistry_GetTokenInfo, b: c.Builder): void { + b.storeUint(0xdd5d5127, 32); + }, + toCell(self: TokenRegistry_GetTokenInfo): c.Cell { + return makeCellFrom(self, TokenRegistry_GetTokenInfo.store); + } +} + +/** + > struct (0xddccddb5) TokenRegistry_ReturnTokenInfo { + > tokenInfo: TokenRegistry_TokenInfo + > } + */ +export interface TokenRegistry_ReturnTokenInfo { + readonly $: 'TokenRegistry_ReturnTokenInfo' + tokenInfo: TokenRegistry_TokenInfo +} + +export const TokenRegistry_ReturnTokenInfo = { + PREFIX: 0xddccddb5, + + create(args: { + tokenInfo: TokenRegistry_TokenInfo + }): TokenRegistry_ReturnTokenInfo { + return { + $: 'TokenRegistry_ReturnTokenInfo', + ...args + } + }, + fromSlice(s: c.Slice): TokenRegistry_ReturnTokenInfo { + loadAndCheckPrefix32(s, 0xddccddb5, 'TokenRegistry_ReturnTokenInfo'); + return { + $: 'TokenRegistry_ReturnTokenInfo', + tokenInfo: TokenRegistry_TokenInfo.fromSlice(s), + } + }, + store(self: TokenRegistry_ReturnTokenInfo, b: c.Builder): void { + b.storeUint(0xddccddb5, 32); + TokenRegistry_TokenInfo.store(self.tokenInfo, b); + }, + toCell(self: TokenRegistry_ReturnTokenInfo): c.Cell { + return makeCellFrom(self, TokenRegistry_ReturnTokenInfo.store); + } +} + +/** + > struct (0x7adb20bb) MockTokenPool_NotifySuccessfulLockOrBurn { + > } + */ +export interface MockTokenPool_NotifySuccessfulLockOrBurn { + readonly $: 'MockTokenPool_NotifySuccessfulLockOrBurn' +} + +export const MockTokenPool_NotifySuccessfulLockOrBurn = { + PREFIX: 0x7adb20bb, + + create(): MockTokenPool_NotifySuccessfulLockOrBurn { + return { + $: 'MockTokenPool_NotifySuccessfulLockOrBurn', + } + }, + fromSlice(s: c.Slice): MockTokenPool_NotifySuccessfulLockOrBurn { + loadAndCheckPrefix32(s, 0x7adb20bb, 'MockTokenPool_NotifySuccessfulLockOrBurn'); + return { + $: 'MockTokenPool_NotifySuccessfulLockOrBurn', + } + }, + store(self: MockTokenPool_NotifySuccessfulLockOrBurn, b: c.Builder): void { + b.storeUint(0x7adb20bb, 32); + }, + toCell(self: MockTokenPool_NotifySuccessfulLockOrBurn): c.Cell { + return makeCellFrom(self, MockTokenPool_NotifySuccessfulLockOrBurn.store); + } +} + +/** + > struct Metadata { + > sender: address + > value: coins + > } + */ +export interface Metadata { + readonly $: 'Metadata' + sender: c.Address + value: coins +} + +export const Metadata = { + create(args: { + sender: c.Address + value: coins + }): Metadata { + return { + $: 'Metadata', + ...args + } + }, + fromSlice(s: c.Slice): Metadata { + return { + $: 'Metadata', + sender: s.loadAddress(), + value: s.loadCoins(), + } + }, + store(self: Metadata, b: c.Builder): void { + b.storeAddress(self.sender); + b.storeCoins(self.value); + }, + toCell(self: Metadata): c.Cell { + return makeCellFrom(self, Metadata.store); + } +} + +/** + > struct TokenRegistry_TokenInfo { + > tokenPool: address + > minterAddress: address + > enabled: bool + > } + */ +export interface TokenRegistry_TokenInfo { + readonly $: 'TokenRegistry_TokenInfo' + tokenPool: c.Address + minterAddress: c.Address + enabled: boolean +} + +export const TokenRegistry_TokenInfo = { + create(args: { + tokenPool: c.Address + minterAddress: c.Address + enabled: boolean + }): TokenRegistry_TokenInfo { + return { + $: 'TokenRegistry_TokenInfo', + ...args + } + }, + fromSlice(s: c.Slice): TokenRegistry_TokenInfo { + return { + $: 'TokenRegistry_TokenInfo', + tokenPool: s.loadAddress(), + minterAddress: s.loadAddress(), + enabled: s.loadBoolean(), + } + }, + store(self: TokenRegistry_TokenInfo, b: c.Builder): void { + b.storeAddress(self.tokenPool); + b.storeAddress(self.minterAddress); + b.storeBit(self.enabled); + }, + toCell(self: TokenRegistry_TokenInfo): c.Cell { + return makeCellFrom(self, TokenRegistry_TokenInfo.store); + } +} + // ———————————————————————————————————————————— // class CCIPSendExecutor // @@ -1142,12 +1427,15 @@ function calculateDeployedAddress(code: c.Cell, data: c.Cell, options: DeployedA } export class CCIPSendExecutor implements c.Contract { - static CodeCell = c.Cell.fromBase64('te6ccgECFwEAA+cAART/APSkE/S88sgLAQIBYgIDAgLPBAUCAUgTFARdPiRjo/THzHXLCOkt/q0MeMC8j/gINcsJXnjFZzjAtcsIP0wG6TjAtcsJeeFWHyAGBwgJA/cW4IJMS0AggnZBcCCEAVdSoCCEATjOICCC8FNwLYJoKCgIqAlvOMC+ACIVHh2U4cEyMvfz5Nz5k8KE8z6UgH6AszPhoDMye1UI9D6SPpIMdHIz5M+mszaKc8L31AD+gLLXybPFFJQ+lIk+gLJyM+FiBL6UnHPC27MyYMGgEBIRA/ztRNDT39csJufMnhTyv9T6SPoA1NcsAZQwgQCHjhXXLAOUMIEAiJvXLAUxkvI/4YEAieLigUWIgQCIWLry9IhUdUNTVATIy9/Pk3PmTwoTzPpSAfoCzM+GgMzJ7VTQ+kj6SDHRyM+TEBo4hhXL34FFjM8L/xPM+lIB+gLJyIkSCgsC/jHXLCbnzJ4U8r/U+kj6ANdM0PpI0e1E0PpI1wvfAcj6UhL6UsmBRYn4kvgoxwXy9IFFi/iXghAFXUqAghAE4ziAggvBTcC2CaC+8vQg0PpIMfpI0YIQBBzbQIsIyM+R0lv9WijPFM7JyM+FiBP6UgH6AnHPC2rMyXH7AIhUclQSDADOMe1E0NPf1ywm58yeFPK/1PpI+gDU1ywBlddMgQCHjhfXLAOV10yBAIic1ywFkvI/4ddMgQCJ4uKBRYiBAIhYuvL0gUWJItD6SDH6SNH4kscF8vQG+gDTX9QQiRB4EGcQVhBF8AFfBgEU4wIwhA8BxwDy9A0AAWIAHs8WEvpScc8LbszJgwb7AAA+JjY2NjYFyMvfz5Nz5k8KFMwS+lIB+gLMz4WAzMntVAP+Me1E0NPf1ywm58yeFPK/1PpI+gDU1ywBlDCBAIeOFdcsA5QwgQCIm9csBTGS8j/hgQCJ4uKBRYiBAIhYuvL0gUWJIdD6SDH6SNH4kscF8vQF1wv/iFR1Q1NZBMjL38+Tc+ZPChPM+lIB+gLMz4aAzMntVCXQNgX6SPpIMdHIiRIODwAIxAaOIQBWzxYlzwvfNVBUy/8izxQyUgL6UjEi+gJsEsnIz4WIEvpScc8LbszJgwb7AAGqW4hUdlRTZQTIy9/Pk3PmTwoTzPpSAfoCzM+GgMzJ7VQh0PpI+kgx0cjPkxAaOIYnzwvfgUWKzwv/Js8UUlD6UiT6AsnIz4WIEvpScc8LbszJgwb7ABIABPsAAAACASAVFgALuGhYEAsoAGG2K/GhI2NLc1lzG0MLS3Fzo3txcxsbS4FyGhpKgpsrcyIrwysbq6N7lBFqYlxsXGMQABm1xRAosRQEEIH3flCQ'); + static CodeCell = c.Cell.fromBase64('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'); static Errors = { + 'Common_Error.CrossChainAddressOutOfRange': 5, + 'Utils_Error.InvalidData': 13500, 'CCIPSendExecutor_Error.StateNotExpected': 17800, 'CCIPSendExecutor_Error.Unauthorized': 17801, 'CCIPSendExecutor_Error.InsufficientFee': 17803, + 'CCIPSendExecutor_Error.TokenNotEnabled': 17805, } readonly address: c.Address @@ -1218,6 +1506,17 @@ export class CCIPSendExecutor implements c.Contract { ); } + static createCellOfTokenRegistryReturnTokenInfo(body: { + tokenInfo: TokenRegistry_TokenInfo + }) { + return TokenRegistry_ReturnTokenInfo.toCell(TokenRegistry_ReturnTokenInfo.create(body)); + } + + static createCellOfMockTokenPoolNotifySuccessfulLockOrBurn(body: { + }) { + return MockTokenPool_NotifySuccessfulLockOrBurn.toCell(MockTokenPool_NotifySuccessfulLockOrBurn.create()); + } + async sendDeploy(provider: ContractProvider, via: Sender, msgValue: coins, extraOptions?: ExtraSendOptions) { return provider.internal(via, { value: msgValue, @@ -1271,6 +1570,25 @@ export class CCIPSendExecutor implements c.Contract { }); } + async sendTokenRegistryReturnTokenInfo(provider: ContractProvider, via: Sender, msgValue: coins, body: { + tokenInfo: TokenRegistry_TokenInfo + }, extraOptions?: ExtraSendOptions) { + return provider.internal(via, { + value: msgValue, + body: TokenRegistry_ReturnTokenInfo.toCell(TokenRegistry_ReturnTokenInfo.create(body)), + ...extraOptions + }); + } + + async sendMockTokenPoolNotifySuccessfulLockOrBurn(provider: ContractProvider, via: Sender, msgValue: coins, body: { + }, extraOptions?: ExtraSendOptions) { + return provider.internal(via, { + value: msgValue, + body: MockTokenPool_NotifySuccessfulLockOrBurn.toCell(MockTokenPool_NotifySuccessfulLockOrBurn.create()), + ...extraOptions + }); + } + async getTypeAndVersion(provider: ContractProvider): Promise<[ c.Slice, c.Slice, diff --git a/contracts/wrappers/gen/ccip/FeeQuoter.ts b/contracts/wrappers/gen/ccip/FeeQuoter.ts index dbcab4859..82a0a86d9 100644 --- a/contracts/wrappers/gen/ccip/FeeQuoter.ts +++ b/contracts/wrappers/gen/ccip/FeeQuoter.ts @@ -1955,7 +1955,7 @@ function calculateDeployedAddress(code: c.Cell, data: c.Cell, options: DeployedA } export class FeeQuoter 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, @@ -1965,7 +1965,6 @@ export class FeeQuoter implements c.Contract { 'FeeQuoter_Error.GasLimitTooHigh': 34401, 'FeeQuoter_Error.ExtraArgOutOfOrderExecutionMustBeTrue': 34402, 'FeeQuoter_Error.InvalidExtraArgsData': 34403, - 'FeeQuoter_Error.UnsupportedNumberOfTokens': 34404, 'FeeQuoter_Error.InvalidSuiReceiverAddress': 34407, 'FeeQuoter_Error.InvalidSVMReceiverAddress': 34408, 'FeeQuoter_Error.TooManySuiExtraArgsReceiverObjectIds': 34410, diff --git a/contracts/wrappers/gen/ccip/OnRamp.ts b/contracts/wrappers/gen/ccip/OnRamp.ts index 4cf96d8fe..9347d75c4 100644 --- a/contracts/wrappers/gen/ccip/OnRamp.ts +++ b/contracts/wrappers/gen/ccip/OnRamp.ts @@ -1058,6 +1058,58 @@ export const Router_MessageRejected = { } } +/** + > struct (0x6f2d00df) Router_LockOrBurn { + > tokenPool: address + > tokenAmount: TokenAmount + > destChainSelector: uint64 + > executorAddress: address + > } + */ +export interface Router_LockOrBurn { + readonly $: 'Router_LockOrBurn' + tokenPool: c.Address + tokenAmount: TokenAmount + destChainSelector: uint64 + executorAddress: c.Address +} + +export const Router_LockOrBurn = { + PREFIX: 0x6f2d00df, + + create(args: { + tokenPool: c.Address + tokenAmount: TokenAmount + destChainSelector: uint64 + executorAddress: c.Address + }): Router_LockOrBurn { + return { + $: 'Router_LockOrBurn', + ...args + } + }, + fromSlice(s: c.Slice): Router_LockOrBurn { + loadAndCheckPrefix32(s, 0x6f2d00df, 'Router_LockOrBurn'); + return { + $: 'Router_LockOrBurn', + tokenPool: s.loadAddress(), + tokenAmount: TokenAmount.fromSlice(s), + destChainSelector: s.loadUintBig(64), + executorAddress: s.loadAddress(), + } + }, + store(self: Router_LockOrBurn, b: c.Builder): void { + b.storeUint(0x6f2d00df, 32); + b.storeAddress(self.tokenPool); + TokenAmount.store(self.tokenAmount, b); + b.storeUint(self.destChainSelector, 64); + b.storeAddress(self.executorAddress); + }, + toCell(self: Router_LockOrBurn): c.Cell { + return makeCellFrom(self, Router_LockOrBurn.store); + } +} + /** > struct (0x7496ff56) FeeQuoter_GetValidatedFee { > msg: Cell @@ -1633,7 +1685,7 @@ export const TVM2AnyRampMessage = { > receiver: Cell > data: cell > extraArgs: cell - > tokenAmounts: cell + > tokenAmounts: SnakedCell > feeToken: address > feeTokenAmount: uint256 > } @@ -1643,7 +1695,7 @@ export interface TVM2AnyRampMessageBody { receiver: CellRef data: c.Cell extraArgs: c.Cell - tokenAmounts: c.Cell + tokenAmounts: SnakedCell feeToken: c.Address feeTokenAmount: uint256 } @@ -1653,7 +1705,7 @@ export const TVM2AnyRampMessageBody = { receiver: CellRef data: c.Cell extraArgs: c.Cell - tokenAmounts: c.Cell + tokenAmounts: SnakedCell feeToken: c.Address feeTokenAmount: uint256 }): TVM2AnyRampMessageBody { @@ -1694,6 +1746,7 @@ export const TVM2AnyRampMessageBody = { > config: Cell > destChainConfigs: map > executor: ExecutorDeployment + > tokenRegistry: address? > } */ export interface OnRamp_Storage { @@ -1704,6 +1757,7 @@ export interface OnRamp_Storage { config: CellRef destChainConfigs: c.Dictionary executor: ExecutorDeployment + tokenRegistry: c.Address | null } export const OnRamp_Storage = { @@ -1714,6 +1768,7 @@ export const OnRamp_Storage = { config: CellRef destChainConfigs: c.Dictionary executor: ExecutorDeployment + tokenRegistry: c.Address | null }): OnRamp_Storage { return { $: 'OnRamp_Storage', @@ -1729,6 +1784,7 @@ export const OnRamp_Storage = { config: loadCellRef(s, OnRamp_DynamicConfig.fromSlice), destChainConfigs: c.Dictionary.load(c.Dictionary.Keys.BigUint(64), createDictionaryValue(OnRamp_DestChainConfig.fromSlice, OnRamp_DestChainConfig.store), s), executor: ExecutorDeployment.fromSlice(s), + tokenRegistry: s.loadMaybeAddress(), } }, store(self: OnRamp_Storage, b: c.Builder): void { @@ -1738,6 +1794,7 @@ export const OnRamp_Storage = { storeCellRef(self.config, b, OnRamp_DynamicConfig.store); b.storeDict(self.destChainConfigs, c.Dictionary.Keys.BigUint(64), createDictionaryValue(OnRamp_DestChainConfig.fromSlice, OnRamp_DestChainConfig.store)); ExecutorDeployment.store(self.executor, b); + b.storeAddress(self.tokenRegistry); }, toCell(self: OnRamp_Storage): c.Cell { return makeCellFrom(self, OnRamp_Storage.store); @@ -1812,6 +1869,58 @@ export const OnRamp_GetValidatedFee = { }, } +/** + > struct (0x9be1fb61) OnRamp_ExecutorRequestsLockOrBurn { + > tokenAmount: TokenAmount + > tokenPool: address + > destChainSelector: uint64 + > executorID: CCIPSendExecutor_ID + > } + */ +export interface OnRamp_ExecutorRequestsLockOrBurn { + readonly $: 'OnRamp_ExecutorRequestsLockOrBurn' + tokenAmount: TokenAmount + tokenPool: c.Address + destChainSelector: uint64 + executorID: CCIPSendExecutor_ID +} + +export const OnRamp_ExecutorRequestsLockOrBurn = { + PREFIX: 0x9be1fb61, + + create(args: { + tokenAmount: TokenAmount + tokenPool: c.Address + destChainSelector: uint64 + executorID: CCIPSendExecutor_ID + }): OnRamp_ExecutorRequestsLockOrBurn { + return { + $: 'OnRamp_ExecutorRequestsLockOrBurn', + ...args + } + }, + fromSlice(s: c.Slice): OnRamp_ExecutorRequestsLockOrBurn { + loadAndCheckPrefix32(s, 0x9be1fb61, 'OnRamp_ExecutorRequestsLockOrBurn'); + return { + $: 'OnRamp_ExecutorRequestsLockOrBurn', + tokenAmount: TokenAmount.fromSlice(s), + tokenPool: s.loadAddress(), + destChainSelector: s.loadUintBig(64), + executorID: CCIPSendExecutor_ID.fromSlice(s), + } + }, + store(self: OnRamp_ExecutorRequestsLockOrBurn, b: c.Builder): void { + b.storeUint(0x9be1fb61, 32); + TokenAmount.store(self.tokenAmount, b); + b.storeAddress(self.tokenPool); + b.storeUint(self.destChainSelector, 64); + CCIPSendExecutor_ID.store(self.executorID, b); + }, + toCell(self: OnRamp_ExecutorRequestsLockOrBurn): c.Cell { + return makeCellFrom(self, OnRamp_ExecutorRequestsLockOrBurn.store); + } +} + /** > struct OnRamp_GetValidatedFeeContext { > onrampContext: address @@ -2236,7 +2345,7 @@ function calculateDeployedAddress(code: c.Cell, data: c.Cell, options: DeployedA } export class OnRamp implements c.Contract { - static CodeCell = c.Cell.fromBase64('te6ccgECRQEAC9MAART/APSkE/S88sgLAQIBYgIDAgLGIiMCASAEBQIBIAYHAgEgFBUCASAICQIBIA4PAgFYCgsCASAMDQBNrK/Gg02NLc1lzG0MLS3Fzo3txcxsbS4Fye3KTC2uEEWpiXGxcYxAAJmugXaiaGmPmP0kGP0oGOmfmOoY+gLAmiwswCB6BzfQiXl6fSQY6Z+Y6QAY+gJotpDAgIX6QTfSmUiAzykBN4EoiUCAhfo6N9KZdBgYwAAZs4ogTRYoCCED7vyhIABfsVX7UTQ0x8x+kgx+lAx0z8x1DH0BYE0WFmAQPQOb6ES8vT6SDHTP9IAMfQEMdGkgAgJxEBECASASEwAVpjvaiaGmPmP0kGEACaULAgENACOwNDtRNDTHzH6SDH6UDHXCz+AAHbK6+1E0NMfMfpIMfpQMIAAruFDTDtRNDXTND6SPpIMfpIMfoAMdGAIBIBYXAgFIGBkCASAaGwApr2Z2omhrpmh9JBj9JBj9JBj9AGjAACOs0vaiaGumaH0kfSR9JH0AaMACAUgcHQIBSB4fADaoee1E0NMfMfpIMfpQMdM/MdQx9AHUMddM+QAAVqvl7UTQ0x8x+kgx+lAx0z8x1DH0BYE0WFmAQPQOb6ES8vT6SNM/0gD0BNEAOKru7UTQ0x8x+kgx+lAx0z8x1DH0BYBA9A5voTECAVggIQAxoRu1E0NMfMfpIMfpQMdM/MdQx9AHUMddMgBhoJ+1E0NMfMfpIMfpQMdM/MdQx9AVtIYBA9IZvpTKRAZ1SAm8CURKAQPR8b6Uy6DAxgIBzyQlAgOj0kNEAgEgJicB9U7aLt+zUDjmxSIoEBC/QKb6GzkjB/ltIA0bPDAOKOUzJsYzMzAtDXLCGLtGys8r/TP9M/0wchwUHyhQGqAtcYMdQx1DH6UDHUMdHIz5IriURSEss/yz/6UoE0Ws8L/8nIz4UIEvpScc8LbszJgED7ANsx4DOSNDDiJtCEEEyz4kfJAINcsJOFmY/SONDHU+JLtRNDXTND6SPpIMfpIMfoAMdHIz5HSW/1aFMz6Us7JyM+FiBL6UnHPC27MyYBA+wDg1ywg/TAbpOMC1ywl54VYfOMC1ywm58yeFOMC1ywmfTWZtICgpKisBqTtou371ywnkNvtDI5E1ywnzxTyVJRbcNsx4YIAwoojbrPy9CGCAMKKBMcFE/L0IG0D1ws/iwIByMs/FfpSEvpSycjPhyAUznHPC2ETzMlw+wDjDX+BAAIwx7UTQ10zQ+kj6SDH6SDH6ADHRgTRZ+JJYxwXy9PoA018x1PpIyM+Qq+xG9lAE+gISzBLOycjPhQgS+lJxzwtuzMmAQPsAAIQx7UTQ10zQ+kj6SDH6SDH6ADHRgTRZ+JJYxwXy9NP/1PpIyM+SsHdEuhTL/xLMEs7JyM+FCBL6UnHPC27MyYBA+wAB/jHtRNAB1PpI+gAwItDXLCGLtGys8r/TP9M/0wchwUHyhQGqAtcYMdQx1DH6UDHUMdEF0x/6SPpQ0z/U9ATU10xTwoBA9A5voY4vEJpfCjL4ksjPkiuJRFITyz8Tyz8S+lKBNFjPC//JyM+FCBL6UnHPC27MyYBA+wDhOTwH+kgsBDbjAtcsJiA0cQzjAtcsJQvGMXTjAtcsINEjW2QtLi8wAELTP9IA9ATRgTRZ+JIlxwXy9BCeEI0QfBBrEFoQSVUl8AIB/DHtRNAB09/6ANNf1PpIMAXTH/pI+lDTP9T0BNTXTIE0WfgoyPpSz5AAAAACHcvfySLIz4TQzMz5FsjPigBAy//PUPiSxwUc8vQH0NcsIYu0bKzyv9M/0z/TByHBQfKFAaoC1xjU1PpQ1NGBNFhTaIBA9A5voRLy9PpI0z/SADEB/jHtRNAB09/T/9T6SDAE0x8x+kgx+lAx0z8x1DH0BNdMgTRZ+CjI+lLPkAAAAAIWy9/JAcjPhNDMzPkWyM+KAEDL/89Q+JLHBRTy9NDXLCGLtGys8r/TP9M/0wchwUHyhQGqAtcYMdQx1DH6UDHUMdEggTRYBYBA9A5voRXy9AM1AO4x7UTQ0x/6SPpQ0z/UMfQE1NdM+JKCAMKIURfHBfL0B/pI+kj6SPoAMCPI+lJSMPpSUiD6UiH6AsknyMs/FfpSE/pS+lIB+gLJyM+PGAAEghAeMiIszwv3cc8LYczJcPsABsjLHxX6UhP6VMs/E8wS9ADMzMntVAS0jr4x7UTQ0x/6SPpQ0z/U9ATU10z4koIAwohRGMcF8vQI10zQlCDHALOK6DAGyMsfFfpSE/pUyz/M9ADMzMntVODXLCTuAwws4wLXLCQUgOIs4wLXLCOCluOsNjc4OQP89ATRAqQjyPpSIc8LPxLKABL0AFQgi4BA9EMOyMsfHfpSG/pUKc8LPxjMG/QAG8wdzMntVMgs10kgqTgC8kWrAiDBQfKFzwsHHM7JyMwYzBTMFcwU+lImzwv/yVRzeMiJzxYXyz8qzws/+CgB+lL5FonIzsv/UmD6UiTPCz9wMjM0AEA2ua4DugBaUtwCfe1aLn194qsTivQegpP6SfOLEZ+tdABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAws8LPyPPFPkWIMjL/xPLP8s/E8s/cM8LPxT6UhPMFMtfycjPjxgABIIQpF0pPM8L93HPC2HMyXD7AMjPkZRP44YSyz/L/xPLPxP6UsnIz4UIEvpScc8LbszJAXT7AoMG+wAAYvpI0z8x0gAx9AQx0cjPkiuJRFISyz8Tyz8T+lISy//JyM+FCBL6UnHPC27MyYBA+wAB/iDXSwGRMJuBNLwBwAHy9NdM0OLTP/pI0gBTNYBA9A5voY4j+kgx0z/SADH0BNEkyPpSIs8LPyTPCgBSEPQAVCBpgED0SzCONTBwbSTI+lJwzws/JM8KAFIQ9ABUIGmAQPRDyM+PGAAEghDT0QT/zwv3cM8LYSbPCz/JIvsA4sg6AaQx7UTQ0x/6SPpQ0z/U9ATU10z4kiTQ+kgx+kgx+kj6ADHRxwWc+JKCAMKIURjHBfL03wjXTNCUIMcAs4roMAbIyx8V+lIT+lTLP8z0AMzMye1UPABmMe1E0NYf+kj6UNY/1PQE10z4koIAwohRF8cF8vQH10wGyM4V+lIT+lTOzPQAEszMye1UAu6OwTGBNF34l4IQBU4IQLzy9NdM0IE0XAHHAPL07UTQ10zQ+kgx+kj6SDH6ANFy+wKIyM+FiBL6UnHPC27MyYEAkPsA4NcsIFVAj2zjAjDtRNDWH/pI+lD4kkMwJfABnjQCyM4S+lIS+lTOye1U4F8EhA8BxwDy9D4/AUaJzxaCEDqiXPHPC/dwzwthFss/FPpSE8s/ygAU9ADJcPsAAjsABcYAAQH+INdLAZEwm4E0vAHAAfL010zQ4tM/1NSBNFhTRoBA9A5voRLy9PpI0z/SAPQE0QbQlCDHALOOICDXSwGRMJuBNLwBwAHy9NdM0OL6SMjPg0AIgQEL9EEG6DAE0JQgxwCzjh0g10sBkTCbgTS8AcAB8vTXTNDi+kgGgQEL9FkwBT0AKugwAcj6Uss/EsoAEvQAQASAQPRDAgAAALox7UTQ0x8x+kgw+JKCAMKIAscF8vTTPzHXTJPxA+gAk/ED6QAg2gEj+wQj0O0e7VPtREAT2iHtVCH5AAHaAQLIzMv/zsnIz48YAASCEKM7SY7PC/dxzwthzMlw+wAAZmwS0z/6SDCCAMKIUTTHBRPy9IIAwolTI8cFs/L0IYsCyM+HIM5wzwthEss/EvpSyXD7AAH8+kj6SDH6SDH6ADHR+CX4FfgQqx/4KMj6Us+QAAAAAiHPC9/JJ/goyPpSE8vfyYIQBV1KgIIQBOM4gIILwU3AtgmgBMj6UsnIi4rzxis9z5k8KM8WGMwV+lJQBfoCFczJyM+Sw7FFXibPFBPMAfoCzMnIz4mIAVMjyM+E0MzMQgBS+RbPC/+BAI3PC3QTzMzMyYBA+wAHyMsfFvpSFPpUEss/zPQAzMzJ7VQAHyBTbwBi1MS42LjCMcF8vSAADyLUxLjYuMYg'); + static CodeCell = c.Cell.fromBase64('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'); static Errors = { 'Common_Error.CrossChainAddressOutOfRange': 5, @@ -2281,6 +2390,7 @@ export class OnRamp implements c.Contract { config: CellRef destChainConfigs: c.Dictionary executor: ExecutorDeployment + tokenRegistry: c.Address | null }, deployedOptions?: DeployedAddrOptions) { const initialState = { code: deployedOptions?.overrideContractCode ?? OnRamp.CodeCell, @@ -2334,6 +2444,15 @@ export class OnRamp implements c.Contract { ); } + static createCellOfOnRampExecutorRequestsLockOrBurn(body: { + tokenAmount: TokenAmount + tokenPool: c.Address + destChainSelector: uint64 + executorID: CCIPSendExecutor_ID + }) { + return OnRamp_ExecutorRequestsLockOrBurn.toCell(OnRamp_ExecutorRequestsLockOrBurn.create(body)); + } + static createCellOfOnRampExecutorFinishedSuccessfully(body: { executorID: CCIPSendExecutor_ID fee: Fee @@ -2457,6 +2576,19 @@ export class OnRamp implements c.Contract { }); } + async sendOnRampExecutorRequestsLockOrBurn(provider: ContractProvider, via: Sender, msgValue: coins, body: { + tokenAmount: TokenAmount + tokenPool: c.Address + destChainSelector: uint64 + executorID: CCIPSendExecutor_ID + }, extraOptions?: ExtraSendOptions) { + return provider.internal(via, { + value: msgValue, + body: OnRamp_ExecutorRequestsLockOrBurn.toCell(OnRamp_ExecutorRequestsLockOrBurn.create(body)), + ...extraOptions + }); + } + async sendOnRampExecutorFinishedSuccessfully(provider: ContractProvider, via: Sender, msgValue: coins, body: { executorID: CCIPSendExecutor_ID fee: Fee diff --git a/contracts/wrappers/gen/ccip/Router.ts b/contracts/wrappers/gen/ccip/Router.ts index 104e45aa9..04bf974e9 100644 --- a/contracts/wrappers/gen/ccip/Router.ts +++ b/contracts/wrappers/gen/ccip/Router.ts @@ -1005,6 +1005,102 @@ export const ReceiveExecutorId = { } } +/** + > struct (0x7362d09c) Common_JettonTransferNotification { + > queryId: uint64 + > amount: coins + > sender: address + > forwardPayload: cell? + > } + */ +export interface Common_JettonTransferNotification { + readonly $: 'Common_JettonTransferNotification' + queryId: uint64 + amount: coins + sender: c.Address + forwardPayload: c.Cell | null +} + +export const Common_JettonTransferNotification = { + PREFIX: 0x7362d09c, + + create(args: { + queryId: uint64 + amount: coins + sender: c.Address + forwardPayload: c.Cell | null + }): Common_JettonTransferNotification { + return { + $: 'Common_JettonTransferNotification', + ...args + } + }, + fromSlice(s: c.Slice): Common_JettonTransferNotification { + loadAndCheckPrefix32(s, 0x7362d09c, 'Common_JettonTransferNotification'); + return { + $: 'Common_JettonTransferNotification', + queryId: s.loadUintBig(64), + amount: s.loadCoins(), + sender: s.loadAddress(), + forwardPayload: s.loadBoolean() ? s.loadRef() : null, + } + }, + store(self: Common_JettonTransferNotification, b: c.Builder): void { + b.storeUint(0x7362d09c, 32); + b.storeUint(self.queryId, 64); + b.storeCoins(self.amount); + b.storeAddress(self.sender); + storeTolkNullable(self.forwardPayload, b, + (v,b) => b.storeRef(v) + ); + }, + toCell(self: Common_JettonTransferNotification): c.Cell { + return makeCellFrom(self, Common_JettonTransferNotification.store); + } +} + +/** + > struct (0x7dd8f942) MockTokenPool_LockOrBurn { + > tokenAmount: TokenAmount + > notify: address + > } + */ +export interface MockTokenPool_LockOrBurn { + readonly $: 'MockTokenPool_LockOrBurn' + tokenAmount: TokenAmount + notify: c.Address +} + +export const MockTokenPool_LockOrBurn = { + PREFIX: 0x7dd8f942, + + create(args: { + tokenAmount: TokenAmount + notify: c.Address + }): MockTokenPool_LockOrBurn { + return { + $: 'MockTokenPool_LockOrBurn', + ...args + } + }, + fromSlice(s: c.Slice): MockTokenPool_LockOrBurn { + loadAndCheckPrefix32(s, 0x7dd8f942, 'MockTokenPool_LockOrBurn'); + return { + $: 'MockTokenPool_LockOrBurn', + tokenAmount: TokenAmount.fromSlice(s), + notify: s.loadAddress(), + } + }, + store(self: MockTokenPool_LockOrBurn, b: c.Builder): void { + b.storeUint(0x7dd8f942, 32); + TokenAmount.store(self.tokenAmount, b); + b.storeAddress(self.notify); + }, + toCell(self: MockTokenPool_LockOrBurn): c.Cell { + return makeCellFrom(self, MockTokenPool_LockOrBurn.store); + } +} + /** > struct OnRamps { > destChainSelectors: SnakedCell @@ -1807,6 +1903,58 @@ export const Router_GetValidatedFee = { }, } +/** + > struct (0x6f2d00df) Router_LockOrBurn { + > tokenPool: address + > tokenAmount: TokenAmount + > destChainSelector: uint64 + > executorAddress: address + > } + */ +export interface Router_LockOrBurn { + readonly $: 'Router_LockOrBurn' + tokenPool: c.Address + tokenAmount: TokenAmount + destChainSelector: uint64 + executorAddress: c.Address +} + +export const Router_LockOrBurn = { + PREFIX: 0x6f2d00df, + + create(args: { + tokenPool: c.Address + tokenAmount: TokenAmount + destChainSelector: uint64 + executorAddress: c.Address + }): Router_LockOrBurn { + return { + $: 'Router_LockOrBurn', + ...args + } + }, + fromSlice(s: c.Slice): Router_LockOrBurn { + loadAndCheckPrefix32(s, 0x6f2d00df, 'Router_LockOrBurn'); + return { + $: 'Router_LockOrBurn', + tokenPool: s.loadAddress(), + tokenAmount: TokenAmount.fromSlice(s), + destChainSelector: s.loadUintBig(64), + executorAddress: s.loadAddress(), + } + }, + store(self: Router_LockOrBurn, b: c.Builder): void { + b.storeUint(0x6f2d00df, 32); + b.storeAddress(self.tokenPool); + TokenAmount.store(self.tokenAmount, b); + b.storeUint(self.destChainSelector, 64); + b.storeAddress(self.executorAddress); + }, + toCell(self: Router_LockOrBurn): c.Cell { + return makeCellFrom(self, Router_LockOrBurn.store); + } +} + /** > struct Router_GetValidatedFeeContext { > routerContext: address @@ -2543,7 +2691,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, @@ -2552,17 +2700,20 @@ export class Router implements c.Contract { 'Ownable2Step_Error.OnlyCallableByOwner': 49800, 'Ownable2Step_Error.CannotTransferToSelf': 49801, 'Ownable2Step_Error.MustBeProposedOwner': 49802, - 'Withdrawable_Error.InsufficientBalance': 57100, 'Router_Error.DestChainNotEnabled': 57100, + 'Withdrawable_Error.InsufficientBalance': 57100, 'Withdrawable_Error.HitReserve': 57101, 'Router_Error.SourceChainNotEnabled': 57101, - 'Router_Error.SenderIsNotOffRamp': 57102, 'Withdrawable_Error.InvalidRequest': 57102, + 'Router_Error.SenderIsNotOffRamp': 57102, 'Router_Error.OffRampNotSetForSelector': 57103, 'Router_Error.OffRampAddressMismatch': 57104, 'Router_Error.SubjectCursed': 57105, 'Router_Error.NotOnRamp': 57106, + 'Router_Error.MissingTokenAmounts': 57107, + 'Router_Error.NoMultiTokenTransfers': 57108, 'Router_Error.InsufficientFee': 57109, + 'Router_Error.TokenTransferNotThroughNotification': 57110, } readonly address: c.Address @@ -2708,12 +2859,30 @@ export class Router implements c.Contract { return Router_MessageRejected.toCell(Router_MessageRejected.create(body)); } + static createCellOfRouterLockOrBurn(body: { + tokenPool: c.Address + tokenAmount: TokenAmount + destChainSelector: uint64 + executorAddress: c.Address + }) { + return Router_LockOrBurn.toCell(Router_LockOrBurn.create(body)); + } + static createCellOfRouterRMNOwnableMessage(body: { content: RemainingBitsAndRefs }) { return Router_RMNOwnableMessage.toCell(Router_RMNOwnableMessage.create(body)); } + static createCellOfCommonJettonTransferNotification(body: { + queryId: uint64 + amount: coins + sender: c.Address + forwardPayload: c.Cell | null + }) { + return Common_JettonTransferNotification.toCell(Common_JettonTransferNotification.create(body)); + } + async sendDeploy(provider: ContractProvider, via: Sender, msgValue: coins, extraOptions?: ExtraSendOptions) { return provider.internal(via, { value: msgValue, @@ -2882,6 +3051,19 @@ export class Router implements c.Contract { }); } + async sendRouterLockOrBurn(provider: ContractProvider, via: Sender, msgValue: coins, body: { + tokenPool: c.Address + tokenAmount: TokenAmount + destChainSelector: uint64 + executorAddress: c.Address + }, extraOptions?: ExtraSendOptions) { + return provider.internal(via, { + value: msgValue, + body: Router_LockOrBurn.toCell(Router_LockOrBurn.create(body)), + ...extraOptions + }); + } + async sendRouterRMNOwnableMessage(provider: ContractProvider, via: Sender, msgValue: coins, body: { content: RemainingBitsAndRefs }, extraOptions?: ExtraSendOptions) { @@ -2892,6 +3074,19 @@ export class Router implements c.Contract { }); } + async sendCommonJettonTransferNotification(provider: ContractProvider, via: Sender, msgValue: coins, body: { + queryId: uint64 + amount: coins + sender: c.Address + forwardPayload: c.Cell | null + }, extraOptions?: ExtraSendOptions) { + return provider.internal(via, { + value: msgValue, + body: Common_JettonTransferNotification.toCell(Common_JettonTransferNotification.create(body)), + ...extraOptions + }); + } + async getVerifyNotCursed(provider: ContractProvider, subject: uint128): Promise { const r = StackReader.fromGetMethod(1, await provider.get('verifyNotCursed', [ { type: 'int', value: subject }, From 4111963652d23ec0017613743c3b781a8cbba8e3 Mon Sep 17 00:00:00 2001 From: vicente Date: Thu, 11 Jun 2026 09:54:52 -0300 Subject: [PATCH 09/14] fix router errors --- contracts/contracts/ccip/router/contract.tolk | 8 +++++--- contracts/contracts/ccip/router/errors.tolk | 2 ++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/contracts/contracts/ccip/router/contract.tolk b/contracts/contracts/ccip/router/contract.tolk index 08089d5a4..10fb203a4 100644 --- a/contracts/contracts/ccip/router/contract.tolk +++ b/contracts/contracts/ccip/router/contract.tolk @@ -167,14 +167,16 @@ fun onInternalMessage(in: InMessage) { //TODO: Validate sender is owned jetton transfer val st = lazy Storage.load(); - // TODO: catch errors, if different message type than CCIPSend - val sendMsg = Router_CCIPSend.fromCell(msg.forwardPayload!); + assert (msg.forwardPayload != null) throw Router_Error.JettonTransferNotificationWithoutForwardPayload; + + //TODO: should we catch cases when the forward payload is not Router_CCIPSend? + val sendMsg = Router_CCIPSend.fromCell(msg.forwardPayload); var tokenAmounts = sendMsg.tokenAmounts.iter(); assert (!tokenAmounts.empty()) throw Router_Error.MissingTokenAmounts; val transferedJetton = tokenAmounts.next(); - assert (transferedJetton.amount == msg.amount) throw 5; // TODO: if transfered token is link, extract fee before this check + assert (transferedJetton.amount == msg.amount) throw Router_Error.TokenAmountMismatch; assert (tokenAmounts.empty()) throw Router_Error.NoMultiTokenTransfers; val onRamp = st.onRamps.mustGet(sendMsg.destChainSelector, Router_Error.DestChainNotEnabled as int); diff --git a/contracts/contracts/ccip/router/errors.tolk b/contracts/contracts/ccip/router/errors.tolk index 0f95b0e4c..d3065dc10 100644 --- a/contracts/contracts/ccip/router/errors.tolk +++ b/contracts/contracts/ccip/router/errors.tolk @@ -13,4 +13,6 @@ enum Router_Error { NoMultiTokenTransfers InsufficientFee TokenTransferNotThroughNotification + JettonTransferNotificationWithoutForwardPayload + TokenAmountMismatch } From 7b60147b568f2324adbc826e547f34c4118c474b Mon Sep 17 00:00:00 2001 From: vicente Date: Thu, 11 Jun 2026 09:55:08 -0300 Subject: [PATCH 10/14] fix sendExecutor wrapper missing state types --- contracts/wrappers/ccip/CCIPSendExecutor.ts | 63 ++++++++++++++++++--- 1 file changed, 55 insertions(+), 8 deletions(-) diff --git a/contracts/wrappers/ccip/CCIPSendExecutor.ts b/contracts/wrappers/ccip/CCIPSendExecutor.ts index 6c0c0bc10..0dacfa10a 100644 --- a/contracts/wrappers/ccip/CCIPSendExecutor.ts +++ b/contracts/wrappers/ccip/CCIPSendExecutor.ts @@ -52,7 +52,7 @@ export type Addresses = { tokenRegistry?: Address | null } -export type State = Initialized | OnGoingFeeValidation +export type State = Initialized | OnGoingFeeValidation | TokenRegistryAccess | TokenTransfer | Finalized export type Initialized = { kind: 'initialized' @@ -62,6 +62,21 @@ export type OnGoingFeeValidation = { kind: 'on-going-fee-validation' } +export type TokenRegistryAccess = { + kind: 'token-registry-access' + fee: fq.Fee +} + +export type TokenTransfer = { + kind: 'token-transfer' + tokenPool: Address + fee: fq.Fee +} + +export type Finalized = { + kind: 'finalized' +} + export type Config = { feeQuoter: Address // Null when the send carries no token transfers. @@ -107,20 +122,52 @@ export const builder = (() => { encode: function (data: State): Builder { switch (data.kind) { case 'initialized': - return beginCell().storeUint(0, 1) + return beginCell().storeUint(0b000, 3).storeRef(beginCell().endCell()) case 'on-going-fee-validation': - return beginCell().storeUint(1, 1) + return beginCell().storeUint(0b001, 3).storeRef(beginCell().endCell()) + case 'token-registry-access': + return beginCell() + .storeUint(0b010, 3) + .storeRef(fq.builder.data.fee.encode(data.fee).endCell()) + case 'token-transfer': + return beginCell() + .storeUint(0b011, 3) + .storeRef( + beginCell() + .storeAddress(data.tokenPool) + .storeBuilder(fq.builder.data.fee.encode(data.fee)) + .endCell(), + ) + case 'finalized': + return beginCell().storeUint(0b100, 3).storeRef(beginCell().endCell()) } }, load: function (src: Slice): State { - const kind = src.loadUint(1) - switch (kind) { - case 0: + const tag = src.loadUint(3) + switch (tag) { + case 0b000: + src.loadRef() return { kind: 'initialized' } - case 1: + case 0b001: + src.loadRef() return { kind: 'on-going-fee-validation' } + case 0b010: { + const feeSlice = src.loadRef().beginParse() + return { kind: 'token-registry-access', fee: fq.builder.data.fee.load(feeSlice) } + } + case 0b011: { + const inner = src.loadRef().beginParse() + return { + kind: 'token-transfer', + tokenPool: inner.loadAddress(), + fee: fq.builder.data.fee.load(inner), + } + } + case 0b100: + src.loadRef() + return { kind: 'finalized' } default: - throw new Error(`Unknown State kind: ${kind}`) + throw new Error(`Unknown State tag: ${tag}`) } }, } From c2733ffc80cde0788c020336e33e023d2ab54108 Mon Sep 17 00:00:00 2001 From: vicente Date: Thu, 11 Jun 2026 22:15:37 -0300 Subject: [PATCH 11/14] unify under onCCIPSend handler --- contracts/contracts/ccip/router/contract.tolk | 26 +++++++------------ contracts/contracts/ccip/router/errors.tolk | 1 + 2 files changed, 10 insertions(+), 17 deletions(-) diff --git a/contracts/contracts/ccip/router/contract.tolk b/contracts/contracts/ccip/router/contract.tolk index 10fb203a4..b377370ec 100644 --- a/contracts/contracts/ccip/router/contract.tolk +++ b/contracts/contracts/ccip/router/contract.tolk @@ -55,6 +55,8 @@ fun onInternalMessage(in: InMessage) { Router_CCIPSend => { val minValue = Router_Costs.CCIPSend(); assert (in.valueCoins >= minValue) throw Router_Error.InsufficientFee; + // Token transfer messages can only come in through jetton transfer notifications + assert(msg.tokenAmounts.empty()) throw Router_Error.TokenTransferNotThroughNotification; //TBD shuold this be sendMessageRejected instead of throw? onCCIPSend(msg, in.senderAddress, in.valueCoins); } // Permissionless @@ -164,13 +166,16 @@ fun onInternalMessage(in: InMessage) { } // Sender must be a Jetton Wallet owned by the Router Common_JettonTransferNotification => { - //TODO: Validate sender is owned jetton transfer - val st = lazy Storage.load(); + + // TODO minValue is probably higher for a tokenTransfer as it needs more hops. + // We should revisit our entire min gas assertion model anyway + val minValue = Router_Costs.CCIPSend(); + assert (in.valueCoins >= minValue) throw Router_Error.InsufficientFee; assert (msg.forwardPayload != null) throw Router_Error.JettonTransferNotificationWithoutForwardPayload; //TODO: should we catch cases when the forward payload is not Router_CCIPSend? - val sendMsg = Router_CCIPSend.fromCell(msg.forwardPayload); + val sendMsg = lazy Router_CCIPSend.fromCell(msg.forwardPayload); var tokenAmounts = sendMsg.tokenAmounts.iter(); assert (!tokenAmounts.empty()) throw Router_Error.MissingTokenAmounts; @@ -179,17 +184,7 @@ fun onInternalMessage(in: InMessage) { assert (transferedJetton.amount == msg.amount) throw Router_Error.TokenAmountMismatch; assert (tokenAmounts.empty()) throw Router_Error.NoMultiTokenTransfers; - val onRamp = st.onRamps.mustGet(sendMsg.destChainSelector, Router_Error.DestChainNotEnabled as int); - // Fees are paid in native TON, not in the transferred token. metadata.value must be the - // native TON attached to the transfer notification (used downstream to cover fee + - // execution costs), mirroring the plain-message path which uses in.valueCoins. - val onRampSend = createMessage({ - bounce: true, - value: 0, - dest: onRamp, - body: OnRamp_Send { msg: sendMsg.toCell(), metadata: Metadata{ sender: msg.sender, value: in.valueCoins } }, - }); - onRampSend.send(SEND_MODE_CARRY_ALL_REMAINING_MESSAGE_VALUE); + onCCIPSend(sendMsg, msg.sender, in.valueCoins); } else => { // attempt to handle Ownable messages @@ -518,9 +513,6 @@ fun onCCIPSend(msg: Router_CCIPSend, sender: address, value: coins) { msg.feeToken = st.wrappedNative } - // Token transfer messages can only come in through jetton transfer notifications - assert(msg.tokenAmounts.empty()) throw Router_Error.TokenTransferNotThroughNotification; //TBD shuold this be sendMessageRejected instead of throw? - val onRampResult = st.onRamps.get(msg.destChainSelector); if (!onRampResult.isFound) { return sendMessageRejected(sender, msg.queryID, Router_Error.DestChainNotEnabled as uint256); diff --git a/contracts/contracts/ccip/router/errors.tolk b/contracts/contracts/ccip/router/errors.tolk index d3065dc10..1cfdee07f 100644 --- a/contracts/contracts/ccip/router/errors.tolk +++ b/contracts/contracts/ccip/router/errors.tolk @@ -15,4 +15,5 @@ enum Router_Error { TokenTransferNotThroughNotification JettonTransferNotificationWithoutForwardPayload TokenAmountMismatch + ForwardPayloadIsNotCCIPSend } From 83de367d9a8334170e30872350669e67b81cdbec Mon Sep 17 00:00:00 2001 From: vicente Date: Thu, 11 Jun 2026 23:44:49 -0300 Subject: [PATCH 12/14] add TODOs and missing lazy decodings --- .../contracts/ccip/ccipsend_executor/contract.tolk | 12 ++++++++++-- contracts/contracts/ccip/onramp/contract.tolk | 2 +- .../contracts/ccip/token_registry/contract.tolk | 2 ++ 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/contracts/contracts/ccip/ccipsend_executor/contract.tolk b/contracts/contracts/ccip/ccipsend_executor/contract.tolk index 0512651b1..de598ff1d 100644 --- a/contracts/contracts/ccip/ccipsend_executor/contract.tolk +++ b/contracts/contracts/ccip/ccipsend_executor/contract.tolk @@ -73,9 +73,16 @@ fun onBouncedMessage(in: InMessageBounced) { val this = CCIPSendExecutor.load(); this.exitWithError(CCIPSendExecutor_Error.FeeQuoterBounce); } + //TODO: We should handle bounced messages from the TokenRegistry, as that means the token is not enabled on the lane } } +//TODO: Figure out how to maintain backwards compatibility for messages sent between updating the Executor code in the OnRamp and upgrading the OnRamp itself. +// Option 1: split the initialization in two messages to maintain backwards compatibility. +// 1. CCIPSendExecutor_Execute stays the same as in 1.6.1 (that means not changing Config) +// 2. CCIPSendExecutor_InitTokenTransfer passes the token registry address and other necessary configs +// That way we can upgrade the SendExecutor code in the OnRamp and then upgrade the OnRamp itself, if an executor is deployed by the OnRamp between upgrades the new SendExecutor will still be able to handle the initialization message. +// Option 2: Create a new message type CCIPSendExecutor_ExecuteV2 which has the new config element. Make the new executor able to handle both this version and the original. fun init(onrampSend: OnRamp_Send, config: CCIPSendExecutor_Config): CCIPSendExecutor { val st = lazy CCIPSendExecutor_InitialData.fromCell(contract.getData()); return CCIPSendExecutor { @@ -154,12 +161,13 @@ fun CCIPSendExecutor.onMessageValid fun CCIPSendExecutor.onTokenInfoReceived(mutate self, msg: TokenRegistry_ReturnTokenInfo) { //TODO validate sender wallet address by querying the jettonMinter assert(msg.tokenInfo.enabled) throw CCIPSendExecutor_Error.TokenNotEnabled; - val onrampSend = self.onrampSend.msg.load(); + val onrampSend = lazy self.onrampSend.msg.load(); val tokenAmount = onrampSend.tokenAmounts.iter().next(); + val addresses = lazy self.addresses.load(); val requestLockOrBurn = createMessage({ bounce: true, value: 0, - dest: self.addresses.load().onramp, + dest: addresses.onramp, body: OnRamp_ExecutorRequestsLockOrBurn { tokenAmount, tokenPool: msg.tokenInfo.tokenPool, diff --git a/contracts/contracts/ccip/onramp/contract.tolk b/contracts/contracts/ccip/onramp/contract.tolk index 54d4f7420..b74820cfd 100644 --- a/contracts/contracts/ccip/onramp/contract.tolk +++ b/contracts/contracts/ccip/onramp/contract.tolk @@ -75,7 +75,7 @@ fun onInternalMessage(in: InMessage) { OnRamp_ExecutorRequestsLockOrBurn => { // Sender must be Send Executor var st = lazy OnRamp_Storage.load(); - assert(st.executor.autoDeployAddress(msg.executorID).addressMatches(in.senderAddress), Error.Unauthorized); + assert(st.executor.autoDeployAddress(msg.executorID).calculateAddress() == in.senderAddress, Error.Unauthorized); onExecutorRequestsLockOrBurn(st, msg, in.senderAddress); } // Sender must be Send Executor diff --git a/contracts/contracts/ccip/token_registry/contract.tolk b/contracts/contracts/ccip/token_registry/contract.tolk index b79aecc54..d80879b29 100644 --- a/contracts/contracts/ccip/token_registry/contract.tolk +++ b/contracts/contracts/ccip/token_registry/contract.tolk @@ -18,6 +18,7 @@ fun onInternalMessage(in: InMessage) { match (msg) { TokenRegistry_GetTokenInfo => { + //TODO: min value assertion onGetTokenInfo(msg, in.senderAddress); } else => { @@ -28,6 +29,7 @@ fun onInternalMessage(in: InMessage) { fun onGetTokenInfo(msg: TokenRegistry_GetTokenInfo, sender: address) { val st = TokenRegistry_Storage.load(); + //TODO we might want to send a different message than ReturnTokenInfo when the token is not enabled val response = createMessage({ dest: sender, value: 0, From e98991ed7bedd8d94204a10c1a8e23f5f111dd98 Mon Sep 17 00:00:00 2001 From: vicente Date: Fri, 12 Jun 2026 01:26:52 -0300 Subject: [PATCH 13/14] fmt --- contracts/wrappers/ccip/CCIPSendExecutor.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/contracts/wrappers/ccip/CCIPSendExecutor.ts b/contracts/wrappers/ccip/CCIPSendExecutor.ts index 0dacfa10a..a68d4bb6b 100644 --- a/contracts/wrappers/ccip/CCIPSendExecutor.ts +++ b/contracts/wrappers/ccip/CCIPSendExecutor.ts @@ -52,7 +52,12 @@ export type Addresses = { tokenRegistry?: Address | null } -export type State = Initialized | OnGoingFeeValidation | TokenRegistryAccess | TokenTransfer | Finalized +export type State = + | Initialized + | OnGoingFeeValidation + | TokenRegistryAccess + | TokenTransfer + | Finalized export type Initialized = { kind: 'initialized' From 0b2de826a230e531e134c8dfd9df34f02a4ced1a Mon Sep 17 00:00:00 2001 From: vicente Date: Fri, 12 Jun 2026 11:13:51 -0300 Subject: [PATCH 14/14] abigen --- contracts/wrappers/gen/ccip/CCIPSendExecutor.ts | 2 +- contracts/wrappers/gen/ccip/OnRamp.ts | 2 +- contracts/wrappers/gen/ccip/Router.ts | 6 ++++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/contracts/wrappers/gen/ccip/CCIPSendExecutor.ts b/contracts/wrappers/gen/ccip/CCIPSendExecutor.ts index aeed5c22b..7313b855f 100644 --- a/contracts/wrappers/gen/ccip/CCIPSendExecutor.ts +++ b/contracts/wrappers/gen/ccip/CCIPSendExecutor.ts @@ -1427,7 +1427,7 @@ function calculateDeployedAddress(code: c.Cell, data: c.Cell, options: DeployedA } export class CCIPSendExecutor 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/OnRamp.ts b/contracts/wrappers/gen/ccip/OnRamp.ts index 9347d75c4..262cd43cf 100644 --- a/contracts/wrappers/gen/ccip/OnRamp.ts +++ b/contracts/wrappers/gen/ccip/OnRamp.ts @@ -2345,7 +2345,7 @@ function calculateDeployedAddress(code: c.Cell, data: c.Cell, options: DeployedA } export class OnRamp 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/Router.ts b/contracts/wrappers/gen/ccip/Router.ts index 04bf974e9..ee0cf53b1 100644 --- a/contracts/wrappers/gen/ccip/Router.ts +++ b/contracts/wrappers/gen/ccip/Router.ts @@ -2691,7 +2691,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, @@ -2700,8 +2700,8 @@ export class Router implements c.Contract { 'Ownable2Step_Error.OnlyCallableByOwner': 49800, 'Ownable2Step_Error.CannotTransferToSelf': 49801, 'Ownable2Step_Error.MustBeProposedOwner': 49802, - 'Router_Error.DestChainNotEnabled': 57100, 'Withdrawable_Error.InsufficientBalance': 57100, + 'Router_Error.DestChainNotEnabled': 57100, 'Withdrawable_Error.HitReserve': 57101, 'Router_Error.SourceChainNotEnabled': 57101, 'Withdrawable_Error.InvalidRequest': 57102, @@ -2714,6 +2714,8 @@ export class Router implements c.Contract { 'Router_Error.NoMultiTokenTransfers': 57108, 'Router_Error.InsufficientFee': 57109, 'Router_Error.TokenTransferNotThroughNotification': 57110, + 'Router_Error.JettonTransferNotificationWithoutForwardPayload': 57111, + 'Router_Error.TokenAmountMismatch': 57112, } readonly address: c.Address