Skip to content

TP deposit & async flow auth (deposit/withdraw accounts + CCT) - #814

Open
krebernisak wants to merge 24 commits into
mainfrom
feat/tp-ctx-executor
Open

TP deposit & async flow auth (deposit/withdraw accounts + CCT)#814
krebernisak wants to merge 24 commits into
mainfrom
feat/tp-ctx-executor

Conversation

@krebernisak

@krebernisak krebernisak commented Jul 31, 2026

Copy link
Copy Markdown
Collaborator

Summary

Eliminates queryId-keyed pending storage (pendingBurns, pendingMints, pendingReleases, pendingLocks) from all token pool variants, enabling concurrent cross-chain operations without storage collision or circuit breaker limits. The design evolved through two phases within this PR:

  1. ContextExecutor — introduced as a deterministic proxy contract per operation to receive and forward completion messages without local storage
  2. OffRampAccount + CCT forwardPayload — the final design replaces ContextExecutor entirely: OffRampAccount handles release/lock continuations, while the CCT burn path carries context directly through jetton forwardPayload

What Changed

OffRampAccount (new):

  • Deterministic account contract for async operation continuation
  • Receives forwarded jetton notifications and relays them to the pool with context
  • No per-operation proxy storage needed

CCT Burn Flow:

  • CCT jetton minter/wallet now accept forwardPayload on burn messages
  • CCT_AskToBurn, CCT_BurnNotificationForMinter, CCT_ReturnExcessesBack all carry forwardPayload
  • BurnMintTokenPool sends CCT_AskToBurn with context embedded, finalizing the burn directly — no proxy contract

Token Pools (3 files):

  • BurnMintTokenPool: Burn path uses direct CCT forwardPayload flow
  • LockReleaseTokenPool: Release flow uses OffRampAccount for async continuation
  • LockReleaseLockboxTokenPool: Both lock and release flows use OffRampAccount

Token Pool Entrypoint entrypoint.tolk:

  • Comprehensive error handling for onLockOrBurnTransfer with try/catch around forward payload decoding
  • bestEffortReturnTransfer: Returns custody to sender on recoverable failures
  • notifyLockOrBurnFailure / reserveLockOrBurnFailureValue: Pool balance protection

Other:

  • Composed consumeInboundRateLimit / consumeOutboundRateLimit functions shared across pools
  • JettonLockBox tests updated to use auto-generated error bindings

@krebernisak
krebernisak requested a review from a team as a code owner July 31, 2026 09:10
@github-actions

Copy link
Copy Markdown

👋 krebernisak, thanks for creating this pull request!

To help reviewers, please consider creating future PRs as drafts first. This allows you to self-review and make any final changes before notifying the team.

Once you're ready, you can mark it as "Ready for review" to request feedback. Thanks!

@krebernisak krebernisak changed the title Add TP <> ContextExecutor integration + Jetton transfer error handling Replace ContextExecutor with OffRampAccount + CCT burn forwardPayload flow Aug 7, 2026
@krebernisak krebernisak changed the title Replace ContextExecutor with OffRampAccount + CCT burn forwardPayload flow Replace per-pool pending maps with OffRampAccount & CCT burn forwardPayload Aug 7, 2026
@krebernisak krebernisak changed the title Replace per-pool pending maps with OffRampAccount & CCT burn forwardPayload TP continuation - OffRampAccount contract & CCT burn flow forwardPayload Aug 7, 2026
notificationTarget: address;
/// Only messages from this jetton wallet are forwarded (prevents spam from other jettons).
/// Set on init — OAA address is derived from (code, owner, notificationTarget) only.
allowedJettonWallet: address?;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this gets deployed with Deploable, there's no need for this to be optional

forwardPayload: msg.forwardPayload,
},
});
reply.send(SEND_MODE_CARRY_ALL_REMAINING_MESSAGE_VALUE);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We want to reserve some balance, either here or through Deployable's Deployable_InitializeAndSend

@krebernisak krebernisak changed the title TP continuation - OffRampAccount contract & CCT burn flow forwardPayload OnRampAccount (deposit auth) + TP continuation using OffRampAccount contract and CCT burn flow fwdPayload Aug 11, 2026
@krebernisak krebernisak changed the title OnRampAccount (deposit auth) + TP continuation using OffRampAccount contract and CCT burn flow fwdPayload TP deposit and continuation flow using deposit/withdraw accounts + CCT (for burn/mint) Aug 11, 2026
@krebernisak krebernisak changed the title TP deposit and continuation flow using deposit/withdraw accounts + CCT (for burn/mint) TP deposit and continuation flow (deposit/withdraw accounts + CCT) Aug 11, 2026
@krebernisak krebernisak changed the title TP deposit and continuation flow (deposit/withdraw accounts + CCT) TP deposit and async flow auth (deposit/withdraw accounts + CCT) Aug 11, 2026
@krebernisak krebernisak changed the title TP deposit and async flow auth (deposit/withdraw accounts + CCT) TP deposit/async flow auth (deposit/withdraw accounts + CCT) Aug 11, 2026
@krebernisak krebernisak changed the title TP deposit/async flow auth (deposit/withdraw accounts + CCT) TP deposit & async flow auth (deposit/withdraw accounts + CCT) Aug 11, 2026

/// Sent by the pool after successful initialization, confirming the account is ready.
/// The pool identifies which OffRampAccount replied from `in.senderAddress`.
struct (0xb2e46750) OffRampAccount_Reply {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: The message name is not very descriptive. OffRampAccount_Initialized may be a better option

bounce: BounceMode.RichBounce,
value: 0,
dest: getJettonWalletOf(data),
body: AskToTransfer {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

followup: pontentially, we could just send CCIPSend to the router instead

writing it here so we don't forget

/// `OffRampAccount`. The token pool (which knows the Deployables setup) is responsible for
/// deriving the account via Deployables to authenticate deposits. See
/// `TokenPool_DynamicConfig.allowedDepositNamespaces` / `TokenPool_AdminConfig.deployableCode`.
fun calcAddressOfOnRampAccount(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this outdated? I think this is unused and has been replace by deriveDepositAccount. We shouldn't be using the OnRampAccount_Data to derive the address if the contract gets deployed with Deployable

val context = lazy BurnMintTokenPool_BurnContext.fromCell(msg.forwardPayload!);
val operation = context.forwardPayload.load();
// TODO: is this check necessary?
assert(context.wallet == pool.data.jettonClient().walletAddress(), BurnMintTokenPool_Error.UnexpectedBurnBounce);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see the point. What are you protecting from? The forwardPayload is arbitrary data. You've already check that sender is your own wallet address and that the initiator was you.

Comment thread contracts/contracts/ccip/pools/burn_mint/contract.tolk Outdated
mutate self,
sender: address,
queryId: uint64,
allowedDepositNamespaces: map<uint32, bool>,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can use void type. See doc here

Suggested change
allowedDepositNamespaces: map<uint32, bool>,
allowedDepositNamespaces: map<uint32, ()>,

Comment thread contracts/contracts/ccip/pools/lib/token_pool/entrypoint.tolk Outdated
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants