Skip to content

feat(sdk)!: raise CPI limits to 64 metas and 4 signer groups - #21

Merged
Mister-Meeseeks merged 2 commits into
CrocSwap:mainfrom
paulbalaji:cpi-raise-limits
Oct 19, 2026
Merged

Mister-Meeseeks merged 2 commits into
CrocSwap:mainfrom
paulbalaji:cpi-raise-limits

Conversation

@paulbalaji

@paulbalaji paulbalaji commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

Problem

CPIs are capped at 16 metas and 2 signer groups, well under the runtime's limits. Hyperlane needs up to 22: a quoted IGP payment takes 22 and a fee quote 17. Both fail with 3002 or 2006.

Solution

Raise the limits to 64 metas and 4 signer groups; seeds are unchanged. Why 64: agave caps account infos at 64 (128 behind a feature gate), and 255 metas would need about 4 KiB of descriptors, the whole frame.

  • sol_Invoke is no longer inlined. Its frame grows from 960 to 2,240 bytes; callers' frames don't change.
  • cpi.Metas stays inline up to 16 and moves to a 576-byte heap array on the 17th Add.

Benchmarks

fogo-v0; solana-v3 within a few CU:

case before after
builder, 3 metas 5,136 5,146
builder, 16 metas 7,073 7,096
raw solana.Invoke, 3 metas 4,414 4,414
builder, 22 metas / 4 groups rejected 9,049
builder, 64 metas / 4 groups rejected 15,577

Tests

19 CPI cases on both profiles, from 3 to 64 metas and 0 to 4 groups, through builders and raw Invoke. A C callee asserts the account count, signers and positions. 65 metas and 5 groups are rejected.

Breaking: the SDK snapshot changes, so existing SDK-2 projects must be recreated.

Linked work

Closes #4. Used by hyperlane-xyz/hyperlane-monorepo#9852.

solana.Invoke, the SDK-2 C runtime and sdk/cpi allowed 16 account metas
and 2 signer groups per CPI; Hyperlane's Sealevel programs need 22 (IGP
PayForGas with quoted accounts) and 17 (fee QuoteFee). Seeds keep 16 per
group, 32 bytes each and 1,024 encoded bytes.

sol_Invoke gets 64-entry meta and 4x16 seed descriptor arrays and is
noinline, so its 2,240-byte frame never lands in a caller's frame.
cpi.Metas keeps 16 records inline and moves them to one 576-byte heap
array at the 17th Add, so small CPIs keep their frame and zeroing cost.

examples/cpi-limits and TestCPILimitsSBF run 3 to 64 metas with up to
four PDA signers on fogo-v0 and solana-v3 against a C callee that checks
its account count, signers and every repeated-account position, plus the
65-meta and 5-group errors through the builders and the raw boundary.
The escrow, full-swap and tutorial SDK snapshots are refreshed; the check
corpus records the 33 C hashes the runtime change moved.
results/compiler/2026-10-19-cpi-limits holds the before/after CU of the
CPI-limits harness and the existing escrow, full-swap and tutorial suites,
static frame sizes, and the fresh-rebuild metrics. The full swap's ELFs
changed (fogo-v0 bcd9253e, solana-v3 86f0ed15), so verify_rebuild.py now
defaults to this reference. HANDOFF records the SDK snapshot change.
@paulbalaji paulbalaji changed the title Raise outgoing CPI bounds to 64 metas and 4 signer groups feat(sdk)!: raise CPI limits to 64 metas and 4 signer groups Oct 19, 2026
@Mister-Meeseeks
Mister-Meeseeks merged commit bd4d0e9 into CrocSwap:main Oct 19, 2026
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.

CPI limits (16 metas, 2 signer groups) are below what the runtime allows

2 participants