Security model
Your keys stay with you
Section titled “Your keys stay with you”The keys of your deposit addresses never leave your custody. Your HSM, KMS or MPC signs one thing per address, an EIP-7702 authorization, and only the signature reaches Portuna. Your hot wallets are your own addresses: the service never holds their keys either.
What an authorization allows
Section titled “What an authorization allows”An authorization makes the deposit address run the code of your hot wallet’s delegate on one chain. That code is small and fixed:
- it moves the address’s tokens or native coin only to the hot wallet written into its bytecode;
- it acts only when your batcher calls it, and your batcher runs only for your gas wallet;
- it has no owner, no admin functions, no storage and no upgrade path, so none of this can change later;
- the address keeps receiving tokens and native coin, and keeps its key: you can still send transactions from it.
An authorization that has not been used yet can be submitted by anyone, not only by Portuna: that is how EIP-7702
works. It still installs only your delegate, which pays only your hot wallet. Sign only for the delegate the API
returns for your hot wallet, and check it first with verify-delegate.
An authorization is bound to:
- one chain: the API refuses chain ID
0, which would be valid on every chain; - one nonce: if the address sends any transaction before the authorization is used, it becomes invalid and you sign a new one.
To undo a delegation, the address signs an authorization of the zero address: see Revoking a delegation.
Contracts you can check
Section titled “Contracts you can check”The contracts are open code, created with CREATE2, so each address is a hash of the exact code that lives there.
If the address you compute from the code matches the one on chain and holds code, the code on chain is that code,
with your hot wallet and gas wallet built in. The SDK’s verify-delegate command does the whole check: see
Verifying the delegate and Contracts.
Isolation between partners
Section titled “Isolation between partners”Each partner has its own gas wallet, batcher and delegates. A delegate obeys only its partner’s batcher, and a batcher only its partner’s gas wallet, so one partner cannot trigger, redirect or block another’s sweeps. The service, in turn:
- accepts an authorization only if it is signed by the deposit address itself, for the delegate of the hot wallet in the request, and for the chain of the request;
- checks each address’s delegation and simulates every batch before sending it;
- sweeps only the tokens listed for the chain;
- trusts only the receipts of its own transactions and the events of your own batcher.
No contract or address of ours is shared between partners, so no explorer page lists all of them together. The code is the same for everyone and public, though, so a determined analyst can find every deployment by its bytecode.
Your gas wallet
Section titled “Your gas wallet”The gas wallet is the one address the service signs for: it holds the native coin you prepay for gas. Its keys are kept in a separate signing service that signs only the transactions of this protocol: deploying your contracts, your batches, your revocations and the withdrawal of the fees due, within caps on gas and fee and a daily budget per chain. Keep a few days of gas on it, not more, and set a low balance alert.
API keys and webhooks
Section titled “API keys and webhooks”- API keys are shown once and stored only as hashes. Keep them on your backend; a revoked key stops working at once.
Test keys (
ptn_test_) work only on the testnets, live keys (ptn_live_) only on mainnet. - Webhooks go only to public
httpsURLs and never follow redirects. Each delivery is signed with HMAC-SHA256 and a timestamp: verify it before you trust it.