Gas efficient routers for L2 applications. With custom contracts that use less calldata than standard methods we can reduce transactions costs for users.
Layer 2 networks share security with mainnet by posting transaction calldata to Layer 1. As a result, Layer 2 users pay their portion of the mainnet gas costs when executing transactions. Layer 1 gas can be >25,000x more expensive than Layer 2 gas, so paying for calldata dominates L2 transaction costs. With custom contracts that use less calldata than standard methods we significantly reduce transaction costs for users.
For three protocols—Aave, Connext, and Superfluid—we deployed a factory contract on Optimism (or Optimism Goerli) which deploys the calldata-optimized routers for that protocol. The factory deploys a unique contract for every combination of methods and parameters that can be hardcoded.
For example, with Aave:
And similarly for Connext and Superfluid.
This means users don't need to specify a function selector, which saves 4 bytes of calldata. This also means users don't need to specify a token address, saving another 32 bytes (20 bytes of non-zero calldata).
Aave lets you specify where to send the receipt tokens (on deposit) or the asset itself (on withdraw). Similarly, Connext lets you specify where to send the asset once bridged. For both of these we assume the user wants to send the asset to themselves so a recipient address is not required, which again saves 32 bytes (20 bytes of non-zero calldata).
Aave, Connext, and wrapping tokens in Superfluid require you to specify an amount of tokens. Instead of specifying exact amounts, users specify amounts as percentages of their balance. If zero bytes of calldata are provided, the full user's balance is used. Any non-empty calldata provided is considered the numerator of a fraction, such that:
From there, we compute the amount to use as userBalance * calldata / denominator
. This lets you specify nearly any amount of tokens with just a few bytes of calldata. The tradeoff is precision: you may not be able to send exactly one token, and must tolerate a small deviation in the amount.
Some protocols may deem this tradeoff unacceptable, and others require rates or other parameters that don't work with this pattern. One such case is creating a flow on Superfluid, which requires specifying a flow rate. In these cases, the user specifies the amount as normal, but with all zero-padding removed. If you wanted to specify a value of 100e6 with this method, the calldata would be 0x05f5e100
. This is just 4 bytes, instead of the standard 32 bytes used by ABI-encoding.