Rewards Distribution DSO

How are fee rewards measured and distributed to oCHI lockers?

Introducing oCHI

oCHI (Option CHI) is an ERC-721 token representing the individual option position of a user on the oCHI Contract. To obtain oCHI, users must define the epochDuration for the oCHI position, which is locked in the LPRewards Contract. The lock duration is expressed in weekly epochs, and the longer it is locked, the greater the discount on CHI and the higher the trading fees earned.

Interpretation of Epochs

Each epoch lasts one week, and the maximum lock-in period is 52 weeks (1 year). When the user mints oCHI, it is automatically locked in LPRewards Contract through the lockLP function

 function lockLP(uint256 lockingTokenId, uint256 amount, uint64 epochDuration) external onlyOwner 

The amount locked is stored on the next epoch data until the lock period expires.

epochData[nextEpoch].totalDeltaAmountLocked += int256(amount);
epochData[nextEpoch + epochDuration].totalDeltaAmountLocked -= int256(amount);
position.endingEpoch = nextEpoch + epochDuration;

Moreover, the user must be familiar with the epoch that determines the beginning of the eligibility window for the trading fees earned by the POL. This is also known as lastClaimedEpoch, which is set to the currentEpoch when the user opens a new position or, if already locked, to the last epoch when the user claimed fee rewards.

Interpretation of Epochs and Claiming Trading Fees

Fee rewards can be claimed on a per-epoch basis. Assuming the user claims their fee rewards before their locked position expires, the eligibility window is given by the range of position.lastClaimedEpoch and currentEpoch - 1.

Similarly, if the user claims rewards after the lock period has expired, the eligibility window starts on position.lastClaimedEpoch and terminates on position.endingEpoch - 1.

Computing Trading Fees Net of Impermanent Loss

Each week, when the updateEpoch function is called.

function updateEpoch() external onlyOwner

The weekly P&L (Profit and Loss), denominated in USD, of the protocol-owned liquidity is updated, and the profitPerLockedToken of the latest epoch is added to the cumulativeProfit of the previous epochs.

cumulativeProfit += profitPerLockedToken;
epoch.cumulativeProfit = cumulativeProfit;

The computation of P&L takes into account the variable epochMinLPBalance, which measures the balance of LP tokens in the LPRewards Contract (USC/ETH, CHI/ETH). The totalprofit of the latest epoch is calculated through the difference between the previous epoch LP value and the current epoch LP value.

int256 totalProfit = (int256(currentLPValue) - int256(prevLPValue)) * int256(epochMinLPBalance);

Assuming the liquidity value has grown (positive difference), this implies positive P&L, and the oCHI lockers uniformly receive the rewards.

profitPerLockedToken = totalProfit / totalAmountLocked;

To ensure that the single oCHI lockers are entitled to the rewards of the epochs they have not claimed yet, the function calculateUnclaimedReward is called when the user claims.

 function calculateUnclaimedReward(uint256 lockingTokenId) public view returns (int256)

Assuming the user claims before the fee rewards eligibility window expires (see Image 1), the claimable time range is from position.lastClaimedEpoch to currentEpoch - 1. If the user claims after the eligibility window expires (see Image 2), the range starts on position.lastClaimedEpoch and ends on position.endingEpoch - 1. Considering that the user has already claimed the latest fees, then claimable is set to zero.

uint64 fromEpoch = position.lastClaimedEpoch;
uint64 c = currentEpoch - 1;
if (position.endingEpoch - 1 < toEpoch) toEpoch = position.endingEpoch - 1; 
if (toEpoch <= fromEpoch) return 0;

Finally, the delta of the cumulative profit for the respective period is computed and made available for claiming by the user.

int256 profitDelta = epochData[toEpoch].cumulativeProfit - epochData[fromEpoch].cumulativeProfit;
int256 totalUSDreward = (int256(position.amountLocked) * profitDelta) / int256(10 ** DECIMALS);
return totalUSDreward;

Example: Fee rewards distribution to locked oCHI

  • Assume user locks 1000 oCHI for 4 epochs (4 weeks), and the profitPerLockedToken and cumulativeProfit per epoch are as follows:

Epoch profitPerLockedTokencumulativeProfit










  • Assuming the user claims the fee rewards on the currentEpoch, the profitDelta is computed as follows:

    • fromEpoch= epoch1

    • toEpoch= epoch3

    • profitDelta = 20 - 10 = 10 USD

  • The user totalUSDreward that can be claimed on currentEpoch are 10 *10000 = 10,000 USD

Last updated