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.