Skip to content

Commit

Permalink
Merge pull request #52 from cryptoalgebra/staged
Browse files Browse the repository at this point in the history
Change in farmings
  • Loading branch information
0xVolosnikov authored Mar 21, 2023
2 parents 70d919c + 455272f commit 11fff53
Show file tree
Hide file tree
Showing 13 changed files with 169 additions and 246 deletions.
33 changes: 11 additions & 22 deletions src/tokenomics/contracts/FarmingCenter.sol
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ contract FarmingCenter is IFarmingCenter, ERC721Permit, Multicall, PeripheryPaym

(_deposit.numberOfFarms, _deposit.inLimitFarming) = (numberOfFarms, inLimitFarming);
bytes32 incentiveId = IncentiveId.compute(key);
(, , , , , address multiplierToken, ) = _farming.incentives(incentiveId);
(, , , , , address multiplierToken, , ) = _farming.incentives(incentiveId);
if (tokensLocked > 0) {
uint256 balanceBefore = _getTokenBalanceOfVault(multiplierToken);
TransferHelper.safeTransferFrom(multiplierToken, msg.sender, address(farmingCenterVault), tokensLocked);
Expand All @@ -129,11 +129,7 @@ contract FarmingCenter is IFarmingCenter, ERC721Permit, Multicall, PeripheryPaym
}

/// @inheritdoc IFarmingCenter
function exitFarming(
IncentiveKey memory key,
uint256 tokenId,
bool isLimit
) external override {
function exitFarming(IncentiveKey memory key, uint256 tokenId, bool isLimit) external override {
Deposit storage deposit = deposits[tokenId];
checkAuthorizationForToken(deposit.L2TokenId);
IAlgebraFarming _farming;
Expand All @@ -148,18 +144,16 @@ contract FarmingCenter is IFarmingCenter, ERC721Permit, Multicall, PeripheryPaym
_farming.exitFarming(key, tokenId, msg.sender);

bytes32 incentiveId = IncentiveId.compute(key);
(, , , , , address multiplierToken, ) = _farming.incentives(incentiveId);
(, , , , , address multiplierToken, , ) = _farming.incentives(incentiveId);
if (multiplierToken != address(0)) {
farmingCenterVault.claimTokens(multiplierToken, msg.sender, tokenId, incentiveId);
}
}

/// @inheritdoc IFarmingCenter
function collect(INonfungiblePositionManager.CollectParams memory params)
external
override
returns (uint256 amount0, uint256 amount1)
{
function collect(
INonfungiblePositionManager.CollectParams memory params
) external override returns (uint256 amount0, uint256 amount1) {
checkAuthorizationForToken(deposits[params.tokenId].L2TokenId);
if (params.recipient == address(0)) {
params.recipient = address(this);
Expand All @@ -168,11 +162,10 @@ contract FarmingCenter is IFarmingCenter, ERC721Permit, Multicall, PeripheryPaym
}

/// @inheritdoc IFarmingCenter
function collectRewards(IncentiveKey memory key, uint256 tokenId)
external
override
returns (uint256 reward, uint256 bonusReward)
{
function collectRewards(
IncentiveKey memory key,
uint256 tokenId
) external override returns (uint256 reward, uint256 bonusReward) {
checkAuthorizationForToken(deposits[tokenId].L2TokenId);
address _virtualPool = _virtualPoolAddresses[address(key.pool)].eternalVirtualPool;
if (_virtualPool != address(0)) {
Expand Down Expand Up @@ -233,11 +226,7 @@ contract FarmingCenter is IFarmingCenter, ERC721Permit, Multicall, PeripheryPaym
}

/// @inheritdoc IFarmingCenter
function withdrawToken(
uint256 tokenId,
address to,
bytes memory data
) external override {
function withdrawToken(uint256 tokenId, address to, bytes memory data) external override {
require(to != address(this), 'cannot withdraw to farming');
Deposit storage deposit = deposits[tokenId];
uint256 l2TokenId = deposit.L2TokenId;
Expand Down
56 changes: 12 additions & 44 deletions src/tokenomics/contracts/farmings/AlgebraFarming.sol
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ abstract contract AlgebraFarming is IAlgebraFarming {
uint24 minimalPositionWidth;
uint224 totalLiquidity;
address multiplierToken;
bool deactivated;
Tiers tiers;
}

Expand All @@ -43,8 +44,7 @@ abstract contract AlgebraFarming is IAlgebraFarming {
/// @inheritdoc IAlgebraFarming
IAlgebraPoolDeployer public immutable override deployer;

/// @inheritdoc IAlgebraFarming
IFarmingCenter public override farmingCenter;
IFarmingCenter public farmingCenter;

/// @dev bytes32 refers to the return value of IncentiveId.compute
/// @inheritdoc IAlgebraFarming
Expand Down Expand Up @@ -153,14 +153,7 @@ abstract contract AlgebraFarming is IAlgebraFarming {
uint24 minimalPositionWidth,
address multiplierToken,
Tiers calldata tiers
)
internal
returns (
bytes32 incentiveId,
uint256 receivedReward,
uint256 receivedBonusReward
)
{
) internal returns (bytes32 incentiveId, uint256 receivedReward, uint256 receivedBonusReward) {
_connectPoolToVirtualPool(key.pool, virtualPool);

incentiveId = IncentiveId.compute(key);
Expand Down Expand Up @@ -198,16 +191,17 @@ abstract contract AlgebraFarming is IAlgebraFarming {
newIncentive.multiplierToken = multiplierToken;
}

function _detachIncentive(IncentiveKey memory key, address currentVirtualPool) internal {
function _deactivateIncentive(IncentiveKey memory key, address currentVirtualPool) internal {
require(currentVirtualPool != address(0), 'Farming do not exist');

require(
incentives[IncentiveId.compute(key)].virtualPoolAddress == currentVirtualPool,
'Another farming is active'
);
Incentive storage incentive = incentives[IncentiveId.compute(key)];
require(incentive.virtualPoolAddress == currentVirtualPool, 'Another farming is active');
require(!incentive.deactivated, 'Already deactivated');
incentive.deactivated = true;

_connectPoolToVirtualPool(key.pool, address(0));

emit IncentiveDetached(
emit IncentiveDeactivated(
key.rewardToken,
key.bonusRewardToken,
key.pool,
Expand All @@ -217,42 +211,16 @@ abstract contract AlgebraFarming is IAlgebraFarming {
);
}

function _attachIncentive(IncentiveKey memory key, address currentVirtualPool) internal {
require(currentVirtualPool == address(0), 'Farming already exists');

address virtualPoolAddress = incentives[IncentiveId.compute(key)].virtualPoolAddress;
require(virtualPoolAddress != address(0), 'Invalid farming');

_connectPoolToVirtualPool(key.pool, virtualPoolAddress);

emit IncentiveAttached(
key.rewardToken,
key.bonusRewardToken,
key.pool,
virtualPoolAddress,
key.startTime,
key.endTime
);
}

function _enterFarming(
IncentiveKey memory key,
uint256 tokenId,
uint256 tokensLocked
)
internal
returns (
bytes32 incentiveId,
int24 tickLower,
int24 tickUpper,
uint128 liquidity,
address virtualPool
)
{
) internal returns (bytes32 incentiveId, int24 tickLower, int24 tickUpper, uint128 liquidity, address virtualPool) {
incentiveId = IncentiveId.compute(key);
Incentive storage incentive = incentives[incentiveId];

require(incentive.totalReward > 0, 'non-existent incentive');
require(!incentive.deactivated, 'incentive stopped');

IAlgebraPool pool;
(pool, tickLower, tickUpper, liquidity) = NFTPositionInfo.getPositionInfo(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,10 @@ contract AlgebraEternalFarming is AlgebraFarming, IAlgebraEternalFarming {

/// @param _deployer pool deployer contract address
/// @param _nonfungiblePositionManager the NFT position manager contract address
constructor(IAlgebraPoolDeployer _deployer, INonfungiblePositionManager _nonfungiblePositionManager)
AlgebraFarming(_deployer, _nonfungiblePositionManager)
{
constructor(
IAlgebraPoolDeployer _deployer,
INonfungiblePositionManager _nonfungiblePositionManager
) AlgebraFarming(_deployer, _nonfungiblePositionManager) {
// just initialize AlgebraFarming
}

Expand Down Expand Up @@ -80,26 +81,55 @@ contract AlgebraEternalFarming is AlgebraFarming, IAlgebraEternalFarming {
}

/// @inheritdoc IAlgebraFarming
function detachIncentive(IncentiveKey memory key) external override onlyIncentiveMaker {
function deactivateIncentive(IncentiveKey memory key) external override onlyIncentiveMaker {
(, address _eternalVirtualPool) = _getCurrentVirtualPools(key.pool);
_detachIncentive(key, _eternalVirtualPool);
}

/// @inheritdoc IAlgebraFarming
function attachIncentive(IncentiveKey memory key) external override onlyIncentiveMaker {
(, address _eternalVirtualPool) = _getCurrentVirtualPools(key.pool);
_attachIncentive(key, _eternalVirtualPool);
IAlgebraEternalVirtualPool virtualPool = IAlgebraEternalVirtualPool(_eternalVirtualPool);
if (virtualPool.rewardRate0() != 0 || virtualPool.rewardRate1() != 0) {
virtualPool.setRates(0, 0);
emit RewardsRatesChanged(0, 0, IncentiveId.compute(key));
}

_deactivateIncentive(key, _eternalVirtualPool);
}

/// @inheritdoc IAlgebraEternalFarming
function addRewards(
/// @inheritdoc IAlgebraFarming
function decreaseRewardsAmount(
IncentiveKey memory key,
uint256 rewardAmount,
uint256 bonusRewardAmount
) external override {
) external override onlyOwner {
bytes32 incentiveId = IncentiveId.compute(key);
Incentive storage incentive = incentives[incentiveId];

require(incentive.totalReward > 0, 'non-existent incentive');

IAlgebraEternalVirtualPool virtualPool = IAlgebraEternalVirtualPool(incentive.virtualPoolAddress);

uint256 rewardReserve0 = virtualPool.rewardReserve0();
if (rewardAmount > rewardReserve0) rewardAmount = rewardReserve0;
if (rewardAmount >= incentive.totalReward) rewardAmount = incentive.totalReward - 1; // to not trigger 'non-existent incentive'
incentive.totalReward = incentive.totalReward - rewardAmount;

uint256 rewardReserve1 = virtualPool.rewardReserve1();
if (bonusRewardAmount > rewardReserve1) bonusRewardAmount = rewardReserve1;
incentive.bonusReward = incentive.bonusReward - bonusRewardAmount;

virtualPool.decreaseRewards(rewardAmount, bonusRewardAmount);

if (rewardAmount > 0) TransferHelper.safeTransfer(address(key.rewardToken), msg.sender, rewardAmount);
if (bonusRewardAmount > 0)
TransferHelper.safeTransfer(address(key.bonusRewardToken), msg.sender, bonusRewardAmount);

emit RewardAmountsDecreased(rewardAmount, bonusRewardAmount, incentiveId);
}

/// @inheritdoc IAlgebraFarming
function addRewards(IncentiveKey memory key, uint256 rewardAmount, uint256 bonusRewardAmount) external override {
bytes32 incentiveId = IncentiveId.compute(key);
Incentive storage incentive = incentives[incentiveId];
require(incentive.totalReward > 0, 'non-existent incentive');
require(!incentive.deactivated, 'incentive stopped');

(rewardAmount, bonusRewardAmount) = _receiveRewards(key, rewardAmount, bonusRewardAmount, incentive);

Expand Down Expand Up @@ -156,11 +186,7 @@ contract AlgebraEternalFarming is AlgebraFarming, IAlgebraEternalFarming {
}

/// @inheritdoc IAlgebraFarming
function exitFarming(
IncentiveKey memory key,
uint256 tokenId,
address _owner
) external override onlyFarmingCenter {
function exitFarming(IncentiveKey memory key, uint256 tokenId, address _owner) external override onlyFarmingCenter {
bytes32 incentiveId = IncentiveId.compute(key);

Farm memory farm = farms[tokenId][incentiveId];
Expand All @@ -173,7 +199,12 @@ contract AlgebraEternalFarming is AlgebraFarming, IAlgebraEternalFarming {
uint256 bonusReward;

{
(, int24 tick, , , , , ) = key.pool.globalState();
int24 tick;
if (incentive.deactivated) {
tick = IAlgebraVirtualPoolBase(incentive.virtualPoolAddress).globalTick();
} else {
(, tick, , , , , ) = key.pool.globalState();
}

// update rewards, as ticks may be cleared when liquidity decreases
virtualPool.applyLiquidityDeltaToPosition(uint32(block.timestamp), farm.tickLower, farm.tickUpper, 0, tick);
Expand Down Expand Up @@ -220,12 +251,10 @@ contract AlgebraEternalFarming is AlgebraFarming, IAlgebraEternalFarming {

/// @notice reward amounts can be outdated, actual amounts could be obtained via static call of `collectRewards` in FarmingCenter
/// @inheritdoc IAlgebraFarming
function getRewardInfo(IncentiveKey memory key, uint256 tokenId)
external
view
override
returns (uint256 reward, uint256 bonusReward)
{
function getRewardInfo(
IncentiveKey memory key,
uint256 tokenId
) external view override returns (uint256 reward, uint256 bonusReward) {
bytes32 incentiveId = IncentiveId.compute(key);

Farm memory farm = farms[tokenId][incentiveId];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ contract EternalVirtualPool is AlgebraVirtualPoolBase, IAlgebraEternalVirtualPoo
using TickManager for mapping(int24 => TickManager.Tick);
using LowGasSafeMath for uint256;

uint128 public rewardRate0;
uint128 public rewardRate1;
uint128 public override rewardRate0;
uint128 public override rewardRate1;

uint256 public rewardReserve0;
uint256 public rewardReserve1;
uint256 public override rewardReserve0;
uint256 public override rewardReserve1;

uint256 public totalRewardGrowth0;
uint256 public totalRewardGrowth1;
Expand All @@ -32,25 +32,31 @@ contract EternalVirtualPool is AlgebraVirtualPoolBase, IAlgebraEternalVirtualPoo
prevTimestamp = uint32(block.timestamp);
}

// @inheritdoc IAlgebraEternalVirtualPool
function addRewards(uint256 token0Amount, uint256 token1Amount) external override onlyFarming {
_increaseCumulative(uint32(block.timestamp));
if (token0Amount > 0) rewardReserve0 = rewardReserve0.add(token0Amount);
if (token1Amount > 0) rewardReserve1 = rewardReserve1.add(token1Amount);
}

// @inheritdoc IAlgebraEternalVirtualPool
function decreaseRewards(uint256 token0Amount, uint256 token1Amount) external override onlyFarming {
_increaseCumulative(uint32(block.timestamp));
if (token0Amount > 0) rewardReserve0 = rewardReserve0.sub(token0Amount);
if (token1Amount > 0) rewardReserve1 = rewardReserve1.sub(token1Amount);
}

// @inheritdoc IAlgebraEternalVirtualPool
function setRates(uint128 rate0, uint128 rate1) external override onlyFarming {
_increaseCumulative(uint32(block.timestamp));
(rewardRate0, rewardRate1) = (rate0, rate1);
}

// @inheritdoc IAlgebraEternalVirtualPool
function getInnerRewardsGrowth(int24 bottomTick, int24 topTick)
external
view
override
returns (uint256 rewardGrowthInside0, uint256 rewardGrowthInside1)
{
function getInnerRewardsGrowth(
int24 bottomTick,
int24 topTick
) external view override returns (uint256 rewardGrowthInside0, uint256 rewardGrowthInside1) {
return ticks.getInnerFeeGrowth(bottomTick, topTick, globalTick, totalRewardGrowth0, totalRewardGrowth1);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,10 @@ interface IAlgebraEternalFarming is IAlgebraFarming {
/// tickUpper The upper tick of position,
/// innerRewardGrowth0 The last saved reward0 growth inside position,
/// innerRewardGrowth1 The last saved reward1 growth inside position
function farms(uint256 tokenId, bytes32 incentiveId)
function farms(
uint256 tokenId,
bytes32 incentiveId
)
external
view
returns (
Expand All @@ -58,17 +61,7 @@ interface IAlgebraEternalFarming is IAlgebraFarming {
Tiers calldata tiers
) external returns (address virtualPool);

function addRewards(
IncentiveKey memory key,
uint256 rewardAmount,
uint256 bonusRewardAmount
) external;

function setRates(
IncentiveKey memory key,
uint128 rewardRate,
uint128 bonusRewardRate
) external;
function setRates(IncentiveKey memory key, uint128 rewardRate, uint128 bonusRewardRate) external;

function collectRewards(
IncentiveKey memory key,
Expand Down
Loading

0 comments on commit 11fff53

Please sign in to comment.