Conversation
Member
|
failing ci |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Escrow Batch Implementation Summary
What This Implements
EscrowBatchis the batch version of the escrow contract. It lets a deployer define many expected transfers in one escrow, lets one or more nodes reserve different parts of that batch, and lets each node prove that the transfers they reserved were executed before they can collect.The batch now supports mixed payment assets. A single batch can contain ERC20 transfers and native ETH transfers, for example USDC, USDT, and ETH in the same escrow.
The reward and bond token is still one ERC20 token. That token is set by
tokenContract. The payment assets are defined per transfer row.Transfer Model
Each row in the batch is represented by
BatchTransfer:assetTypesays whether the payment is ERC20 or native ETH.assetis the ERC20 token address for ERC20 transfers. For native ETH, it must beaddress(0).recipientandamountdescribe the transfer the node must execute.rewardWeightis the common value used to split rewards and calculate bond requirements. This is needed because raw token amounts across USDC, USDT, and ETH cannot be compared directly. For example,1 etherand1 USDCare not the same value just because they are both represented as integers on-chain.So the contract does not use
amountto split rewards. It usesrewardWeight.The contract does not calculate
rewardWeightby itself. The deployer or frontend supplies it for each transfer row.For a batch where every payment uses the same token,
rewardWeightcan simply match the transfer amount:For mixed-asset batches,
rewardWeightshould be normalized to a common value, usually USD value or reward-token value:The total weight is:
If the total reward is
35 USDC, then the reward split is:If the deployer wants every transfer row to receive the same reward regardless of payment size, every row can use the same weight:
Funding
The deployer funds the batch with:
tokenContract;msg.valuefor rows whereassetType == NATIVE.Native funding must exactly equal the sum of all native ETH transfer amounts.
ERC20 payment assets are transferred from the deployer into the escrow contract.
The contract tracks payment balances per asset, so it knows how much USDC, USDT, ETH, or any other supported asset is still locked in the batch.
Funding is one-shot. Once the batch has been funded, it cannot be re-funded with stale state.
Multi-Node Reservations
Nodess do not have to execute the whole batch.
Each node can call
bond()with the transfer indexes they want to execute. For example:The contract prevents overlap. If a transfer index is already reserved or already completed, another node cannot reserve it.
Each reservation stores:
The minimum bond is calculated from the executor's share of the reward:
The reward share is based on
rewardWeight, not raw token amounts.If a node fails to collect before the deadline, their reservation expires. The reserved transfer indexes become available again, and the forfeited bond is added to the reward pool.
Proof Model
Collection uses one interface:
The array is important because one node may need to prove transfers that landed in different receipts, different transactions, or different blocks.
Each proof has a
proofType:For ERC20 transfers, the proof validates receipt logs.
For native ETH transfers, the proof validates both the transaction and the receipt.
ERC20 Proofs
An ERC20 proof can prove multiple transfer rows from one receipt.
For each ERC20 row, the node provides:
The contract checks that each log proves the exact expected transfer:
asset;fromaddress must be the collecting Nomad;toaddress must match the expected recipient;This means a node cannot claim an old transfer, another sender's transfer, or a transfer from the wrong token contract.
Native ETH Proofs
Native ETH does not emit a standard ERC20
Transferlog, so it needs a different proof shape.For native ETH rows, the contract validates: