Protocol Contracts

Composing contracts of the TWAMM protocol

TwammWeightedPool Contract

This is the pool contract, which overrides the BaseWeightedPool and implements some of the core functionalities for the Twamm. It is responsible hooking up the joinPool, exitPool and swap functionalities to execute any pending virtual orders. It is responsible for co-ordinating with the LongTermOrders contract to execute virtual orders and ensuring the long term orders token are accounted properly during execution of swap or other basic pool operations.

LongTermOrders Contract

This contract is responsible for all the accounting of the long term orders placed with the pool. It stores the current state of the execution of the long term orders. This contract also encapsulates the logic for the execution of the virtual orders and maths behind the Twamm calculations.

Data storage

The LongTermOrders contract stores following information to account for the execution of long term orders.

struct LongTermOrdersStruct {

    uint32 orderBlockInterval;
    
    uint32 lastOrderId;
    
    uint64 maxPerBlockSaleRatePercent;
    
    uint64 minltoOrderAmountToAmmBalanceRatio;

    uint64 lastVirtualOrderBlock;
    
    uint256 feePercentage;
    
    uint256 balanceA;
    uint256 balanceB;

    mapping(uint256 => OrderPoolLib.OrderPool) orderPoolMap;
 
    mapping(uint256 => Order) orderMap;
    
    uint256[] orderExpiryHeap;
}

orderBlockInterval

Minimum block interval between order expiries

lastOrderId

Incrementing counter for order ids to be assigned to each long term order placed

maxPerBlockSaleRatePercent

Just like max swap amount allowed check with AMMs, this is upper limit to max per block sales rate. This value is checked whenever a new long term order is placed. If it breaches the limit LONG_TERM_ORDER_AMOUNT_TOO_LARGE error is thrown.

minltoOrderAmountToAmmBalanceRatio

The minimum order amount to AMM balance ration is the minimum order size of a long term order in comparison with the AMM balance. This ration is checked whenever an order is placed. The purpose keeping this check is to prevent someone from placing lots of small size orders and DDoSing the pool.

lastVirtualOrderBlock

The last virtual order block is used to keep track of the last block till which the virtual orders are executed already.

feePercentage

Fee percentage charged from long term orders as protocol fees. The fees is deducted whenever the virtual orders are executed.

balanceA

The balance of A tokens from LongTermOrders for A<->B token pool. This balance is total of all converted and yet to be converted tokens from placed LongTermOrders. This helps pool in calculating how much is pool liquidity from total liquidity.

balanceB

Just like balanceA, balanceB is balance of B tokens in A<->B pool.

orderPoolMap

Order Pool is per token, it stores the details related to sales rate and distribution of converted tokens with respect to orders.

orderMap

Mapping to store long term orders placed.

orderExpiryHeap

Order expiry heap tracks order expiries and is used to manage virtual order execution.

Data Structures

Order data structure

This is how an order is represented internally

struct Order {
    uint256 id;
    uint256 expirationBlock;
    uint256 saleRate;
    address owner;
    uint256 sellTokenIndex;
    uint256 buyTokenIndex;
}
  1. id - The unique id for the order

  2. expirationBlock - The block at which the order will expire, this is calculated based on the number of block intervals for which the order is placed and the order block interval size.

  3. saleRate - For a given amount and total tokens to sell, we can calculate a sale rate per block for the order. This token sell rate per block is represented by saleRate

  4. owner - Store the owner of the order

  5. sellTokenIndex - The index of the token to be sold in the pool

  6. buyTokenIndex - The index of the token to be bought in the pool

Order Pool data structure

struct OrderPool {
    uint256 currentSalesRate;
    uint256 rewardFactor;
    mapping(uint256 => uint256) salesRateEndingPerBlock;
    mapping(uint256 => uint256) rewardFactorAtSubmission;
    mapping(uint256 => uint256) rewardFactorAtBlock;
    mapping(uint256 => uint256) ordersExpiringAtBlock;
}

Last updated