Across V2 Learning Session: Contents
Across V2 Features
Smart Contract Architecture
Contract Breakdown: Hub Pool
Contract Breakdown: Spoke Pool
Contract Breakdown: Chain Adapters
Contract Breakdown: Config Store
Example Fills
Before going into how the bundling works for pool rebalances, relayer refunds and slow relays let’s go through some sample transactions to build an intuition around how the contracts and users interact with each other.
EG 1: Simple fill
EG 2.a: Partial Fill + Slow relay + relayer refund
EG 2.b: Partial Fill + Slow relay + relayer refund
EG 2.c: Partial Fill + Slow relay + relayer refund
Bundles all the things!
Bundles: overview
Primer on Merkle trees and proofs
Primer on Merkle trees and proofs
Primer on Merkle trees and proofs
Primer on Merkle trees and proofs
Primer on Merkle trees and proofs
[
"0xfdc2f9fada1fd2964202b46150f246428cbaffc33dabdd4e2ade6b4bb31892fb",
"0x834d97d1785331b3630a1316b795c6bba7fe967a36eb44066df777c0e3844447"
]
Primer on Merkle trees and proofs
Data Bundles: Overview
Data Bundles: Pool Rebalance Leaf
Data Bundles: Pool Rebalance Leaf
struct PoolRebalanceLeaf {
// This is used to know which chain to send cross-chain transactions to (and which SpokePool to send to).
uint256 chainId;
// Total LP fee amount per token in this bundle, encompassing all associated bundled relays.
uint256[] bundleLpFees;
// Represents the amount to push to or pull from the SpokePool. If +, the pool pays the SpokePool. If negative
// the SpokePool pays the HubPool. There can be arbitrarily complex rebalancing rules defined offchain. This
// number is only nonzero when the rules indicate that a rebalancing action should occur. When a rebalance does
// occur, runningBalances must be set to zero for this token and netSendAmounts should be set to the previous
// runningBalances + relays - deposits in this bundle. If non-zero then it must be set on the SpokePool's
// RelayerRefundLeaf amountToReturn as -1 * this value to show if funds are being sent from or to the SpokePool.
int256[] netSendAmounts;
// This is only here to be emitted in an event to track a running unpaid balance between the L2 pool and the L1
// pool. A positive number indicates that the HubPool owes the SpokePool funds. A negative number indicates that
// the SpokePool owes the HubPool funds. See the comment above for the dynamics of this and netSendAmounts.
int256[] runningBalances;
// Used by data worker to mark which leaves should relay roots to SpokePools, and to otherwise organize leaves.
// For example, each leaf should contain all the rebalance information for a single chain, but in the case where
// the list of l1Tokens is very large such that they all can't fit into a single leaf that can be executed under
// the block gas limit, then the data worker can use this groupIndex to organize them. Any leaves with
// a groupIndex equal to 0 will relay roots to the SpokePool, so the data worker should ensure that only one
// leaf for a specific chainId should have a groupIndex equal to 0.
uint256 groupIndex;
// Used as the index in the bitmap to track whether this leaf has been executed or not.
uint8 leafId;
// The bundleLpFees, netSendAmounts, and runningBalances are required to be the same length. They are parallel
// arrays for the given chainId and should be ordered by the l1Tokens field. All whitelisted tokens with nonzero
// relays on this chain in this bundle in the order of whitelisting.
address[] l1Tokens;
}
Data Bundles: Relayer Refund Leaf
Data Bundles: Relayer Refund Leaf
struct RelayerRefundLeaf {
// This is the amount to return to the HubPool. This occurs when there is a PoolRebalanceLeaf netSendAmount that
// is negative. This is just the negative of this value.
uint256 amountToReturn;
// Used to verify that this is being executed on the correct destination chainId.
uint256 chainId;
// This array designates how much each of those addresses should be refunded.
uint256[] refundAmounts;
// Used as the index in the bitmap to track whether this leaf has been executed or not.
uint32 leafId;
// The associated L2TokenAddress that these claims apply to.
address l2TokenAddress;
// Must be same length as refundAmounts and designates each address that must be refunded.
address[] refundAddresses;
}
Data Bundles: Slow Relay Leaf
Data Bundles: Slow Relay Leafs
struct RelayData {
// The address that made the deposit on the origin chain.
address depositor;
// The recipient address on the destination chain.
address recipient;
// The corresponding token address on the destination chain.
address destinationToken;
// The total relay amount before fees are taken out.
uint256 amount;
// Origin chain id.
uint256 originChainId;
// Destination chain id.
uint256 destinationChainId;
// The LP Fee percentage computed by the relayer based on the deposit's quote timestamp
// and the HubPool's utilization.
uint64 realizedLpFeePct;
// The relayer fee percentage specified in the deposit.
uint64 relayerFeePct;
// The id uniquely identifying this deposit on the origin chain.
uint32 depositId;
}
Bundle Construction Example 1
Bundle Construction Example 2
Bundle Construction Example 3
Bundle Construction Example 4
Bundle Construction Example 5
Bundle Construction Example 6
Bundling of Transactions
Bundling of Funds on L1
A word on “netting”
Token Routes
Fees 1: Overview
Fees 1: LP fee 1
Fees 1: LP fee 2
Fees 2: relayerFeePct with in cost of capital
Relayer bot
Hard problems