Premiums

When a position is first opened, a trader requires a non-zero amount of premiums in his deposit, indexed by his position id.

mapping(PositionId => uint256) public PremiumDeposit;

Premiums are computed and paid from this deposit every time a trader adds or reduces a position.

An off-chain bot will continuously monitor positions and close positions that satisfy the following condition:

// Get premiums quoted this block
// This will be automatically paid when a trader is interacting with the protocol
uint256 premiumQuoted = computePremiums(PositionId); 

// can force close if deposit is less than the instantaneous premiums owed 
bool canForceClose = PremiumDeposit[PositionId] < premiumQuoted; 

Computing Premiums

A pseudocode for computing premiums is presented below.

function computePremiums( PositionId positionId) public view returns(uint256 premium){
    
    (uint lastPremiumPaymentTime, BorrowedTick[] memory borrowedTicks)
        = getPositionInfo(PositionId); 
        
    // get the time-weighted averaged tick between current time and last payment time
    // The 'distance' between the twat and the borrowed ticks will determine the 
    // multiplier
    int24 twat = getTimeWeightedAverageTick(block.timestamp - lastPremiumPaymentTime); 
    
    for(uint i; i<borrowedTicks.length; i++){
        // the closer the twat to the borrowed tick, the higher the multiplier
        uint multiplier = getMultiplier(twat, borrowedTicks[i].tick); 
        
        // get the interest accumulator at the given tick
        uint interestGrowthInTick = getInterestGrowth(borrowedTicks[i].tick); 
        
        // since interestGrowth is an accumulator, need to get actually owed interest
        uint interest = (interestGrowthInTick/borrowedTicks[i].lastInterestGrowth); 
        
        // scale interest by multiplier
        interest = interest * multiplier; 
        
        // add to total premiums for all borrowed ticks
        premium += interest * toTokenAmounts(borrowedTicks[i].liquidity)
    }
    
    return premium; 
}

function getInterestGrowth(int24 tick) public view returns(uint256){
    UtilizationGrowth memory growth = UtilizationGrowths[tick];
    
    // interest rate per second is proportional to utilization rate, 
    // where the utilization rate is recorded whenever a user provides,withdraws,borrows, or repays
    // the tick
    uint percentageIncreaseFromLastGrowth = getInterestRate(growth.lastURate) 
            ** (block.timestamp- growth.lastUpdateTime); 
            
    // the higher the last recorded utilization rate of the tick, the faster
    // the rate of growth
    uint totalAccumulatedGrowthForTick = growth.lastGrowth * percentageIncreaseFromLastGrowth;
    return totalAccumulatedGrowthTick;
}

Since the growth object of a given tick is updated every time an LP provides or withdraws or when a trader borrows and repays, the accumulator will be reflective of all debt originated from that tick.

Interest Rate

The getInterestRate function above is a piecewise function with a pivot rate. Each tick is characterized by its rate function.

Last updated