diff --git a/src/tokenomics/contracts/FarmingCenter.sol b/src/tokenomics/contracts/FarmingCenter.sol index 743be3b86..a037269cb 100644 --- a/src/tokenomics/contracts/FarmingCenter.sol +++ b/src/tokenomics/contracts/FarmingCenter.sol @@ -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); @@ -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; @@ -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); @@ -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)) { @@ -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; diff --git a/src/tokenomics/contracts/farmings/AlgebraFarming.sol b/src/tokenomics/contracts/farmings/AlgebraFarming.sol index 311738990..10987b059 100644 --- a/src/tokenomics/contracts/farmings/AlgebraFarming.sol +++ b/src/tokenomics/contracts/farmings/AlgebraFarming.sol @@ -34,6 +34,7 @@ abstract contract AlgebraFarming is IAlgebraFarming { uint24 minimalPositionWidth; uint224 totalLiquidity; address multiplierToken; + bool deactivated; Tiers tiers; } @@ -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 @@ -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); @@ -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, @@ -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( diff --git a/src/tokenomics/contracts/farmings/eternalFarming/AlgebraEternalFarming.sol b/src/tokenomics/contracts/farmings/eternalFarming/AlgebraEternalFarming.sol index 01035f0ce..ab19e3e28 100644 --- a/src/tokenomics/contracts/farmings/eternalFarming/AlgebraEternalFarming.sol +++ b/src/tokenomics/contracts/farmings/eternalFarming/AlgebraEternalFarming.sol @@ -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 } @@ -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); @@ -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]; @@ -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); @@ -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]; diff --git a/src/tokenomics/contracts/farmings/eternalFarming/EternalVirtualPool.sol b/src/tokenomics/contracts/farmings/eternalFarming/EternalVirtualPool.sol index 54993e495..fad38e76a 100644 --- a/src/tokenomics/contracts/farmings/eternalFarming/EternalVirtualPool.sol +++ b/src/tokenomics/contracts/farmings/eternalFarming/EternalVirtualPool.sol @@ -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; @@ -32,12 +32,20 @@ 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)); @@ -45,12 +53,10 @@ contract EternalVirtualPool is AlgebraVirtualPoolBase, IAlgebraEternalVirtualPoo } // @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); } diff --git a/src/tokenomics/contracts/farmings/eternalFarming/interfaces/IAlgebraEternalFarming.sol b/src/tokenomics/contracts/farmings/eternalFarming/interfaces/IAlgebraEternalFarming.sol index 4cdf2c6cc..b56135f5c 100644 --- a/src/tokenomics/contracts/farmings/eternalFarming/interfaces/IAlgebraEternalFarming.sol +++ b/src/tokenomics/contracts/farmings/eternalFarming/interfaces/IAlgebraEternalFarming.sol @@ -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 ( @@ -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, diff --git a/src/tokenomics/contracts/farmings/eternalFarming/interfaces/IAlgebraEternalVirtualPool.sol b/src/tokenomics/contracts/farmings/eternalFarming/interfaces/IAlgebraEternalVirtualPool.sol index b7ef4f782..11229ec76 100644 --- a/src/tokenomics/contracts/farmings/eternalFarming/interfaces/IAlgebraEternalVirtualPool.sol +++ b/src/tokenomics/contracts/farmings/eternalFarming/interfaces/IAlgebraEternalVirtualPool.sol @@ -12,8 +12,18 @@ interface IAlgebraEternalVirtualPool is IAlgebraVirtualPoolBase { function addRewards(uint256 token0Amount, uint256 token1Amount) external; - function getInnerRewardsGrowth(int24 bottomTick, int24 topTick) - external - view - returns (uint256 rewardGrowthInside0, uint256 rewardGrowthInside1); + function decreaseRewards(uint256 token0Amount, uint256 token1Amount) external; + + function getInnerRewardsGrowth( + int24 bottomTick, + int24 topTick + ) external view returns (uint256 rewardGrowthInside0, uint256 rewardGrowthInside1); + + function rewardRate0() external returns (uint128); + + function rewardRate1() external returns (uint128); + + function rewardReserve0() external returns (uint256); + + function rewardReserve1() external returns (uint256); } diff --git a/src/tokenomics/contracts/farmings/limitFarming/AlgebraLimitFarming.sol b/src/tokenomics/contracts/farmings/limitFarming/AlgebraLimitFarming.sol index a54f6ee39..e6b7bb5ec 100644 --- a/src/tokenomics/contracts/farmings/limitFarming/AlgebraLimitFarming.sol +++ b/src/tokenomics/contracts/farmings/limitFarming/AlgebraLimitFarming.sol @@ -103,6 +103,7 @@ contract AlgebraLimitFarming is AlgebraFarming, IAlgebraLimitFarming { ); } + /// @inheritdoc IAlgebraFarming function addRewards( IncentiveKey memory key, uint256 reward, @@ -119,6 +120,7 @@ contract AlgebraLimitFarming is AlgebraFarming, IAlgebraLimitFarming { } } + /// @inheritdoc IAlgebraFarming function decreaseRewardsAmount( IncentiveKey memory key, uint256 rewardAmount, @@ -130,29 +132,24 @@ contract AlgebraLimitFarming is AlgebraFarming, IAlgebraLimitFarming { require(block.timestamp < key.endTime || incentive.totalLiquidity == 0, 'incentive finished'); uint256 _totalReward = incentive.totalReward; - if (rewardAmount > _totalReward) rewardAmount = _totalReward; + if (rewardAmount >= _totalReward) rewardAmount = _totalReward - 1; // to not trigger 'non-existent incentive' incentive.totalReward = _totalReward - rewardAmount; uint256 _bonusReward = incentive.bonusReward; if (bonusRewardAmount > _bonusReward) bonusRewardAmount = _bonusReward; incentive.bonusReward = _bonusReward - bonusRewardAmount; - TransferHelper.safeTransfer(address(key.bonusRewardToken), msg.sender, bonusRewardAmount); - TransferHelper.safeTransfer(address(key.rewardToken), msg.sender, rewardAmount); + 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 detachIncentive(IncentiveKey memory key) external override onlyIncentiveMaker { - (address _incentiveVirtualPool, ) = _getCurrentVirtualPools(key.pool); - _detachIncentive(key, _incentiveVirtualPool); - } - - /// @inheritdoc IAlgebraFarming - function attachIncentive(IncentiveKey memory key) external override onlyIncentiveMaker { + function deactivateIncentive(IncentiveKey memory key) external override onlyIncentiveMaker { (address _incentiveVirtualPool, ) = _getCurrentVirtualPools(key.pool); - _attachIncentive(key, _incentiveVirtualPool); + _deactivateIncentive(key, _incentiveVirtualPool); } /// @inheritdoc IAlgebraFarming @@ -183,11 +180,7 @@ contract AlgebraLimitFarming is AlgebraFarming, IAlgebraLimitFarming { } /// @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); Incentive storage incentive = incentives[incentiveId]; // anyone can call exitFarming if the block time is after the end time of the incentive @@ -247,7 +240,12 @@ contract AlgebraLimitFarming is AlgebraFarming, IAlgebraLimitFarming { } } } else { - (, int24 tick, , , , , ) = key.pool.globalState(); + int24 tick; + if (incentive.deactivated) { + tick = IAlgebraVirtualPoolBase(incentive.virtualPoolAddress).globalTick(); + } else { + (, tick, , , , , ) = key.pool.globalState(); + } virtualPool.applyLiquidityDeltaToPosition( uint32(block.timestamp), @@ -273,12 +271,10 @@ contract AlgebraLimitFarming is AlgebraFarming, IAlgebraLimitFarming { } /// @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]; diff --git a/src/tokenomics/contracts/farmings/limitFarming/interfaces/IAlgebraLimitFarming.sol b/src/tokenomics/contracts/farmings/limitFarming/interfaces/IAlgebraLimitFarming.sol index e71b024b5..dd3609b20 100644 --- a/src/tokenomics/contracts/farmings/limitFarming/interfaces/IAlgebraLimitFarming.sol +++ b/src/tokenomics/contracts/farmings/limitFarming/interfaces/IAlgebraLimitFarming.sol @@ -27,14 +27,10 @@ interface IAlgebraLimitFarming is IAlgebraFarming { /// @return liquidity The amount of liquidity in the NFT as of the last time the rewards were computed, /// tickLower The lower end of the tick range for the position, /// tickUpper The upper end of the tick range for the position - function farms(uint256 tokenId, bytes32 incentiveId) - external - view - returns ( - uint128 liquidity, - int24 tickLower, - int24 tickUpper - ); + function farms( + uint256 tokenId, + bytes32 incentiveId + ) external view returns (uint128 liquidity, int24 tickLower, int24 tickUpper); function createLimitFarming( IncentiveKey memory key, @@ -42,18 +38,6 @@ interface IAlgebraLimitFarming is IAlgebraFarming { IncentiveParams memory params ) external returns (address virtualPool); - function addRewards( - IncentiveKey memory key, - uint256 reward, - uint256 bonusReward - ) external; - - function decreaseRewardsAmount( - IncentiveKey memory key, - uint256 rewardAmount, - uint256 bonusRewardAmount - ) external; - /// @notice Event emitted when a liquidity mining incentive has been created /// @param rewardToken The token being distributed as a reward /// @param bonusRewardToken The token being distributed as a bonus reward @@ -79,6 +63,4 @@ interface IAlgebraLimitFarming is IAlgebraFarming { uint24 minimalAllowedPositionWidth, uint32 enterStartTime ); - - event RewardAmountsDecreased(uint256 reward, uint256 bonusReward, bytes32 incentiveId); } diff --git a/src/tokenomics/contracts/interfaces/IAlgebraFarming.sol b/src/tokenomics/contracts/interfaces/IAlgebraFarming.sol index fc16097ed..2ba42f951 100644 --- a/src/tokenomics/contracts/interfaces/IAlgebraFarming.sol +++ b/src/tokenomics/contracts/interfaces/IAlgebraFarming.sol @@ -7,7 +7,6 @@ import '@cryptoalgebra/core/contracts/interfaces/IAlgebraPool.sol'; import '@cryptoalgebra/core/contracts/interfaces/IERC20Minimal.sol'; import '@cryptoalgebra/periphery/contracts/interfaces/INonfungiblePositionManager.sol'; -import './IFarmingCenter.sol'; import './IIncentiveKey.sol'; /// @title Algebra Farming Interface @@ -16,9 +15,6 @@ interface IAlgebraFarming is IIncentiveKey { /// @notice The nonfungible position manager with which this farming contract is compatible function nonfungiblePositionManager() external view returns (INonfungiblePositionManager); - /// @notice The farming Center - function farmingCenter() external view returns (IFarmingCenter); - /// @notice The pool deployer function deployer() external returns (IAlgebraPoolDeployer); @@ -39,7 +35,9 @@ interface IAlgebraFarming is IIncentiveKey { /// @notice Represents a farming incentive /// @param incentiveId The ID of the incentive computed from its parameters - function incentives(bytes32 incentiveId) + function incentives( + bytes32 incentiveId + ) external view returns ( @@ -49,16 +47,17 @@ interface IAlgebraFarming is IIncentiveKey { uint24 minimalPositionWidth, uint224 totalLiquidity, address multiplierToken, + bool deactivated, Tiers memory tiers ); - /// @notice Detach incentive from the pool + /// @notice Detach incentive from the pool and deactivate it /// @param key The key of the incentive - function detachIncentive(IncentiveKey memory key) external; + function deactivateIncentive(IncentiveKey memory key) external; - /// @notice Attach incentive to the pool - /// @param key The key of the incentive - function attachIncentive(IncentiveKey memory key) external; + function addRewards(IncentiveKey memory key, uint256 rewardAmount, uint256 bonusRewardAmount) external; + + function decreaseRewardsAmount(IncentiveKey memory key, uint256 rewardAmount, uint256 bonusRewardAmount) external; /// @notice Returns amounts of reward tokens owed to a given address according to the last time all farms were updated /// @param owner The owner for which the rewards owed are checked @@ -74,21 +73,13 @@ interface IAlgebraFarming is IIncentiveKey { /// @param key The key of the incentive for which to enterFarming the NFT /// @param tokenId The ID of the token to exitFarming /// @param tokensLocked The amount of tokens locked for boost - function enterFarming( - IncentiveKey memory key, - uint256 tokenId, - uint256 tokensLocked - ) external; + function enterFarming(IncentiveKey memory key, uint256 tokenId, uint256 tokensLocked) external; /// @notice exitFarmings for Algebra LP token /// @param key The key of the incentive for which to exitFarming the NFT /// @param tokenId The ID of the token to exitFarming /// @param _owner Owner of the token - function exitFarming( - IncentiveKey memory key, - uint256 tokenId, - address _owner - ) external; + function exitFarming(IncentiveKey memory key, uint256 tokenId, address _owner) external; /// @notice Transfers `amountRequested` of accrued `rewardToken` rewards from the contract to the recipient `to` /// @param rewardToken The token being distributed as a reward @@ -120,9 +111,10 @@ interface IAlgebraFarming is IIncentiveKey { /// @param tokenId The ID of the token /// @return reward The reward accrued to the NFT for the given incentive thus far /// @return bonusReward The bonus reward accrued to the NFT for the given incentive thus far - function getRewardInfo(IncentiveKey memory key, uint256 tokenId) - external - returns (uint256 reward, uint256 bonusReward); + function getRewardInfo( + IncentiveKey memory key, + uint256 tokenId + ) external returns (uint256 reward, uint256 bonusReward); /// @notice Event emitted when a liquidity mining incentive has been stopped from the outside /// @param rewardToken The token being distributed as a reward @@ -131,23 +123,7 @@ interface IAlgebraFarming is IIncentiveKey { /// @param virtualPool The detached virtual pool address /// @param startTime The time when the incentive program begins /// @param endTime The time when rewards stop accruing - event IncentiveDetached( - IERC20Minimal indexed rewardToken, - IERC20Minimal indexed bonusRewardToken, - IAlgebraPool indexed pool, - address virtualPool, - uint256 startTime, - uint256 endTime - ); - - /// @notice Event emitted when a liquidity mining incentive has been runned again from the outside - /// @param rewardToken The token being distributed as a reward - /// @param bonusRewardToken The token being distributed as a bonus reward - /// @param pool The Algebra pool - /// @param virtualPool The attached virtual pool address - /// @param startTime The time when the incentive program begins - /// @param endTime The time when rewards stop accruing - event IncentiveAttached( + event IncentiveDeactivated( IERC20Minimal indexed rewardToken, IERC20Minimal indexed bonusRewardToken, IAlgebraPool indexed pool, @@ -195,6 +171,8 @@ interface IAlgebraFarming is IIncentiveKey { /// @param incentiveId The ID of the incentive for which rewards were added event RewardsAdded(uint256 rewardAmount, uint256 bonusRewardAmount, bytes32 incentiveId); + event RewardAmountsDecreased(uint256 reward, uint256 bonusReward, bytes32 incentiveId); + /// @notice Event emitted when a reward token has been claimed /// @param to The address where claimed rewards were sent to /// @param reward The amount of reward tokens claimed diff --git a/src/tokenomics/package.json b/src/tokenomics/package.json index 7895473bb..3df5a42d9 100644 --- a/src/tokenomics/package.json +++ b/src/tokenomics/package.json @@ -2,7 +2,7 @@ "name": "@cryptoalgebra/farmings", "description": "Liquidity mining contracts for Algebra protocol", "license": "GPL-3.0-or-later", - "version": "2.0.0", + "version": "2.1.0", "keywords": [ "algebra", "liquidity mining" diff --git a/src/tokenomics/test/unit/EternalFarms.spec.ts b/src/tokenomics/test/unit/EternalFarms.spec.ts index 0adac2801..b1c1abb9a 100644 --- a/src/tokenomics/test/unit/EternalFarms.spec.ts +++ b/src/tokenomics/test/unit/EternalFarms.spec.ts @@ -914,7 +914,7 @@ describe('unit/EternalFarms', () => { }) }) - describe('attach/detach incentive', () => { + describe('deactivate incentive', () => { let incentiveArgs: HelperTypes.CreateIncentive.Args let incentiveKey: ContractParams.IncentiveKey let virtualPool: Contract @@ -948,31 +948,17 @@ describe('unit/EternalFarms', () => { }) - it('detach incentive', async () => { + it('deactivate incentive', async () => { let activeIncentiveBefore = await context.poolObj.connect(incentiveCreator).activeIncentive() - await context.eternalFarming.connect(incentiveCreator).detachIncentive(incentiveKey) + await context.eternalFarming.connect(incentiveCreator).deactivateIncentive(incentiveKey) let activeIncentiveAfter = await context.poolObj.connect(incentiveCreator).activeIncentive() expect(activeIncentiveBefore).to.equal(virtualPool.address) expect(activeIncentiveAfter).to.equal(ZERO_ADDRESS) }) - - it('attach incentive', async () => { - - await context.eternalFarming.connect(incentiveCreator).detachIncentive(incentiveKey) - - let activeIncentiveBefore = await context.poolObj.connect(incentiveCreator).activeIncentive() - - await context.eternalFarming.connect(incentiveCreator).attachIncentive(incentiveKey) - - let activeIncentiveAfter = await context.poolObj.connect(incentiveCreator).activeIncentive() - - expect(activeIncentiveBefore).to.equal(ZERO_ADDRESS) - expect(activeIncentiveAfter).to.equal(virtualPool.address) - }) }) describe('rewards', async () => { diff --git a/src/tokenomics/test/unit/FarmingCenter.spec.ts b/src/tokenomics/test/unit/FarmingCenter.spec.ts index 929cb044b..7f71cb263 100644 --- a/src/tokenomics/test/unit/FarmingCenter.spec.ts +++ b/src/tokenomics/test/unit/FarmingCenter.spec.ts @@ -971,7 +971,7 @@ describe('unit/FarmingCenter', () => { }) - it('collect rewards after eternalFarming detach', async() => { + it('collect rewards after eternalFarming deactivate', async() => { let balanceBefore = await context.eternalFarming.rewards(lpUser0.address,context.rewardToken.address) let bonusBalanceBefore = await context.eternalFarming.rewards(lpUser0.address,context.bonusRewardToken.address) @@ -1004,7 +1004,7 @@ describe('unit/FarmingCenter', () => { desiredValue: 10, }) - await context.eternalFarming.connect(incentiveCreator).detachIncentive( + await context.eternalFarming.connect(incentiveCreator).deactivateIncentive( { rewardToken: context.rewardToken.address, bonusRewardToken: context.bonusRewardToken.address, @@ -1025,8 +1025,8 @@ describe('unit/FarmingCenter', () => { let balanceAfter = await context.eternalFarming.rewards(lpUser0.address,context.rewardToken.address) let bonusBalanceAfter = await context.eternalFarming.rewards(lpUser0.address,context.bonusRewardToken.address) - expect(balanceAfter.sub(balanceBefore)).to.equal(BN(199099)) - expect(bonusBalanceAfter.sub(bonusBalanceBefore)).to.equal(BN(99249)) + expect(balanceAfter.sub(balanceBefore)).to.equal(BN(199199)) + expect(bonusBalanceAfter.sub(bonusBalanceBefore)).to.equal(BN(99299)) }) diff --git a/src/tokenomics/test/unit/Incentives.spec.ts b/src/tokenomics/test/unit/Incentives.spec.ts index b48a44a80..42e0f3960 100644 --- a/src/tokenomics/test/unit/Incentives.spec.ts +++ b/src/tokenomics/test/unit/Incentives.spec.ts @@ -188,7 +188,7 @@ describe('unit/Incentives', async () => { }) }) - describe('attach/detach incentive', () => { + describe('deactivate incentive', () => { let incentiveArgs: HelperTypes.CreateIncentive.Args let incentiveKey: ContractParams.IncentiveKey let virtualPool: Contract @@ -221,30 +221,16 @@ describe('unit/Incentives', async () => { }) - it('detach incentive', async () => { + it('deactivate incentive', async () => { let activeIncentiveBefore = await context.poolObj.connect(incentiveCreator).activeIncentive() - await context.farming.connect(incentiveCreator).detachIncentive(incentiveKey) + await context.farming.connect(incentiveCreator).deactivateIncentive(incentiveKey) let activeIncentiveAfter = await context.poolObj.connect(incentiveCreator).activeIncentive() expect(activeIncentiveBefore).to.equal(virtualPool.address) expect(activeIncentiveAfter).to.equal(ZERO_ADDRESS) }) - - it('attach incentive', async () => { - - await context.farming.connect(incentiveCreator).detachIncentive(incentiveKey) - - let activeIncentiveBefore = await context.poolObj.connect(incentiveCreator).activeIncentive() - - await context.farming.connect(incentiveCreator).attachIncentive(incentiveKey) - - let activeIncentiveAfter = await context.poolObj.connect(incentiveCreator).activeIncentive() - - expect(activeIncentiveBefore).to.equal(ZERO_ADDRESS) - expect(activeIncentiveAfter).to.equal(virtualPool.address) - }) }) describe('increase/decrease rewards', () => { @@ -334,15 +320,15 @@ describe('unit/Incentives', async () => { }) it('decrease rewards completely', async () => { - let rewardAmount = await (await context.farming.connect(incentiveCreator).incentives(incentiveId)).totalReward - let bonusRewardAmount = await (await context.farming.connect(incentiveCreator).incentives(incentiveId)).bonusReward + let rewardAmount = (await context.farming.connect(incentiveCreator).incentives(incentiveId)).totalReward + let bonusRewardAmount = (await context.farming.connect(incentiveCreator).incentives(incentiveId)).bonusReward await context.farming.connect(incentiveCreator).decreaseRewardsAmount(incentiveKey, rewardAmount.mul(2), bonusRewardAmount.mul(2)) - rewardAmount = await (await context.farming.connect(incentiveCreator).incentives(incentiveId)).totalReward - bonusRewardAmount = await (await context.farming.connect(incentiveCreator).incentives(incentiveId)).bonusReward + rewardAmount = (await context.farming.connect(incentiveCreator).incentives(incentiveId)).totalReward + bonusRewardAmount = (await context.farming.connect(incentiveCreator).incentives(incentiveId)).bonusReward - expect(rewardAmount).to.eq(0) + expect(rewardAmount).to.eq(1) expect(bonusRewardAmount).to.eq(0) })