Expand description
§paralock-evm
The EVM layer of Paralock — trustless swaps between shielded ZEC and stablecoins on EVM
chains (Tempo, Base, Ethereum, Arbitrum, Robinhood Chain, HyperEVM). It is the Rust counterpart of the TypeScript
package @paralock/evm, built on alloy:
EvmHtlcClientforParalockHTLC(htlc mode) andAdaptorEscrowClientforParalockAdaptorEscrow(adaptor mode): exact approvals, lock, claim, refund, lock lookups with block and transaction, outcomes (empty / active / claimed with the preimage or signature / refunded), EVM time and balances;- the protocol math they rely on (
hashlock_of,HtlcSwap::commitment,AdaptorSwap::id,claim_digest,ClaimSignaturenormalization), identical to the contracts and tospec/vectors/evm.json; EvmConnection: chain-id verification before anything is sent, simulation with typed revert decoding (EvmError::TransactionReverted,RevertReason), gas and fee estimation with a fee cap, process-wide nonce management, receipt waits with per-call timeouts (EvmConnection::send_and_confirm_with), fee bumps that replace a stuck transaction (EvmConnection::bump), status lookups (EvmConnection::transaction_status), and bounded retries with backoff on transport errors and 429/5xx. Every error raised after a transaction was signed carries its hash (EvmError::tx_hash);- escrow address checks against the embedded bytecode (
EvmConnection::verify_escrow_code); - Tempo transactions that pay gas in a TIP-20 fee token, through Tempo’s official
tempo-alloy(featuretempo, on by default; opt out withdefault-features = falseif you don’t need fee tokens; seetempo); KNOWN_NETWORKS(verified public networks and stablecoins) andTESTNET_DEPLOYMENTS(Paralock’s public testnet contracts), anddeploy_paralock_contractsfor local chains.
The clients need a Tokio runtime. Amounts are token base units (alloy::primitives::U256; every supported
stablecoin has 6 decimals) and expiries are Unix seconds of EVM block time.
use paralock_evm::{EvmConfig, EvmConnection, EvmHtlcClient, HtlcSwap, ScanConfig, testnet_deployment};
use alloy::primitives::{B256, U256};
let deployment = testnet_deployment(84532).expect("Base Sepolia");
let config = EvmConfig::new("https://sepolia.base.org", 84532).with_private_key("0x…")?;
let conn = EvmConnection::connect(config).await?; // verifies the chain id
let htlc = EvmHtlcClient::new(conn.clone(), deployment.htlc, ScanConfig::from_block(deployment.start_block));
let preimage = B256::random();
let swap = HtlcSwap {
hashlock: paralock_evm::hashlock_of(&preimage),
token: deployment.quote_token_address().expect("USDC"),
sender: conn.address().expect("signer"),
recipient: "0x36e33698492d087ee35db0830ba305faf075d087".parse().expect("address"),
amount: U256::from(25_000_000u64), // 25 USDC
expiry: htlc.now().await? + 3_600,
};
htlc.approve_and_lock(&swap).await?;
println!("{:?}", htlc.outcome(swap.hashlock).await?);The code is experimental and not audited.
Re-exports§
pub use artifacts::ContractArtifact;pub use artifacts::ParalockContract;pub use networks::EvmChainName;pub use networks::KNOWN_NETWORKS;pub use networks::KnownNetwork;pub use networks::ParalockDeployment;pub use networks::TESTNET_DEPLOYMENTS;pub use networks::TestnetDeployment;pub use networks::known_network;pub use networks::known_networks;pub use networks::testnet_deployment;pub use tempo::ANVIL_TEMPO_CHAIN_ID;pub use tempo::TEMPO_CHAIN_IDS;pub use tempo::TEMPO_TOKENS;pub use tempo::TempoTokens;pub use tempo::is_tempo_chain_id;pub use tempo::is_tip20_address;pub use alloy;
Modules§
- artifacts
- The compiled Paralock contracts (ABI, creation and runtime bytecode), embedded from
artifacts/*.json. - bindings
- Typed ABI bindings (
alloy::sol!) for the Paralock contracts and the token interfaces the clients use. - networks
- Public EVM networks Paralock knows, and its public testnet deployments.
- tempo
- Tempo specifics: chain ids, TIP-20 addresses and precompiles.
Structs§
- Adaptor
Escrow Client - Client for a deployed
ParalockAdaptorEscrowon any EVM chain (TIP-20 on Tempo, ERC-20 elsewhere). - Adaptor
Lock - Result of
AdaptorEscrowClient::lock: the transaction and the swap id. - Adaptor
Lock Receipt - Result of
AdaptorEscrowClient::approve_and_lock: the approval (if one was needed), the lock and the swap id. - Adaptor
Swap - On-chain parameters of an adaptor-mode swap, mirroring
ParalockAdaptorEscrow.Swap. - Block
Info - Number, timestamp and hash of a block.
- Claim
Signature - A secp256k1 ECDSA signature in the form
ParalockAdaptorEscrow.claimtakes:vis 27 or 28 andsis low. - Deploy
Options - Options of
deploy_paralock_contracts. - Deploy
Result - Result of
deploy_paralock_contracts. - EvmConfig
- How to reach an EVM chain, which account signs, and the client’s safety limits.
- EvmConnection
- A connection to one EVM chain: an RPC endpoint whose chain id has been verified, and an optional signer.
- EvmHtlc
Client - Client for a deployed
ParalockHTLCon any EVM chain (TIP-20 on Tempo, ERC-20 elsewhere). - EvmSigner
- The account that signs transactions: a local private key, or any alloy
TxSigner(a KMS such asalloy-signer-aws/alloy-signer-gcp, a Ledger, a remote signer, …). - Htlc
State - On-chain state of a hashlock.
- Htlc
Swap - On-chain parameters of an htlc-mode swap, mirroring
ParalockHTLC.Swap. - Lock
Info - A lock read back from the chain (rebuilt from its
Lockedevent), with where it was mined. - Lock
Receipt - Result of
approve_and_lock: the approval (if one was needed) and the lock. - Previous
Deployment - An earlier deployment to reuse where it is still current.
- Reused
- What
deploy_paralock_contractskept instead of creating. - Revert
Reason - A decoded revert: custom error,
Error(string)orPanic(uint256). - Scan
Config - Where event scans start and how many blocks one
eth_getLogsrequest may span. - SentTx
- A transaction this process signed and broadcast (
EvmConnection::submit): everything needed to wait for it (EvmConnection::wait_for_sent), look it up (EvmConnection::transaction_status) or replace it with higher fees and the same nonce (EvmConnection::bump). - TxRequest
- A transaction to send through
EvmConnection::send. - TxResult
- A mined transaction’s receipt: successful, except inside
TxStatus::Reverted.
Enums§
- Escrow
Status - Status of an escrow entry. An entry is never reusable once settled (claimed or refunded).
- EvmError
- Everything that can go wrong in this crate.
- Outcome
- Where an escrow entry stands, without waiting.
Claimedcarries what the claim revealed: the HTLC preimage (HtlcOutcome) or the adaptor escrow’s release signature (AdaptorOutcome). - Revert
Source - Which contract a revert came from, to resolve error names shared between contracts (
InvalidAmount(), …). - Signature
Error - Why a claim signature was rejected.
- TxStatus
- Where a transaction stands, from
EvmConnection::transaction_status.
Constants§
- CLAIM_
TYPEHASH keccak256("ParalockAdaptorClaim"): the claim digest’s domain tag (ParalockAdaptorEscrow.CLAIM_TYPEHASH).- HTLC_
EMPTY_ STATE - The state word of a hashlock that was never used.
- HTLC_
SETTLED_ STATE ParalockHTLC.SETTLED: the state word of a claimed or refunded hashlock.- LOCAL_
MINT_ AMOUNT - 1,000,000,000 USD (6 decimals): what
Deploy.s.solmints per account. - SECP256
K1_ N - secp256k1 group order
n. - SECP256
K1_ N_ HALF floor(n / 2): the largest canonical (low)sthe adaptor escrow accepts.
Functions§
- adaptor_
swap_ id - The adaptor escrow id of
swap(seeAdaptorSwap::id). - address_
of_ public_ key - The EVM address of a secp256k1 public key given as SEC1 bytes (33-byte compressed or 65-byte uncompressed):
keccak256(uncompressed point without the 0x04 prefix)[12..32]. Use it to check that an adaptor swap’ssignermatches the one-time key’s public key. - claim_
digest keccak256(abi.encode(CLAIM_TYPEHASH, chainId, contract, id)): the raw 32-byte digest the swap’s signer signs (no EIP-191 or EIP-712 prefix). Bound to the chain and the escrow contract, so a signature cannot be replayed elsewhere.- commitment_
of keccak256(abi.encode(swap))of an htlc-mode swap (seeHtlcSwap::commitment).- deploy_
paralock_ contracts - Deploys
ParalockHTLC,ParalockAdaptorEscrowand a local stablecoin from the embedded artifacts, the waycontracts/script/Deploy.s.soldoes on the Paralock devnet, without Foundry: - fetch_
chain_ id - The chain id served at
rpc_url(oneeth_chainIdrequest with the default timeout and retries). - hashlock_
of sha256(preimage): the hashlock of a 32-byte secret (the contract’s check and the Zcash script’sOP_SHA256).- local_
ousd_ salt - Salt of the local OUSD stand-in, as in
contracts/script/Deploy.s.sol:keccak256("paralock/ousd"). - random_
salt - 32 random bytes from the operating system’s RNG, for
AdaptorSwap::salt.
Type Aliases§
- Adaptor
Outcome Outcomeof an adaptor-mode swap:Claimedcarries the published release signature.- Htlc
Outcome Outcomeof an htlc-mode swap:Claimedcarries the 32-byte preimage.