Withdraw Reward

To withdraw the earned reward for a position, the withdrawReward function is used. It requires, as input:

function withdrawReward(uint256 positionId) external byPositionOwner(positionId) {     _withdrawReward(positionId, 0); }
  • positionId -> id corresponding to the position.

withdrawReward can be called at any time to withdraw the amount of reward tokens accumulated thus far by a position. It internally calls the _withdrawReward method, the helper function used to calculate and send the reward to the position owner.‌

If there is a claimable reward amount, the function transfers the amount to the position owner's address:

reward = calculateFreeFarmingReward(positionId, false);
_safeTransfer(_rewardTokenAddress, farmingPosition.uniqueOwner, reward);

The withdrawn reward amount is added to the rewardPaid of the position; rewardPaid represents the total amount of reward already claimed for the position:

_rewardPaid[farmingPosition.setupIndex] += reward;

Aside from being called directly in this function, withdrawReward will also be called internally when the withdrawLiquidity function is used.‌

As explained in the NFT Management Section, when a user claims their reward, they also withdraw their share of the trading fees earned by the NFT. _withdrawReward is responsible for this; it calls the _retrieveGen2LiquidityAndFees method, which itself calls the calculateTradingFees method that calculates their share of earned fees using the formula explained here:

uint256 lastRedeemeableBlock = block.number > chosenSetup.endBlock ? chosenSetup.endBlock : block.number;uint256 percentageOfFeesOwnedByPosition = reward * ONE_HUNDRED / (((chosenSetup.rewardPerBlock * (lastRedeemeableBlock - chosenSetup.startBlock)) - _rewardPaid[farmingPosition.setupIndex]));

Then, the feeAmount0 and feeAmount1 amounts are withdrawn from the NFT position using the _collect method, which internally calls the collect method of INonfungiblePositionManager:

uint256 collectedAmount0 = 0;uint256 collectedAmount1 = 0;(uint256 feeAmount0, uint256 feeAmount1) = (0, 0);if(reward > 0) {    (feeAmount0, feeAmount1) = calculateTradingFees(positionId, reward, 0, 0);}collectedAmount0 += feeAmount0;collectedAmount1 += feeAmount1;(collectedAmount0, collectedAmount1) = _checkLastPosition(positionId, liquidityToRemove, collectedAmount0, collectedAmount1);if (collectedAmount0 > 0 || collectedAmount1 > 0) {    address token0;    address token1;    (token0, token1, collectedAmount0, collectedAmount1) = _collect(positionId, collectedAmount0, collectedAmount1);    uint256 dfoFee0 = 0;    uint256 dfoFee1 = 0;

At this stage, if a fee for the Covenants DFO is to be taken, it is calculated, subtracted from the fee amounts and sent to the Covenants DFO wallet. The rest is sent to the address of the position owner:

(uint256 exitFeePercentage, address exitFeeWallet) = IFarmFactory(_factory).feePercentageInfo();if (exitFeePercentage > 0) {    dfoFee0 = (feeAmount0 * ((exitFeePercentage * 1e18) / ONE_HUNDRED)) / 1e18;    dfoFee1 = (feeAmount1 * ((exitFeePercentage * 1e18) / ONE_HUNDRED)) / 1e18;    _safeTransfer(token0, exitFeeWallet, dfoFee0);    _safeTransfer(token1, exitFeeWallet, dfoFee1);}_safeTransfer(token0, recipient, collectedAmount0 - dfoFee0);_safeTransfer(token1, recipient, collectedAmount1 - dfoFee1);

Otherwise, if the fees are 0, the whole share of the position fees is sent directly to the user.‌

(This differs from the Covenant Farming Generation 1 setup system, in which the fee for the Covenants DFO is taken as a percentage of the user's LP tokens at the moment of liquidity withdrawal).

Last updated