Time-Weighted Average Market Makers [1] (TWAMM) uniquely enable large trades by distributing them in time, potentially freeing market participants from slippage woes of the Constant Product Automated Market Maker (CPAMM) bonding curve. TWAMMs also simultaneously provide benefits to other market makers, like arbitrageurs in a unique symbiotic relationship.
To realize these benefits, understanding and optimizing TWAMM gas usage is imperative. If gas usage is excessive, both arbitrageurs and large position traders suffer, losing profit opportunities and suffering slippage, respectively.
A high-level analysis of TWAMM pool gas usage from the reference Solidity implementation [2] on the Ethereum Virtual Machine (EVM) is presented herein. The focus is on gaining intuitive understanding of high-level operational parameters of TWAMM and their effect on gas usage, specifically these parameters:
Prior to presenting the effects of these parameters on gas usage, it’s important to have an understanding of TWAMM virtual order execution.
Virtual orders are described extensively in [1] as:
“TWAMM breaks ... long-term orders into infinitely many infinitely small virtual sub-orders
, which trade against the embedded AMM at an even rate over time. ... a closed-form mathematical formula allows us to calculate their cumulative effect only when needed.”
The use of the closed form formula to calculate the cumulative effect and apply it to the contract state is Virtual Order Execution.
Virtual order execution is applicable to regular swaps in addition to LT swaps and any other contract operations affecting reserve values; the following operations in [2] require execution of virtual orders:
Each aforementioned TWAMM operation incurs the gas burden of executing virtual orders, which will be demonstrated as the leading gas usage contributor.
Order Block Interval (OBI) is an explicit parameter on the reference Solidity implementation in [2]. It specifies the number of blocks between the execution of virtual orders and explicitly limits temporal resolution for specifying trades. The temporal resolution limitation arises because the length of an LT-Swap is expressed in integer multiples of the OBI. Thus if the OBI was 10,000 and a user desired an LT-Swap expiring in 7,000 blocks, it would not be possible; the earliest possible expiry would be approximately 10,000 blocks from swap initiation.
Computing the result of the closed-form mathematical formula described in [1] can alternately be described as performing a virtual order execution iteration, where each iteration occurs at a specific block. The block where each iteration occurs is controlled by the OBI and when the pool was deployed. Importantly, OBI will be shown to significantly reduce gas usage by reducing the number of iterations that the closed form mathematical formula need be computed for periods of inactivity during active LT-swaps.
If no TWAMM operations necessitating virtual order execution occur for an arbitrary number of blocks, a.k.a. blocks of inactivity, the next TWAMM operation requiring virtual order execution incurs the cost of executing all the virtual orders since the last such operation. The number of virtual order execution iterations incurred for a given block number in such a scenario can be calculated with the following formula:
Where:
VOE Iterations = Virtual Order Execution Iterations
BN = Block Number
LVOB = Last Virtual Order Block
OBI = Order Block Interval
The inverse relationship in equation (1) between iterations and OBI suggests that for pairs with significant inactivity, larger order block intervals may be appropriate to reduce gas usage. To illustrate this relationship, consider a TWAMM pair last updated at block 1000, the Last Virtual Order Block (LVOB), with a new TWAMM operation requiring virtual order execution issued at the current block, BN, 1201. Equation 1 can be used to plot the number of iterations against the OBI for this 201 block inactivity scenario:
Deploying the reference Solidity contract from [2] on Hardhat’s EVM permits the measurement of gas usage for the top-level contract methods.
To measure the gas used in the 201 block inactivity scenario described above, a single LT-swap transaction is issued to the deployed TWAMM pool. Then 201 blocks are mined with no other transactions against the pool. Finally, an explicit call to the pool contract’s execute virtual orders method is made. The transaction receipt from the EVM reports the gas used by the execute virtual orders transaction.
Note:
Figure 2 below shows the measured gas to execute virtual orders in a sweep of OBI values from 1 to 100 for the 201 block inactivity scenario during a single active LT-swap:
The results of Figure 2.0 clearly indicate that choosing larger block intervals offers significant reduction in gas usage for all transactions.
The primary downside to choosing larger values of OBI is the previously mentioned reduction in temporal resolution for LT-swap duration and expiry. Another effect of larger OBI values, beyond the scope of this discussion, is that the minimum amount sold in a swap transaction must be increased to avoid losses due to finite precision arithmetic errors—this effect is illustrated in [3] (see figures “Loss & Constant Product Error for Varying Swap Amounts” and “Loss for Varying Swap Amounts”).
Another important factor in TWAMM’s gas usage is the LT-Swap scenario. Real world TWAMM use would include the situation where there are one or more active LT swaps, offset, and also occurring in opposite directions.
Consider a TWAMM pool consisting of Token A and Token B. Direction in this case refers to a swap from Token A to Token B—the opposite direction would be from Token B to Token A. Figure 3.0 below illustrates some of the important possible LT swap scenarios:
The first scenario in figure 3.0 above represents minimal gas usage in the presence of inactivity because the contract will not perform CPAMM or TWAMM arithmetic, nor will it be modifying a significant amount of the blockchain state. Scenario 2, represents the next best possible scenario, because despite requiring more state updates than scenario 1, the required arithmetic is still inexpensive. Specifically, the contract is performing the less expensive CPAMM arithmetic to execute virtual orders in this scenario. Although unintuitive on inspection, scenario 6 is similar in gas usage to scenario 2, with the exception that there are increased state updates to handle LT-swap expiration (An attack based on expirations is described in [1] and will be addressed in a forthcoming report). The arithmetic performed in scenario 6 is still basic CPAMM and isn’t more expensive than scenario 2 because the sales rate of the 4 concurrent LT-swaps are aggregated into a single rate using the technique described in [4].
Scenarios 3-5 represent the worst case gas usage because in addition to managing additional LT-swap expirations, the reserve update for each virtual order execution is the more complex, gas consuming TWAMM arithmetic defined by the following equations, explained in detail in [1] and [5]:
Given that the worst case gas usage for the contract is scenarios 3-5 from figure 3.0, the experiment used to generate figure 2.0 can be modified to feature two opposing direction LT-swaps. Retaining the values of all other experiment parameters and re-using the same gas measuring procedure as before, the plot of gas usage for a block interval sweep when two opposing direction LT-swaps are active appears below in figure 4.0:
Figure 4.0 shows gas usage approaching 15 million for an OBI of 1—this is the target gas for an entire Ethereum block, post EIP-1559 (network demand can cause this to increase up to 30 million gas). Even at an OBI of 20, virtual order execution after 201 blocks of inactivity uses about 1 million gas.
Note: Hardhat users will recognize that the measurement methodology outlined previously would present challenges in producing figure 4.0, especially the ~15M gas measured for an OBI of 1. The main problem is that Hardhat uses the eth_estimateGas RPC call, which results in timeouts for larger gas measurements. To get around this issue, it’s possible to specify larger timeout delays in Hardhat configuration; 120,000ms proved sufficient in this case.
To visualize the gas used by different amounts of inactivity for a range of OBI values, the same procedure that generated figures 2.0 and 4.0 was replicated. However, OBI was set to fixed values of 1, 10, 30, and 60 while inactivity was swept from 0 to 200 in 10 block steps. Figure 5.0 below shows the results of these measurements:
The gas units depicted in the vertical axis of figure 5.0 are logarithmically scaled—it’s important to note this and the approximately linear growth of gas used as a function of inactivity (there is some deviation from linearity for large OBI values due to the floor and mod operations present in equation 1, but for smaller OBI values this appears to be less of an issue).
Figure 5.0 shows that for the LT-swap scenario in this experiment, 200 blocks of inactivity is near the maximum nominal Ethereum block target gas when OBI is 1, at 15,010,686 gas units. Figure 5.0 again illustrates the significant advantage of larger OBI values, 10 and beyond, in reducing gas usage for inactivity of a TWAMM pool with concurrent opposing direction LT-swaps.
For a specific OBI value and the constraints of the Ethereum blockchain’s target and maximum gas per block, it is important to understand the maximum permissible inactivity before a TWAMM transaction cannot be completed.
Consider the case where OBI is 10, gas usage for the experiment described in the previous section is plotted in figure 6.0 below:
Figure 6.0 Gas usage vs. inactivity measured in blocks for concurrent opposing active LT-swaps in a TWAMM pool with order block intervals 10. Inactivity is swept from 0 to 200 blocks in steps of 10 blocks.
Using the formula for a line, it’s possible to extrapolate and compute an approximate maximum inactivity for a nominal target of 15M gas units and a maximum of 30m gas units:
Assuming an approximate Ethereum average block time of 14s, the maximum inactivity time for a pool with OBI 10 and two concurrent opposite direction LT-swaps is 7.7 and 15.6 hours for the 15 million and 30 million gas limits, respectively.
The 15 and 30 million gas usage bounds represent an upper limit and are impractical for a contract deployed on mainnet that is expected to be used by consumers in addition to institutional customers.
A more practical study would present inactivity as a function of multiples of the average gas used per Uniswap V2 swap transaction. Recent Crypto.com data [6] suggest this average is 154,919 gas units. Using the same pool with an OBI of 10, the delay in time assuming 14s block time for multiples of 154,919 gas appears below in Figure 7.0:
Figure 7.0 shows that a minimum of 3 average network transactions, 464757 gas, is required for TWAMM to be inactive for about 10 minutes. To get to almost 20 minutes of inactivity, the gas of 5 average UNI V2 swap transactions would be required. This suggests that without low-level solidity optimizations, the TWAMM contract under test, derived from [2] is not competitive with existing CPAMMs for consumer trades (i.e. simple swaps of small amounts) because of the larger gas costs. A combination of intelligent operating parameter selection and low-level solidity optimizations can potentially address this problem.
Idle can be defined as the scenario when there are no active LT-Swaps in any direction—this is scenario 1 from figure 3.0. Replicating the measurements from the procedure used to create figure 5.0, but in the absence of any active transactions yields the following results for gas usage at idle, swept for inactivity from 0 to 200 blocks:
Comparing the data of figures 5.0 and 8.0 shows that gas use is significantly reduced at idle, however it is important to note that there will still be a maximum inactivity duration when a pool is at idle, albeit markedly more then for the worst case gas usage of opposing direction LT-swaps.
What happens if a pool is inactive for so long that the gas required to execute virtual orders exceeds that provided in an Ethereum block?
For the TWAMM contract in [2], nothing can be done (as of 3/9/2022). However a simple contract modification is possible that allows a contract user to execute virtual orders up to a specified block. By specifying the block up-to which virtual orders are executed, the user can manually limit the number of iterations that are computed, and thus limit the gas used by the call.
It’s conceivable that such a long period of inactivity has occurred that multiple block limited execute virtual order calls are required before the pool is useable.
The effects of OBI, LT-Swap scenarios, and inactivity on the gas usage of TWAMM have been examined in this report. Intelligent selection of OBI for a given pair of tokens can be seen as a necessary first step for optimizing the gas usage of a TWAMM pool. The effect of the OBI selection on maximum inactivity durations was illustrated and a mitigation strategy presented.
Thus far, the experiments have shown that careful selection of OBI is required to minimize gas usage. Without understanding the magnitude of gas reduction that is possible by low-level contract optimizations, it is too early to recommend an OBI values or a range of OBI values for expected TWAMM pool activity levels.
Future work will be presented addressing the LT-Swap expiry concerns (Long-Term Order Expiration section) communicated in [1]. The author’s work in performing this analysis has revealed significant potential for low-level optimizations of the TWAMM contract published in [2]—optimizations of the variety performed on the Uniswap V2 contract described in [7] are readily applicable (encoding values into compact representations and packing multiple values into single machine native words for example). Additionally, because of the complexity of the TWAMM arithmetic, several common computations can be refactored and reused to further reduce gas. There may also be opportunities for caching and finally, the commonly used optimization of using memory instead of storage in loops is applicable.