Interoperability: how Arrekta connects to other chains
2026-10-28. Policy plus the pieces built so far. Companion to LAYER_ARCHITECTURE.md and PROTOCOL.md §4.2 and §9.9.
1. Policy
Arrekta is a settlement chain for issued assets. Value moving to or from another chain is where most crypto losses happen: bridges lost billions again in 2026 [1][2][3]. The common failure is that a few keys, or one contract's message validation, can release everything the bridge holds. So the rules are:
- Atomic swaps first. A swap moves no custody: each party locks coins on its own chain under the same hash, and either both claims happen or both refunds do [4][5]. Nobody has to be trusted beyond each chain's own consensus. Arrekta supports swaps with Bitcoin, Ethereum and any chain with SHA-256 or SHA3 hashlocks (§3).
- Proofs, not signatures, for anything else. When another system must learn a Arrekta fact (a deposit, a burn), it checks a finality proof (§2) against Arrekta's checkpoint signer group. This is the light-client model of IBC [6]: the verifier holds a trusted root and checks proofs against it; it does not trust a relayer. Optimistic or zero-knowledge verification of other chains (the BitVM2 approach for Bitcoin [7]) is acceptable later, under the same rule.
- Never an external multisig as the canonical bridge. Arrekta will not endorse, list or integrate a wrapped asset whose only backing is an off-chain m-of-n custodian as "the" Arrekta bridge. Third parties can run such services; the project will not present them as protocol. An issuer that wants a token on two chains issues it natively on both and reconciles supply publicly, as major stablecoin issuers do.
- No VM for bridging. Bridge logic in a general-purpose VM is the attack surface that keeps failing [1][3]. Arrekta keeps its fixed policy language (PROTOCOL.md §4.2); interop needs only hashlocks, timelocks and proofs.
- Operational practice counts, not only the protocol. Garden Finance's HTLC contracts were drained of about $450K in July 2026 through how the liquidity side was run, not through a broken hashlock [8][9]. The swap tools therefore pin every parameter (preimage size, timelock order) and the docs give a checklist (§3.3).
2. Finality proofs (built)
A finality proof (PROTOCOL.md §9.9) shows, with no node, that a transaction is in a block that a signed checkpoint (§9.8) made final:
proof = u8 1 ‖ var tx ‖ merkle branch ‖ headers (tx block … checkpointed block) ‖
hand-over checkpoints ‖ final checkpoint
- Verification:
- the txid is under
headers[0].merkle_root; - the headers link;
- the checkpoint names the last header with a threshold of signatures.
- the txid is under
- Trusted input: only the signer set the verifier starts from, normally the genesis group. Group rotations ride along as hand-over checkpoints, each final under the group before it.
- Proof of work is not checked. Finality comes from the signer group. A verifier that also wants work can check the headers' AuxPoW separately.
- Size: the headers between the transaction's block and the next checkpoint (124 B each; the signer interval is 10 blocks), plus one or two ML-DSA checkpoints. That's typically under 20 KB.
| Where | API |
|---|---|
| Node REST (both nodes) | GET /v1/txs/{txid}/proof → {hex, height, checkpoint_height, signer_set_id, …}; 409 tx-not-final until a checkpoint covers the block |
| Rust | arrekta_core::finality::{build, FinalityProof::verify} |
| Python | arrekta_core.finality, SDK verify_finality_proof, get_finality_proof |
| TypeScript | verifyFinalityProof, decodeFinalityProof, client getFinalityProof (verifies locally) |
| Vectors | core/vectors/finality.json (13 cases, 3 implementations) |
Who uses it:
- an exchange or custodian crediting deposits without running a node;
- an issuer's redemption desk on another chain;
- a contract on Ethereum, through the zk light client below.
2.1 Checking finality proofs on Ethereum (built; backend pending)
Ethereum can't run the check directly:
- Arrekta hashes with SHA3-256 and SHAKE. The EVM's
keccak256is pre-standard Keccak (different padding), so even Arrekta's merkle and header hashes can't be recomputed cheaply. - Checkpoints are signed with ML-DSA-65, and the EVM has no ML-DSA.
So the check runs in a zero-knowledge VM, and Ethereum only verifies the result:
finality proof ──▶ SP1 guest (zk/program): arrekta_core::finality::FinalityProof::verify, unchanged
│ commits ABI-encoded FinalityPublicValues
▼
ArrektaLightClient.submit(publicValues, proof) ──▶ IFinalityBackend.verify ──▶ signer-set rules ──▶ finalTxs
The guest (zk/program) is arrekta-core itself, built with default-features = false:
- What it contains: only the codec, hashing, ML-DSA/FN-DSA verification, checkpoints and
finality. Signing, chain state, the mempool and the RNG are behind the
signandnodefeatures and stay out. - Speed: SP1's patched
sha3andsha2crates [13] turn every Keccak-f and SHA-256 permutation into a zkVM precompile, including the SHAKE inside ML-DSA. - Same code everywhere: the guest, the nodes and the SDK conformance tests run the same verifier on the same vectors.
Public values (zk/lib, version 1), what a contract learns:
- the network magic;
- the starting signer set, every hand-over (height and new set), and the final set;
- the checkpoint height and hash;
- the transaction's height, block, txid, inputs (outpoints), outputs (asset, amount, lock bytes) and memo.
A deposit or burn can therefore be acted on in the same Ethereum transaction, with no Arrekta parsing in Solidity.
ArrektaLightClient (contracts/src):
- Trust: it starts from one signer set, the genesis group, and learns rotations from the hand-overs that proofs carry.
- Signer-set rules: a set signs heights in
[activeFrom, retiredAt]and retires exactly once, so a second hand-over from the same set is a fork and is rejected. - No admin: no owner and no upgrade path (rule 3). A new backend means a new deployment, which re-learns rotations from ordinary proofs.
The backend slot (IFinalityBackend) is the only part still to choose:
| Backend | Status | Trade-off |
|---|---|---|
SP1FinalityBackend + SP1 Groth16/PLONK verifier | ready to deploy | cheapest gas today; the BN254 wrapper is not post-quantum |
| SP1 + a STARK verifier on Ethereum | when available | post-quantum end to end; more gas |
| Native ML-DSA (an EVM precompile) | if Ethereum adds one | no zk at all; a backend that runs the checks itself |
SP1MockVerifier | tests only | accepts empty proofs |
Tooling (zk/script, binary arrekta-finality-zk):
vkeyprints the program key thatSP1FinalityBackendpins;executeruns every finality vector in the zkVM executor, and the output must match the native computation byte for byte;fixtureswrites the Foundry fixtures;provemakes a real proof, which needs Docker or native gnark and is slow.
Measured with the 13 shared vectors:
- Cost in the zkVM: a proof with one checkpoint, so two ML-DSA-65 signatures, runs in about 3.0 million zkVM cycles; one with a hand-over takes about 6.0 million. That is small for SP1, thanks to the accelerated Keccak.
- Gas on Ethereum:
submititself costs about 45,000–120,000 gas, before the backend's verifier. SP1's Groth16 verifier adds roughly a few hundred thousand gas. - Rejections: all 9 invalid vectors are rejected inside the zkVM.
Why a panicked run can't verify:
- A panic inside the guest ends the run with a non-zero exit code, not an executor error.
- SP1's verifiers reject non-zero exit codes, both the SDK and the on-chain
SP1VerifierGroth16/SP1VerifierPlonkfrom v6.1.0. - The guest commits its public values only after verification succeeds.
So a run on an invalid proof never yields public values that verify.
Versions: SP1 6.9.0, held in lockstep in zk/Cargo.toml and zk/script/Cargo.toml until 6.10
is two weeks old; Foundry 1.8.5. Program key for this build:
0x00162e80eb057bbe659fa86ecde60c6ab51f2706f2140333bccfad5f036bb170. Any change to arrekta-core's
verifier changes it, so redeploy SP1FinalityBackend with the new key. For a deployment, take the
key from a reproducible build (cargo prove build --docker in zk/program) so anyone can rebuild
the program and get the same key.
3. Atomic swaps with Bitcoin (built)
3.1 Why SHA-256
Both legs of a swap must lock to the same digest. Arrekta's original hashlock was SHA3-256 only.
Bitcoin script offers SHA-256, RIPEMD-160 and HASH160 but no SHA3, and Ethereum has a SHA-256 precompile
and a Keccak-256 opcode (Keccak is not the standardised SHA3-256). So a swap with either chain was impossible. Policy op 9,
SHA256(digest) (PROTOCOL.md §4.2, v1.3), fixes that. Pre-mainnet, it is part of the launch rules,
not a fork.
The quantum side is unchanged. A hashlock's security is preimage resistance, and SHA-256 keeps about 128-bit security against Grover search, the same margin as SHA3-256.
3.2 The two legs
-
Arrekta leg:
htlc_sha256(receiver, refund, H, timeout_height):or(and(key(receiver), sha256(H)), and(key(refund), after(timeout_height))). -
Bitcoin leg: P2WSH, the BIP 199 shape [10] with the preimage size pinned:
OP_IF OP_SIZE 32 OP_EQUALVERIFY OP_SHA256 <H> OP_EQUALVERIFY <claim_pubkey> OP_ELSE <locktime> OP_CHECKLOCKTIMEVERIFY OP_DROP <refund_pubkey> OP_ENDIF OP_CHECKSIGWhy
OP_SIZE 32: Arrekta accepts only 32-byte preimages. Without the size check, the secret holder could pick a longer secret, claim the BTC, and leave the counterparty with a preimage that can't claim the ARRK. Decred's cross-chain swap contracts pin the size for the same reason [11].
| SDK | Functions |
|---|---|
TypeScript (swap.ts) | newSwapSecret, arrkSwapPolicy, btcHtlcScript, p2wshAddress, p2wshScriptPubkey, btcClaimWitness, btcRefundWitness, findSwapPreimage |
Python (arrekta_sdk.swap) | the same, snake_case |
Both SDKs reproduce BIP 173's P2WSH test vector and a shared HTLC script fixture. Bitcoin signing stays in the Bitcoin wallet.
3.3 Running a swap safely
Alice holds ARRK and wants BTC; Bob holds BTC.
- Alice draws a secret:
preimage, H = new_swap_secret(). - Alice locks first, on the chain with the later refund: ARRK to
htlc_sha256(bob, alice, H, T_arrk). - Bob checks Alice's output (a finality proof makes this node-free) and locks BTC to the P2WSH
script with
claim = alice,refund = boband locktimeT_btc.T_btcmust expire well beforeT_arrk. - Alice claims the BTC, revealing the preimage in her witness.
- Bob reads it with
find_swap_preimageand claims the ARRK beforeT_arrk.
Checklist:
- the secret holder always gets the longer timeout;
- the gap between timeouts must cover the time to confirm on both chains plus watcher downtime (hours, not minutes);
- confirm the counterparty's lock to finality (a Arrekta checkpoint; Bitcoin depth) before locking yours;
- run a watcher, because a swap does not force settlement and the losing side of a price move may simply stop [12].
3.4 The Ethereum leg (built; audit before real funds)
contracts/src/ArrektaHTLC.sol is the Ethereum counterpart of htlc_sha256. Its shape (lock,
claim with the secret, refund after expiry) follows the audited Garden HTLCs [14][15]:
lock(recipient, token, amount, hash, deadline)takes ETH (token = 0) or any ERC-20;claim(id, preimage)works whilenow < deadlineand emits the preimage;refund(id)works oncenow ≥ deadline.
Choices:
- The preimage is a
bytes32, so Arrekta's 32-byte rule holds by type. - Claim and refund windows don't overlap, so the two can't race.
- Fee-on-transfer tokens are rejected: the escrow must receive exactly
amount. - No owner, fees or upgrades. Anyone may relay a claim or refund, but funds move only to the recorded parties.
- The id binds every parameter plus the chain id and contract address.
Foundry tests cover:
- the ETH and ERC-20 paths;
- every revert;
- fuzzed wrong preimages;
- a recipient that refuses ETH (the sender can still refund);
- the shared secret fixture, checked against the Arrekta
htlc_sha256vector incore/vectors/base_layer.json.
Garden's July 2026 incident [8] is the reminder that operating the liquidity side carries its own risk, separate from the contract.
4. Not built, and why
| Item | Status |
|---|---|
| A production proof backend for the Ethereum light client | §2.1: the guest, public values, light client and tests are built. Choose Groth16 now (not post-quantum) or wait for a STARK verifier or an ML-DSA precompile |
| Verifying Bitcoin or Ethereum on Arrekta | Would need new consensus (a proof-verifying lock kind, reserved kinds 16–127). Only if the market asks, and only light-client or optimistic designs (rule 2) |
| IBC compatibility | IBC v2 [6] is the closest model. An IBC client for Arrekta can be built on finality proofs without consensus change; deferred until there is a counterparty |
| Wrapped ARRK on other chains | Only behind rule 3; nothing planned |
Sources
- 1inch, "The biggest bridge hacks in 2026": https://1inch.com/blog/post/the-biggest-bridge-hacks-in-2026
- Halborn, "Month in review: top DeFi hacks of February 2026" (CrossCurve message spoofing): https://www.halborn.com/blog/post/month-in-review-top-defi-hacks-of-february-2026
- BlockEden, "Cross-chain bridges in 2026: why are we still losing billions?": https://blockeden.xyz/forum/t/cross-chain-bridges-in-2026-why-are-we-still-losing-billions/4095
- Garden Finance, "Atomic swap protocols in 2026": https://garden.finance/blog/atomic-swap-protocols-in-2026, and contracts overview: https://docs.garden.finance/contracts/overview
- Chainlink education hub, "Atomic swaps": https://chain.link/education-hub/atomic-swaps
- IBC v2 specification: https://docs.cosmos.network/ibc/next/spec/IBC_V2/README
- BitVM2 bridge paper, IACR ePrint 2025/1158: https://eprint.iacr.org/2025/1158
- KuCoin, "Garden Finance HTLC exploit: $450K USDT stolen": https://www.kucoin.com/blog/in-garden-finance-htlc-exploit-450k-usdt-stolen
- Blockworks Research, "Bridging BTC: multisigs and BitVM": https://blockworks-research.beehiiv.com/p/bridging-btc-multisigs-bitvm
- BIP 199, Hashed Time-Locked Contract transactions: https://github.com/bitcoin/bips/blob/master/bip-0199.mediawiki; BIP 65 (CLTV) and BIP 173 (bech32), same repository
- Decred atomic swap tool and contracts: https://github.com/decred/atomicswap
- EPFL, "A game-theoretic analysis of cross-chain atomic swaps with HTLCs": https://infoscience.epfl.ch/record/291005
- SP1 docs, "Cryptography precompiles" (keccak permute syscall, patched sha2/sha3 crates): https://docs.succinct.xyz/docs/sp1/optimizing-programs/precompiles; verifier contracts incl.
SP1MockVerifier: https://github.com/succinctlabs/sp1-contracts - OtterSec, Garden HTLC swapper security audit: https://garden.finance/blog/garden-htlc-swapper-security-audit-ottersec
- Code4rena, Garden competitive audit (Nov 2025, NativeHTLC.sol and related contracts): https://code4rena.com/reports/2025-11-garden