Repository navigation
Releases
v0.5.106
What's Changed
- fix: 0.5.105 — QA 0.5.104 open items (gasless project, revoke code, native MFA close, Smart Account held grant) by @Oscorped in #626
Full Changelog: v0.5.105...v0.5.106
v0.5.105
What's Changed
Full Changelog: v0.5.104...v0.5.105
v0.5.104
What's Changed
Full Changelog: v0.5.103...v0.5.104
v0.5.103
What's Changed
- 0.5.102: QA findings on 0.5.101 (two reports) and the wrapping-secret custody guard by @Oscorped in #622
Full Changelog: v0.5.102...v0.5.103
v0.5.102
What's Changed
Full Changelog: v0.5.101...v0.5.102
v0.5.101
What's Changed
Full Changelog: v0.5.100...v0.5.101
v0.5.100
What's Changed
- 0.5.99: 1Click hold settles before network reads; restored LI.FI journal records a claimed send by @Oscorped in #619
Full Changelog: v0.5.99...v0.5.100
v0.5.99
Two LOW findings from QA's review of 0.5.98 (Codex, re-checked by Claude). No CRITICAL, HIGH or MEDIUM remained.
- NEAR 1Click, the usage hold in status. Status saved a safe source receipt as
source_observedbut settled the usage hold only at the end, after the 1Click status read and the destination proof. A failure in either left the holdreservedorsubmitted, counting against the daily limit (also on later UTC days) until a status got through. The hold now follows the saved journal first and again right after the source outcome is saved, before any provider or destination read. Deposits submitted before 0.5.98 were never held and are not added to the ledger afterwards, so on the day of the upgrade the daily limit does not count them. - LI.FI, a restored journal with a surviving send claim. A journal restored from before its effect signed, already past its ordinary bound (as 0.5.96 could leave one), could not record a SEND claim that survived the restore: the catch-up's first step (
unsealed→signing_started) was an ordinary transition, refused on every resume, so a send that may have moved money was never recorded or observed. Enteringsigning_startedis now a send step and bounded evidence like the rest of the send; past the ordinary line it can happen at most once per effect, because the release back tounsealedis ordinary and the normal path signs only with room for its whole send. The bounds grow to fit both effects' full catch-up: up to 12 closing transitions past the 512th and then the end (the 525th at most), an open journal up to 1 MiB + 832 KiB and a finished one up to 1 MiB + 896 KiB.
Downgrade. 0.5.98 cannot read an open LI.FI journal with more than 519 transitions, any journal with more than 520, an open one over 1.5 MiB, a finished one over 1 MiB + 576 KiB, or a catch-up signing_started recorded past the 512th transition.
v0.5.98
Fixes from QA's second independent review (Codex, re-checked by Claude) of 0.5.97, and the NEAR 1Click owner-policy gap found while preparing it.
- NEAR 1Click under the owner policy.
oneclick source submitnever loaded the owner's active allowlist policy: no lane admission, per-operation or daily cap, recipient pin or usage hold applied, and a missing or expired policy did not stop it. Each lane is now its ownbridgemechanism on the payer's origin asset,{ "provider": "near-1click", "reference": "<lane>.v1" }on Base USDC or Ethereum ETH. Submit checks the active policy (its EVM account must be the payer), the lane, the caps and the lane'srecipientspin before any quote, checks them again after the foreground consent, and holds the principal in the usage ledger before signing. A failure before the seal releases the hold; the journal refuses to seal after the effective deadline (oneclick_source_quote_expired_before_seal) or once the run's hold is no longer held (oneclick_source_usage_hold_not_held), and status releases an unsigned record's hold once that deadline has passed. Status settles the hold from the journal (submitted,unknown_finality,finalized,failed_confirmed_revert,released_unsubmitted) and reports it asusageHold. Profiles that use 1Click need a policy revision admitting their lanes; until then submit refuses withAPN_ALLOWLIST_REFUSEDandoneclick_source_active_owner_policy_required,oneclick_source_mechanism_not_admittedoroneclick_source_policy_refused(asset, rail or lane not admitted, a cap or the policy window, named incause). Records written before 0.5.98 hold nothing and are unchanged. - Stargate V2 native lane (Ethereum ETH to Unichain), expiry before the send marker. After approval, nothing rechecked the prepared expiry until the send marker, so a wait for the usage hold, the signer check or the signing lock could carry the send past it. The expiry is now checked again after signing, as on the token lane; an operation that expired by then is refused with
expired_before_marker. Any refusal between the usage hold and the send marker (a changed signer, a signing failure, a bad signed transaction, that expiry) now releases the hold at once, since nothing was sent, and the operation must be prepared again: a retry of it is refused withAPN_REPREPARE_REQUIRED/usage_released_before_send. - Solana x402, a payment left signed. A later
payof a payment that stopped right after signing checked only the blockhash lifetime and sent it, even if the owner had since changed the allowlist or the Solana x402 policy.paynow checks both again before exposing signed bytes. If either changed, nothing is sent, andobserveends the payment without effect once its lifetime passes. - Delivery trace root value. 0.5.97 tied the trace root to the verified transaction's sender, target and calldata but not its value. The native-fill proof (Linea, Monad, BNB native) and the BNB composite proof now also require the root's value to equal the verified transaction's, and the BNB composite root must carry an explicit value and input. A mismatch is a wrong RPC answer: it is read again on the next resume and the operation stays observable. callTracer reports no transaction hash; the trace is requested by the verified one.
- Owner recipient pins on gasless and swap admissions. An owner's
recipientslist (1 to 16 addresses) can now be written ongaslessandswapadmissions, so the allowlist can restrict who receives money on local gasless transfers on every chain (before: Ethereum and Base only, one address), on the Avalanche facilitator, Coinbase and Ethereum USDT gasless lanes, and on every swap, including a Uniswap swap to another address. A swap is bound by the list on either of its two rows (the asset it spends and the asset it receives); swaps that pay only the owner (Jupiter, Orca, SunSwap) need the owner on the list. An unlisted recipient is refused withAPN_ALLOWLIST_REFUSED/allowlist_recipient_not_admittedat prepare, approval, reservation and first send. The single gaslessrecipientkeeps its meaning; a row cannot carry both (recipient_pin_conflict); Coinbase rows accept either. MetaMask Agent and Smart Account gasless transfers and direct transfers from provider wallets are not admitted by the allowlist at all (their limits are the provider's: Guard policy, the Smart Account permission, the Coinbase wallet's controls), anddocs/allowlist-policy.mdnow states this boundary. Releases up to 0.5.97 cannot read a policy that uses the new fields: do not downgrade a profile after staging one. - Solana x402, the usage hold. The hold was reserved under a second policy load taken after the check against the prepared admission. It is now reserved under the same load that matched it.
- LI.FI journals an earlier release filled. 0.5.96 and earlier wrote journal transitions with no reserve, up to 1 MiB. A journal grown to within about 44 KiB of 1 MiB before its bridge transaction was safe could never record that safe proof under 0.5.97's capacity rules: every resume was refused with
bridge_record_capacity, and the operation stayed open with its claims and usage hold. Evidence a journal can add only a bounded number of times may now pass 1 MiB like the terminal transition, without its read telemetry: an effect's first safe proof, the destination proof, and the loss of an inclusion that was never safe (a reorg; at most once per effect past the line). Ordinary changes still cannot, and a provider hint passes only together with such evidence or the end. An effect now starts its send only when all of its send transitions fit under the ordinary bounds, and every step after signing (sealed,submittingand the save after the send, each at most once per effect) is always recorded, so a journal that reached its ordinary bound mid-send no longer leaves an effect sealed in custody or with its send claimed but unrecorded: it sends, ends at expiry in its usual halt, or is observed. On a two-transaction route the approval signs only when the journal also has room for the bridge's send and the approval's ordinary observations, so a nearly full journal no longer sends the approval and then refuses the bridge on the ordinary path (RPC failures between the two sends can still use that room, and the route then endsfailed_after_approvalat expiry). A guarded WBTC bridge whose run stopped after custody signed the bridge transaction but before the journal recorded it stayed open forever with its usage hold; the next resume now records the seal (signing nothing; a further confirmed resume sends those bytes) and, once the operation has expired, ends it asfailed_after_approvalwith the transaction never sent (an expired unsent WBTC approval, or a bridge-only WBTC route, endsfailed_before_effect). An open journal is now bounded at 1.5 MiB and a finished one at 1 MiB + 576 KiB (9 copies of at most 64 KiB, derived next to the constants). A full journal with an effect leftsigning_startedand nothing sealed now saves the release tounsealedinside its expiry halt (failed_before_effect, orfailed_after_approvalonce the approval is safe) instead of being refused forever. The operation index salvages a damaged bridge journal under the finished-journal bound (1 MiB + 576 KiB) instead of reportingrecord_not_json.
Downgrade. Do not go back below 0.5.98 in the middle of an operation or after staging a policy that uses the new fields:
- 0.5.97 and earlier cannot read an open LI.FI journal larger than 1 MiB, a finished one larger than 1 MiB + 64 KiB, or a lost inclusion or send step recorded past the 512th transition.
- 0.5.97 and earlier refuse a policy with
recipientson agaslessorswapadmission, or a Coinbase gasless admission pinned only byrecipients; once such a revision is staged, they report the profile's whole policy state asAPN_STATE_CORRUPT. - 0.5.97 does not settle 1Click usage holds; holds 0.5.98 took stay open under it.
v0.5.97
Fixes from QA's independent review (Codex, re-checked by QA against dist/) of 0.5.96.
- Owner recipient pins on bridges. An owner's
recipientslist on abridgeadmission, or on one alternative of it, was never checked by LI.FI (Across, Stargate) or by either direct Stargate V2 lane. Any recipient passed, against the documented contract. LI.FI checks the pin at prepare, approval, reservation and first send. The Stargate token lane checks it at prepare, before the approval and the send, and at the usage hold. The Stargate native lane checks it at prepare and at the usage hold taken right before signing, including a retried hold. A recipient the pin does not list is refused withAPN_ALLOWLIST_REFUSED/allowlist_recipient_not_admitted. The lanes that may only pay the owner (BNB, Monad, Linea native; both Stargate lanes) are still bound by the pin: a pin that does not list the owner refuses them. - ETH to BNB (Across + Fly), a run that dies after saving the destination proof. A resume that found a saved proof always wrote
completed. For a savedrecovered_weth,below_floororprotocol_mismatchproof thatcompletedfailed validation on every resume, and since bridges have no abandon, the operation stayed open. A saved proof now settles through the same outcome as a fresh one, and a new proof is saved in the same transition as its end, so a run can no longer die between them. - Linea, Monad and BNB native destinations, a recipient that also spends in the fill block. The recipient's balance change across the block was required to cover the output, so a same-block spend left the operation unprovable forever (it held its profile and account claims), and on BSC turned a delivered fill into
protocol_mismatch. The call trace is now the proof: its root must be the verified transaction itself (sender, target and calldata, with no error), and the delivery call and every call above it must have succeeded. The BNB composite trace now also checks the root's target, and a root that is not the verified transaction is read again on the next resume instead of ending the operation asprotocol_mismatch. The balance change is kept as corroboration; a negative one is stored asnull. - Stargate V2 token lane (OP Mainnet USDC to Polygon), native debit cap. The cap counted value plus gas only. OP Mainnet also charges an L1 data fee and an operator fee on each transaction. Prepare now reads both upper bounds for each signed transaction at one pinned block (
getL1FeeUpperBound,getOperatorFee), stores them, and counts them in the cap, the staged gas ceiling and the balance check. They are read again before the approval, after it and before the send. A failed read refuses. Once the approval has landed, the bridge's budget is charged the approval's real cost from its receipt; without the receipt's fee fields, it is charged its gas limit times its max fee plus the larger of the prepare and before-approval L1 and operator bounds. Optimism's L1 bound is a practical bound at the read block's L1 prices, not a hard maximum. The consent screen shows the bounds. Operations are now record v6. v5 records stay readable, but their only new signature can be the owner-consented allowance revoke in cleanup:op_stack_fees_unbound_repreparebefore the approval, and cleanup once the approval has landed. A transient RPC error before the send now keeps the operation for the next run instead of sending it to cleanup; a reverted call or estimate is not transient and still goes to cleanup with its own reason. A usage hold that never reached its send marker is released asfailed_before_effecton expiry, on the v5 refusal and when cleanup ends. - Stargate V2 token lane, approval window. With an existing allowance the expiry was not checked again between the preflight and the send marker, so a lock wait could carry the send past
expires_at. It is now checked before the marker, and a late send goes to cleanup with reasonexpired_before_marker. - Local gasless (EIP-7702), delegation revoked after a successful transfer. The settlement proof required the delegation to still be in place at the latest head, so a revocation left a sent transfer at
unknown_finality(gasless_receipt_unresolved). The safe receipt and the consumed nonces prove the transfer, and the delegation no longer has to persist: a revoked delegation completes the operation and showsdelegation_persists: false. Delegation to another contract is still refused. - LI.FI bridge journal capacity. Each transition copies the operation's state, so the 1 MiB journal could fill after about 90 transitions. After that every change was refused, including the terminal one, and the operation stayed open with its claims. Transitions are now classed:
- ordinary transitions stop with 128 KiB still free;
- proofs that close the operation keep 32 KiB and up to 7 slots past 512; a provider hint with no room left is carried to the end instead;
- the destination proof is saved together with the operation's end, as its terminal transition, which is always recorded: without read telemetry if that is what does not fit, and in a journal an earlier release filled to 1 MiB, up to 64 KiB past it.
Downgrading in the middle of an operation is unsupported. 0.5.96 and earlier reject these new records:
- a native fill with a short or
nullbalance change; - a Stargate v6 record;
- a gasless record that completed after its delegation was revoked;
- a LI.FI journal longer than 512 transitions, or a finished one larger than 1 MiB.