Skip to content

feat: add flexible retryable ticket encoding primitive - #649

Open
gomesalexandre wants to merge 1 commit into
OffchainLabs:mainfrom
gomesalexandre:feat_encode_retryable_ticket
Open

feat: add flexible retryable ticket encoding primitive#649
gomesalexandre wants to merge 1 commit into
OffchainLabs:mainfrom
gomesalexandre:feat_encode_retryable_ticket

Conversation

@gomesalexandre

@gomesalexandre gomesalexandre commented Aug 18, 2026

Copy link
Copy Markdown

closes #639

what

Adds ParentToChildMessageCreator.encodeRetryableTicket, a static primitive that encodes the Inbox createRetryableTicket calldata and computes the fee math without estimating gas against the child chain. gasLimit and maxFeePerGas are passed directly, so it works before the child chain is running - the ownership-transfer-during-Orbit-deployment scenario from the issue, where gas params are hardcoded.

const { data, deposit, maxSubmissionCost } =
  await ParentToChildMessageCreator.encodeRetryableTicket({
    to, l2CallValue, data, excessFeeRefundAddress, callValueRefundAddress,
    gasLimit, maxFeePerGas, nativeTokenIsEth,
    maxSubmissionCost, // optional: read from the Inbox if omitted
  })
  • maxSubmissionCost is supplied, or read from the Inbox via calculateRetryableSubmissionFee (pass parentProvider + inbox)
  • deposit is supplied, or derived as gasLimit * maxFeePerGas + maxSubmissionCost + l2CallValue
  • handles ETH vs ERC20 native token Inbox encoding
  • returns { data, deposit, maxSubmissionCost }, no transaction request

no behavior change to getTicketCreationRequest

It is refactored to call encodeRetryableTicket after estimating gas, passing the estimated maxSubmissionCost and deposit through, so the calldata/value (including the options.deposit.base override path) are byte-identical to before.

the derived submission fee is padded

When maxSubmissionCost is read from the Inbox it is padded by submissionFeePercentIncrease (default DEFAULT_SUBMISSION_FEE_PERCENT_INCREASE = 300, the same margin the gas estimator applies). The Inbox recomputes the submission fee against block.basefee at inclusion and reverts the whole ticket-creation tx with InsufficientSubmissionCost if the baked-in value is too low. Callers wanting the raw value can pass submissionFeePercentIncrease: 0.

tests + verification

Added packages/sdk/tests/unit/encodeRetryableTicket.test.ts (ETH + ERC20 encoding decoded against the real ABI, derived deposit, caller deposit override, throw-when-underspecified). test:unit (vitest) passes; tsc, eslint, prettier --check clean.

Runtime check (offline path): deposit 1001030000000000000 (= 300000*100000000 + 0.001e18 + 1e18), selector 0x679b6ded.


Rebased onto the v4 monorepo restructure + L1ToL2 -> ParentToChild rename.

@cla-bot cla-bot Bot added the cla-signed label Aug 18, 2026
@CLAassistant

CLAassistant commented Aug 18, 2026

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

Adds `ParentToChildMessageCreator.encodeRetryableTicket`, a static
primitive that encodes the Inbox `createRetryableTicket` calldata and
computes the fee math without estimating gas against the child chain.
Gas params (`gasLimit`, `maxFeePerGas`) are supplied directly, so it can
be used before the child chain is running - for example transferring
ownership during an Orbit chain deployment, where gas params are
hardcoded.

- `maxSubmissionCost` is either supplied or read from the Inbox on the
  parent chain via `calculateRetryableSubmissionFee`, then padded by
  `submissionFeePercentIncrease` (default 300, matching the estimator) so
  the baked-in cost survives a parent base-fee rise before inclusion -
  the Inbox reverts with `InsufficientSubmissionCost` otherwise
- `deposit` is either supplied or derived as
  `gasLimit * maxFeePerGas + maxSubmissionCost + l2CallValue`
- handles ETH vs ERC20 native token Inbox encoding
- returns `{ data, deposit, maxSubmissionCost }`; no transaction request

`getTicketCreationRequest` is refactored to use it after estimating gas,
passing the estimated `maxSubmissionCost` and `deposit` through so the
existing behavior (including deposit overrides) is unchanged.

closes OffchainLabs#639
@gomesalexandre
gomesalexandre force-pushed the feat_encode_retryable_ticket branch from aa5a259 to cd34d7b Compare August 18, 2026 11:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: add flexible retryable ticket encoding primitive

2 participants