You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
docs: update documentation for deferred execution and sync devnet program ID
Update all documentation to cover the new deferred execution feature
(Authorize, ExecuteDeferred, ReclaimDeferred) and sync program ID to
devnet address FLb7fyAtkfA4TSa2uYcAT8QKHd2pkoMHgmqfnXFXo7ao across
22 files including SDK, tests, docs, and build scripts.
Copy file name to clipboardExpand all lines: README.md
+21-7Lines changed: 21 additions & 7 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -2,7 +2,7 @@
2
2
3
3
A high-performance smart wallet program on Solana with passkey (WebAuthn/Secp256r1) authentication, role-based access control, session keys, and replay-safe odometer counters. Built with [pinocchio](https://github.com/febo/pinocchio) for zero-copy serialization.
@@ -15,6 +15,7 @@ A high-performance smart wallet program on Solana with passkey (WebAuthn/Secp256
15
15
-**Clock-Based Slot Freshness**: 150-slot window via `Clock::get()` — no SlotHashes sysvar needed
16
16
-**Zero-Copy Serialization**: Raw byte casting via pinocchio, no Borsh overhead
17
17
-**CompactInstructions**: Index-based instruction packing for multi-call payloads within Solana's 1,232-byte tx limit
18
+
-**Deferred Execution**: 2-transaction flow for payloads exceeding the tx limit (e.g., Jupiter swaps) -- TX1 authorizes via signature, TX2 executes with full inner instruction space (~1,100 bytes)
| Transaction Fee | 0.000005 SOL | 0.000005 SOL | 0.000005 SOL |
31
32
32
-
Session keys are ideal for frequent transactions — they skip the Secp256r1 precompile and use a simple Ed25519 signer, resulting in lower CU and smaller transactions.
33
+
Session keys are ideal for frequent transactions -- they skip the Secp256r1 precompile and use a simple Ed25519 signer, resulting in lower CU and smaller transactions.
34
+
35
+
### Deferred Execution (Large Payloads)
36
+
37
+
For operations exceeding the ~574 bytes available in a single Secp256r1 Execute tx (e.g., Jupiter swaps):
38
+
39
+
| Metric | Immediate Execute | Deferred (2 txs) |
40
+
|---|---|---|
41
+
| Total CU | 12,441 | 18,613 (11,709 + 6,904) |
42
+
| Inner Ix Capacity |~574 bytes |~1,100 bytes (1.9x) |
43
+
| Tx Fee | 0.000005 SOL | 0.00001 SOL |
44
+
| Temp Rent | -- | 0.00212 SOL (refunded) |
33
45
34
46
See [docs/Costs.md](docs/Costs.md) for full cost analysis, session key costs, and CU benchmarks for all instructions.
35
47
@@ -45,6 +57,7 @@ See [docs/Costs.md](docs/Costs.md) for full cost analysis, session key costs, an
pubinstructions_hash: [u8; 32], // SHA256 of serialized compact instructions
125
+
pubaccounts_hash: [u8; 32], // SHA256 of all account pubkeys referenced
126
+
pubwallet:Pubkey, // 32 bytes
127
+
pubauthority:Pubkey, // 32 bytes — the authority that authorized
128
+
pubpayer:Pubkey, // 32 bytes — receives rent refund on close
129
+
pubexpires_at:u64, // Absolute slot at which this expires
130
+
}
131
+
// Total: 1+1+1+5+32+32+32+32+32+8 = 176 bytes
132
+
```
133
+
134
+
Temporary account created during `Authorize` (tx1) and closed during `ExecuteDeferred` (tx2). Uses the authority's odometer counter as a seed nonce, ensuring unique PDAs per authorization. Expired accounts can be reclaimed via `ReclaimDeferred`.
135
+
136
+
### E. Vault PDA
113
137
114
138
Seeds: `["vault", wallet_pubkey]`
115
139
116
140
No data allocated. Holds SOL. Program signs for it via PDA seeds during Execute.
117
141
118
-
## 5. Instructions (6 total)
142
+
## 5. Instructions (9 total)
119
143
120
144
### CreateWallet (discriminator: 0)
121
145
@@ -155,6 +179,35 @@ No data allocated. Holds SOL. Program signs for it via PDA seeds during Execute.
155
179
- Validates expires_at: must be in future, max ~30 days.
Binary format for packing multiple instructions into Execute:
@@ -175,7 +228,32 @@ Overhead per instruction: 4 bytes + num_accounts. Replaces 32-byte pubkeys with
175
228
176
229
For Secp256r1 Execute, the signed payload includes a SHA256 hash of all account pubkeys referenced by the compact instructions. This prevents account reordering attacks where an attacker could swap recipient addresses while keeping the signature valid.
177
230
178
-
## 7. Auth Payload Layout (Secp256r1)
231
+
## 7. Deferred Execution
232
+
233
+
2-transaction flow for payloads exceeding the ~574 bytes available in a single Secp256r1 Execute transaction (e.g., Jupiter swaps with complex routing).
234
+
235
+
### Flow
236
+
237
+
1.**TX1 (Authorize)**: Client computes `instructions_hash = SHA256(packed_compact_instructions)` and `accounts_hash = SHA256(all_referenced_pubkeys)`. These hashes are signed via Secp256r1 and stored in a DeferredExec PDA. The authority's odometer counter is incremented.
238
+
2.**TX2 (ExecuteDeferred)**: Any signer submits the full compact instructions. The program verifies both hashes match, checks expiry, closes the DeferredExec account, and executes via CPI with vault signing.
-**Hash binding**: Both instruction content and account ordering are hash-verified.
250
+
-**Replay protection**: Odometer counter used as PDA seed nonce — each authorization gets a unique PDA.
251
+
-**Expiry**: 10-9,000 slot window (~4s to ~1h). Prevents stale authorizations.
252
+
-**Role gating**: Only Secp256r1 Owner/Admin can authorize.
253
+
-**Close-before-CPI**: DeferredExec account is closed before CPI execution, avoiding stale-pointer issues with `invoke_signed_unchecked`. Transaction reverts atomically if any CPI fails.
254
+
-**Rent recovery**: `ReclaimDeferred` allows original payer to reclaim rent from expired, unexecuted authorizations.
0 commit comments