From 5b561821570c2ab54ee319c5b11db518f5b42897 Mon Sep 17 00:00:00 2001 From: David Racero Date: Tue, 22 Jun 2021 19:10:44 +0200 Subject: [PATCH] feat: adapted prior curve reward aware token tests. Added 3pool support. --- .../interfaces/curve/ICurveTreasury.sol | 2 + .../curve/CurveGaugeRewardsAwareAToken.sol | 44 +++++-- .../adapters/rewards/curve/CurveTreasury.sol | 120 ++++++++---------- .../protocol/lendingpool/LendingPool.sol | 3 +- helpers/constants.ts | 6 +- tasks/deployments/deploy-CurveTreasury.ts | 15 +-- .../mainnet/atoken-curve-rewards.main.ts | 84 +++++++----- 7 files changed, 149 insertions(+), 125 deletions(-) diff --git a/contracts/adapters/interfaces/curve/ICurveTreasury.sol b/contracts/adapters/interfaces/curve/ICurveTreasury.sol index a9ef56aa..8afe6cf7 100644 --- a/contracts/adapters/interfaces/curve/ICurveTreasury.sol +++ b/contracts/adapters/interfaces/curve/ICurveTreasury.sol @@ -36,12 +36,14 @@ interface ICurveTreasury { * @param entities Entities addresses list * @param tokens Curve LP Token addresses list * @param gauges Curve Gauge Staking tokens list, use zero address to disable staking + * @param areGaugesV2 Curve version list, if true gauge is V2 compatible, false if not. * @param whitelisted Flag to determine if the entity should be enabled or disabled */ function setWhitelist( address[] calldata entities, address[] calldata tokens, address[] calldata gauges, + bool[] memory areGaugesV2, bool[] memory whitelisted ) external; diff --git a/contracts/adapters/rewards/curve/CurveGaugeRewardsAwareAToken.sol b/contracts/adapters/rewards/curve/CurveGaugeRewardsAwareAToken.sol index 8c785189..6f5e2d76 100644 --- a/contracts/adapters/rewards/curve/CurveGaugeRewardsAwareAToken.sol +++ b/contracts/adapters/rewards/curve/CurveGaugeRewardsAwareAToken.sol @@ -9,6 +9,7 @@ import {ICurveMinter} from '../../interfaces/curve/ICurveMinter.sol'; import {ICurveGauge, ICurveGaugeView} from '../../interfaces/curve/ICurveGauge.sol'; import {IAaveIncentivesController} from '../../../interfaces/IAaveIncentivesController.sol'; import {ICurveTreasury} from '../../interfaces/curve/ICurveTreasury.sol'; +import 'hardhat/console.sol'; /** * @title Curve Rewards Aware AToken @@ -82,17 +83,20 @@ contract CurveGaugeRewardsAwareAToken is RewardsAwareAToken { _underlyingAsset = underlyingAsset; _incentivesController = incentivesController; - _gaugeController = _decodeParams(params); + _gaugeController = _decodeGaugeAddress(params); // Initialize Curve Gauge rewards _rewardTokens[0] = CRV_TOKEN; - // Start for loop with index = 1 to not rewrite first element of rewardTokens - for (uint256 index = 1; index < MAX_REWARD_TOKENS; index++) { - address reward = ICurveGaugeView(_decodeParams(params)).reward_tokens(index - 1); - if (reward == address(0)) break; + // If Gauge is version V2, them discover reward tokens + if (_decodeGaugeVersion(params) == true) { + // Start for loop with index = 1 to not rewrite first element of rewardTokens + for (uint256 index = 1; index < MAX_REWARD_TOKENS; index++) { + address reward = ICurveGaugeView(_decodeGaugeAddress(params)).reward_tokens(index - 1); + if (reward == address(0)) break; - _rewardTokens[index] = reward; + _rewardTokens[index] = reward; + } } IERC20(underlyingAsset).safeApprove(CURVE_TREASURY, type(uint256).max); @@ -160,7 +164,6 @@ contract CurveGaugeRewardsAwareAToken is RewardsAwareAToken { function _computeExternalLifetimeRewards(address token) internal override returns (uint256) { // The Curve Gauge can give exact lifetime rewards and accrued rewards for the CRV token if (token == CRV_TOKEN) { - ICurveGauge(_gaugeController).user_checkpoint(CURVE_TREASURY); return _getExternalLifetimeCurve(); } // Other rewards from the Curve Gauge can not get the lifetime rewards externally, only at the moment of claim, due they are external rewards outside the Curve ecosystem. @@ -200,7 +203,7 @@ contract CurveGaugeRewardsAwareAToken is RewardsAwareAToken { priorTokenBalances[index] = IERC20(rewardToken).balanceOf(address(this)); } // Mint other rewards to aToken - ICurveTreasury(CURVE_TREASURY).claimGaugeRewards(_gaugeController); + ICurveTreasury(CURVE_TREASURY).claimGaugeRewards(_underlyingAsset); for (uint256 index = 1; index < MAX_REWARD_TOKENS; index++) { address rewardToken = _getRewardsTokenAddress(index); @@ -220,7 +223,9 @@ contract CurveGaugeRewardsAwareAToken is RewardsAwareAToken { * @param amount Amount of tokens to deposit */ function _stake(address token, uint256 amount) internal override returns (uint256) { - ICurveTreasury(CURVE_TREASURY).deposit(token, amount, true); + if (token == UNDERLYING_ASSET_ADDRESS()) { + ICurveTreasury(CURVE_TREASURY).deposit(token, amount, true); + } return amount; } @@ -230,21 +235,34 @@ contract CurveGaugeRewardsAwareAToken is RewardsAwareAToken { * @param amount Amount of tokens to withdraw */ function _unstake(address token, uint256 amount) internal override returns (uint256) { - ICurveTreasury(CURVE_TREASURY).withdraw(token, amount, true); + if (token == UNDERLYING_ASSET_ADDRESS()) { + ICurveTreasury(CURVE_TREASURY).withdraw(token, amount, true); + } return amount; } /** - * @dev Param decoder to get Gauge Staking address + * @dev Param decoder to get Gauge Staking address. The decoder function is splitted due "Stack too deep" at constructor. * @param params Additional variadic field to include extra params. Expected parameters: * @return address of gauge */ - function _decodeParams(bytes memory params) internal pure returns (address) { - address gauge = abi.decode(params, (address)); + function _decodeGaugeAddress(bytes memory params) internal pure returns (address) { + (address gauge, bool _isGaugeV2) = abi.decode(params, (address, bool)); return gauge; } + /** + * @dev Param decoder to get Gauge Staking address. The decoder function is splitted due "Stack too deep" at constructor. + * @param params Additional variadic field to include extra params. Expected parameters: + * @return bool true if Gauge follows Gauge V2 interface, false otherwise + */ + function _decodeGaugeVersion(bytes memory params) internal pure returns (bool) { + (address _gauge, bool isGaugeV2) = abi.decode(params, (address, bool)); + + return isGaugeV2; + } + /** End of Rewards Aware AToken functions */ /** Start of External getters */ diff --git a/contracts/adapters/rewards/curve/CurveTreasury.sol b/contracts/adapters/rewards/curve/CurveTreasury.sol index 15f6719b..140abb0a 100644 --- a/contracts/adapters/rewards/curve/CurveTreasury.sol +++ b/contracts/adapters/rewards/curve/CurveTreasury.sol @@ -13,6 +13,7 @@ import { } from '../../../protocol/libraries/aave-upgradeability/VersionedInitializable.sol'; import {ICurveFeeDistributor} from '../../interfaces/curve/ICurveFeeDistributor.sol'; import {ICurveTreasury} from '../../interfaces/curve/ICurveTreasury.sol'; +import 'hardhat/console.sol'; /** * @title Curve Treasury that holds Curve LP and Gauge tokens @@ -37,6 +38,7 @@ contract CurveTreasury is ICurveTreasury, VersionedInitializable { mapping(address => mapping(address => bool)) internal _entityTokenWhitelist; mapping(address => mapping(address => address)) internal _entityTokenGauge; + mapping(address => bool) internal _isGaugeV2Compatible; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); @@ -66,6 +68,7 @@ contract CurveTreasury is ICurveTreasury, VersionedInitializable { * @dev Revert if caller and selected token is not a whitelisted entity */ modifier onlyWhitelistedEntity(address token) { + console.log(msg.sender, token, _entityTokenWhitelist[msg.sender][token]); require(_entityTokenWhitelist[msg.sender][token] == true, 'ENTITY_NOT_WHITELISTED'); _; } @@ -79,26 +82,11 @@ contract CurveTreasury is ICurveTreasury, VersionedInitializable { } /** - * @dev Initializes the contract with an owner and optional entities whitelist + * @dev Initializes the contract with an owner that allows to whitelist new entities inside the treasury contract * @param owner Sets the owner of the contract - * @param entities Entities addresses list, optional argument - * @param tokens Curve LP Token addresses list, optional argument - * @param gauges Curve Gauge Staking tokens list, use zero address to disable staking, optional argument */ - function initialize( - address owner, - address[] calldata entities, - address[] calldata tokens, - address[] calldata gauges - ) external virtual initializer { + function initialize(address owner) external virtual initializer { _owner = owner; - if (entities.length > 0) { - bool[] memory whitelisted = new bool[](entities.length); - for (uint256 x; x < whitelisted.length; x++) { - whitelisted[x] = true; - } - _setWhitelist(entities, tokens, gauges, whitelisted); - } } /// @inheritdoc ICurveTreasury @@ -131,9 +119,23 @@ contract CurveTreasury is ICurveTreasury, VersionedInitializable { address[] calldata entities, address[] calldata tokens, address[] calldata gauges, + bool[] memory areGaugesV2, bool[] memory whitelisted ) external override onlyOwner { - _setWhitelist(entities, tokens, gauges, whitelisted); + for (uint256 e; e < entities.length; e++) { + _entityTokenWhitelist[entities[e]][tokens[e]] = whitelisted[e]; + if (whitelisted[e] == true) { + if (gauges[e] != address(0)) { + _entityTokenGauge[entities[e]][tokens[e]] = gauges[e]; + _isGaugeV2Compatible[gauges[e]] = areGaugesV2[e]; + } + _approveEntityTokens(entities[e], tokens[e], gauges[e], areGaugesV2[e], type(uint256).max); + } else { + _entityTokenGauge[entities[e]][tokens[e]] = address(0); + _approveEntityTokens(entities[e], tokens[e], gauges[e], areGaugesV2[e], 0); + _isGaugeV2Compatible[gauges[e]] = false; + } + } } /// @inheritdoc ICurveTreasury @@ -155,28 +157,30 @@ contract CurveTreasury is ICurveTreasury, VersionedInitializable { IERC20(CRV_TOKEN).safeTransfer(msg.sender, crvRewards); } - // Claim the extra rewards from Gauge Staking - uint256[] memory priorRewardsBalance = new uint256[](MAX_REWARD_TOKENS); - uint256[] memory afterRewardsBalance = new uint256[](MAX_REWARD_TOKENS); + if (_isGaugeV2Compatible[gauge] == true) { + // Claim the extra rewards from Gauge Staking + uint256[] memory priorRewardsBalance = new uint256[](MAX_REWARD_TOKENS); + uint256[] memory afterRewardsBalance = new uint256[](MAX_REWARD_TOKENS); - // Calculate balances prior claiming rewards - for (uint256 index = 1; index < MAX_REWARD_TOKENS; index++) { - address rewardToken = ICurveGaugeView(gauge).reward_tokens(index - 1); - if (rewardToken == address(0)) break; - priorRewardsBalance[index] = IERC20(rewardToken).balanceOf(address(this)); - } + // Calculate balances prior claiming rewards + for (uint256 index = 1; index < MAX_REWARD_TOKENS; index++) { + address rewardToken = ICurveGaugeView(gauge).reward_tokens(index - 1); + if (rewardToken == address(0)) break; + priorRewardsBalance[index] = IERC20(rewardToken).balanceOf(address(this)); + } - // Claim extra rewards - ICurveGauge(gauge).claim_rewards(); + // Claim extra rewards + ICurveGauge(gauge).claim_rewards(); - // Transfer extra rewards to entity - for (uint256 index = 1; index < MAX_REWARD_TOKENS; index++) { - address rewardToken = ICurveGaugeView(gauge).reward_tokens(index - 1); - if (rewardToken == address(0)) break; - afterRewardsBalance[index] = IERC20(rewardToken).balanceOf(address(this)); - uint256 rewardsAmount = afterRewardsBalance[index].sub(priorRewardsBalance[index]); - if (rewardsAmount > 0) { - IERC20(rewardToken).safeTransfer(msg.sender, rewardsAmount); + // Transfer extra rewards to entity + for (uint256 index = 1; index < MAX_REWARD_TOKENS; index++) { + address rewardToken = ICurveGaugeView(gauge).reward_tokens(index - 1); + if (rewardToken == address(0)) break; + afterRewardsBalance[index] = IERC20(rewardToken).balanceOf(address(this)); + uint256 rewardsAmount = afterRewardsBalance[index].sub(priorRewardsBalance[index]); + if (rewardsAmount > 0) { + IERC20(rewardToken).safeTransfer(msg.sender, rewardsAmount); + } } } } @@ -246,33 +250,6 @@ contract CurveTreasury is ICurveTreasury, VersionedInitializable { return TREASURY_REVISION; } - /** - * @dev Register entities to enable or disable deposits and withdraws from the treasury - * @param entities Entities addresses list - * @param tokens Curve LP Token addresses list - * @param gauges Curve Gauge Staking tokens list, use zero address to disable staking - * @param whitelisted Flag to determine if the entity should be enabled or disabled - */ - function _setWhitelist( - address[] calldata entities, - address[] calldata tokens, - address[] calldata gauges, - bool[] memory whitelisted - ) internal { - for (uint256 e; e < entities.length; e++) { - _entityTokenWhitelist[entities[e]][tokens[e]] = whitelisted[e]; - if (whitelisted[e] == true) { - if (gauges[e] != address(0)) { - _entityTokenGauge[entities[e]][tokens[e]] = gauges[e]; - } - _approveEntityTokens(entities[e], tokens[e], gauges[e], type(uint256).max); - } else { - _entityTokenGauge[entities[e]][tokens[e]] = address(0); - _approveEntityTokens(entities[e], tokens[e], gauges[e], 0); - } - } - } - /** * @dev ERC20 approval to allow entity and gauge staking contracts to pull whitelisted tokens and rewards from the treasury * @param entity Entity address @@ -284,6 +261,7 @@ contract CurveTreasury is ICurveTreasury, VersionedInitializable { address entity, address token, address gauge, + bool isGaugeV2, uint256 amount ) internal { IERC20(token).safeApprove(entity, 0); @@ -291,11 +269,15 @@ contract CurveTreasury is ICurveTreasury, VersionedInitializable { if (gauge != address(0)) { IERC20(token).safeApprove(gauge, 0); IERC20(token).safeApprove(gauge, amount); - for (uint256 index = 0; index < MAX_REWARD_TOKENS; index++) { - address reward = ICurveGaugeView(gauge).reward_tokens(index - 1); - if (reward == address(0)) break; - IERC20(reward).safeApprove(entity, 0); - IERC20(reward).safeApprove(entity, amount); + IERC20(CRV_TOKEN).safeApprove(entity, 0); + IERC20(CRV_TOKEN).safeApprove(entity, amount); + if (isGaugeV2 == true) { + for (uint256 index = 0; index < MAX_REWARD_TOKENS; index++) { + address reward = ICurveGaugeView(gauge).reward_tokens(index); + if (reward == address(0)) break; + IERC20(reward).safeApprove(entity, 0); + IERC20(reward).safeApprove(entity, amount); + } } } } diff --git a/contracts/protocol/lendingpool/LendingPool.sol b/contracts/protocol/lendingpool/LendingPool.sol index 8e38650c..7744f5ec 100644 --- a/contracts/protocol/lendingpool/LendingPool.sol +++ b/contracts/protocol/lendingpool/LendingPool.sol @@ -115,7 +115,6 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage reserve.updateState(); reserve.updateInterestRates(asset, aToken, amount, 0); - IERC20(asset).safeTransferFrom(msg.sender, aToken, amount); bool isFirstDeposit = IAToken(aToken).mint(onBehalfOf, amount, reserve.liquidityIndex); @@ -713,7 +712,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage } /** - * @dev Returns the fee on flash loans + * @dev Returns the fee on flash loans */ function FLASHLOAN_PREMIUM_TOTAL() public view returns (uint256) { return _flashLoanPremiumTotal; diff --git a/helpers/constants.ts b/helpers/constants.ts index 516b7689..a781ae0c 100644 --- a/helpers/constants.ts +++ b/helpers/constants.ts @@ -84,12 +84,12 @@ export const CURVE_TREASURY = { export const CURVE_CONFIG = { votingEscrow: { - [eEthereumNetwork.main]: ZERO_ADDRESS, + [eEthereumNetwork.main]: '0x5f3b5DfEb7B28CDbD7FAba78963EE202a494e2A2', }, curveFeeDistributor: { - [eEthereumNetwork.main]: ZERO_ADDRESS, + [eEthereumNetwork.main]: '0xA464e6DCda8AC41e03616F95f4BC98a13b8922Dc', }, gaugeController: { - [eEthereumNetwork.main]: ZERO_ADDRESS, + [eEthereumNetwork.main]: '0x2F50D538606Fa9EDD2B11E2446BEb18C9D5846bB', }, }; diff --git a/tasks/deployments/deploy-CurveTreasury.ts b/tasks/deployments/deploy-CurveTreasury.ts index 89eda48d..b305b220 100644 --- a/tasks/deployments/deploy-CurveTreasury.ts +++ b/tasks/deployments/deploy-CurveTreasury.ts @@ -15,7 +15,7 @@ task(`deploy-curve-treasury`, `Deploys the CurveTreasury contract`) .setAction(async ({ verify, proxyAdmin, treasuryAdmin, collector }, localBRE) => { await localBRE.run('set-DRE'); - const net = localBRE.network.name; + const net = process.env.FORK ? process.env.FORK : localBRE.network.name; console.log(`\n- Curve Treasury deployment`); const aaveCollector = collector || ZERO_ADDRESS; @@ -30,18 +30,15 @@ task(`deploy-curve-treasury`, `Deploys the CurveTreasury contract`) ); // Freeze implementatation - await waitForTx(await implementation.initialize(ZERO_ADDRESS, [], [], [])); + await waitForTx(await implementation.initialize(ZERO_ADDRESS)); // Deploy proxy const proxy = await deployInitializableAdminUpgradeabilityProxy(verify); - const encoded = implementation.interface.encodeFunctionData('initialize', [ - treasuryAdmin, - [], - [], - [], - ]); - await waitForTx(await proxy.initialize(implementation.address, proxyAdmin, encoded)); + const encoded = implementation.interface.encodeFunctionData('initialize', [treasuryAdmin]); + await waitForTx( + await proxy['initialize(address,address,bytes)'](implementation.address, proxyAdmin, encoded) + ); console.log(`\tFinished CurveTreasury deployment`); console.log(`\tProxy:`, proxy.address); diff --git a/test-suites/test-aave/mainnet/atoken-curve-rewards.main.ts b/test-suites/test-aave/mainnet/atoken-curve-rewards.main.ts index 39416686..c15e3dc8 100644 --- a/test-suites/test-aave/mainnet/atoken-curve-rewards.main.ts +++ b/test-suites/test-aave/mainnet/atoken-curve-rewards.main.ts @@ -15,20 +15,21 @@ import { getLendingPoolAddressesProvider, getLendingPoolConfiguratorProxy, } from '../../../helpers/contracts-getters'; -import { - deployCurveGaugeReserveInterestRateStrategy, - deployDefaultReserveInterestRateStrategy, -} from '../../../helpers/contracts-deployments'; +import { deployCurveGaugeReserveInterestRateStrategy } from '../../../helpers/contracts-deployments'; import { IERC20Factory } from '../../../types/IERC20Factory'; import BigNumberJs from 'bignumber.js'; -import { CurveGaugeRewardsAwareATokenFactory } from '../../../types'; +import { + CurveGaugeRewardsAwareATokenFactory, + CurveTreasury, + CurveTreasuryFactory, +} from '../../../types'; import { eContractid, eEthereumNetwork, tEthereumAddress } from '../../../helpers/types'; import { strategyWBTC } from '../../../markets/aave/reservesConfigs'; import { checkRewards } from '../helpers/rewards-distribution/verify'; import { IRewardsAwareAToken } from '../../../types/IRewardsAwareAToken'; import { IRewardsAwareATokenFactory } from '../../../types/IRewardsAwareATokenFactory'; import { BigNumber } from 'ethers'; -import { AbiCoder, defaultAbiCoder, parseEther } from 'ethers/lib/utils'; +import { defaultAbiCoder, formatEther, parseEther } from 'ethers/lib/utils'; import { IERC20 } from '../../../types/IERC20'; import { getContractAddressWithJsonFallback, @@ -46,7 +47,6 @@ interface GaugeInfo { symbol: string; rewardTokens: tEthereumAddress[]; } -const BLOCK_HEIGHT = ''; const USER_ADDRESS = '0x9c5083dd4838E120Dbeac44C052179692Aa5dAC5'; const CRV_TOKEN = '0xd533a949740bb3306d119cc777fa900ba034cd52'; @@ -86,12 +86,18 @@ const GAUGE_ANKR: GaugeInfo = { '0x8290333ceF9e6D528dD5618Fb97a76f268f3EDD4', ], }; +const isGaugeV2 = (address: tEthereumAddress) => + GAUGE_3POOL.address.toLowerCase() !== address.toLowerCase(); const unstakeAllGauges = async (key: SignerWithAddress, gauges: tEthereumAddress[]) => { for (let x = 0; x < gauges.length; x++) { - await waitForTx( - await ICurveGaugeFactory.connect(gauges[x], key.signer).withdraw(MAX_UINT_AMOUNT) - ); + if (isGaugeV2(gauges[x])) { + await waitForTx( + await IERC20Factory.connect(gauges[x], key.signer).approve(gauges[x], MAX_UINT_AMOUNT) + ); + } + const balance = IERC20Factory.connect(gauges[x], key.signer).balanceOf(key.address); + await waitForTx(await ICurveGaugeFactory.connect(gauges[x], key.signer).withdraw(balance)); } }; @@ -140,7 +146,10 @@ const listCurveLPToken = async (gauge: GaugeInfo, curveTreasury: tEthereumAddres false ); const interestRateStrategyAddress = interestStrategy.address; - const encodedParams = defaultAbiCoder.encode(['string'], [gauge.address]); + const encodedParams = defaultAbiCoder.encode( + ['address', 'bool'], + [gauge.address, isGaugeV2(gauge.address)] + ); const curveReserveInitParams = [ { aTokenImpl, @@ -175,7 +184,8 @@ const depositPoolToken = async ( const pool = await getLendingPool(); const curveReserveToken = IERC20Factory.connect(gauge.underlying, key.signer); - await curveReserveToken.connect(key.signer).approve(pool.address, amount); + await waitForTx(await curveReserveToken.connect(key.signer).approve(pool.address, 0)); + await waitForTx(await curveReserveToken.connect(key.signer).approve(pool.address, amount)); const txDeposit = await waitForTx( await pool.connect(key.signer).deposit(gauge.underlying, amount, key.address, '0') @@ -249,6 +259,8 @@ makeSuite('Curve Rewards Aware aToken', (testEnv: TestEnv) => { let crvToken: IERC20; let snxToken: IERC20; + let curveTreasury: CurveTreasury; + before('Initializing configuration', async () => { // Sets BigNumber for this suite, instead of globally BigNumberJs.config({ DECIMAL_PLACES: 0, ROUNDING_MODE: BigNumberJs.ROUND_DOWN }); @@ -272,10 +284,6 @@ makeSuite('Curve Rewards Aware aToken', (testEnv: TestEnv) => { // Depositor should have 3pool, EURS, AAVE3, and ANKR balance const curve3poolBalance = await curve3poolErc20.balanceOf(USER_ADDRESS); - const gaugeCurve3poolBalance = await IERC20Factory.connect( - GAUGE_3POOL.address, - depositor.signer - ).balanceOf(USER_ADDRESS); const curveEursBalance = await curveEursErc20.balanceOf(USER_ADDRESS); const curveAave3Balance = await curveAave3Erc20.balanceOf(USER_ADDRESS); const curveAnkrBalance = await curveAnkrErc20.balanceOf(USER_ADDRESS); @@ -292,16 +300,17 @@ makeSuite('Curve Rewards Aware aToken', (testEnv: TestEnv) => { eEthereumNetwork.main ); - const { proxy: curveTreasury } = await DRE.run('deploy-curve-treasury', { - proxyAdmin: ZERO_ADDRESS, - treasuryAdmin: ZERO_ADDRESS, + const { proxy: curveTreasuryAddress } = await DRE.run('deploy-curve-treasury', { + proxyAdmin: testEnv.users[1].address, + treasuryAdmin: testEnv.users[0].address, collector, }); + // Gauge tokens should be listed at Aave test deployment - await listCurveLPToken(GAUGE_3POOL, curveTreasury); - await listCurveLPToken(GAUGE_EURS, curveTreasury); - await listCurveLPToken(GAUGE_AAVE3, curveTreasury); - await listCurveLPToken(GAUGE_ANKR, curveTreasury); + await listCurveLPToken(GAUGE_3POOL, curveTreasuryAddress); + await listCurveLPToken(GAUGE_EURS, curveTreasuryAddress); + await listCurveLPToken(GAUGE_AAVE3, curveTreasuryAddress); + await listCurveLPToken(GAUGE_ANKR, curveTreasuryAddress); const allTokens = await testEnv.helpersContract.getAllATokens(); @@ -319,9 +328,26 @@ makeSuite('Curve Rewards Aware aToken', (testEnv: TestEnv) => { ); aANKR = IRewardsAwareATokenFactory.connect( allTokens.find((aToken) => aToken.symbol.includes('ankr'))?.tokenAddress || ZERO_ADDRESS, - await getFirstSigner() ); + curveTreasury = CurveTreasuryFactory.connect(curveTreasuryAddress, testEnv.users[0].signer); + + // Enable atoken entities into Curve Treasury + console.log(a3POOL.address, aEURS.address, aAAVE3.address, aANKR.address); + await waitForTx( + await curveTreasury.setWhitelist( + [a3POOL.address, aEURS.address, aAAVE3.address, aANKR.address], + [ + GAUGE_3POOL.underlying, + GAUGE_EURS.underlying, + GAUGE_AAVE3.underlying, + GAUGE_ANKR.underlying, + ], + [GAUGE_3POOL.address, GAUGE_EURS.address, GAUGE_AAVE3.address, GAUGE_ANKR.address], + [false, true, true, true], + [true, true, true, true] + ) + ); }); after('Reset', () => { @@ -390,7 +416,7 @@ makeSuite('Curve Rewards Aware aToken', (testEnv: TestEnv) => { it('Deposit and generate user reward checkpoints', async () => { // Deposits - await depositPoolToken(depositor, GAUGE_3POOL, a3POOL.address, parseEther('100000')); + await depositPoolToken(depositor, GAUGE_3POOL, a3POOL.address, parseEther('2000')); const curveATokenBalance = await crvToken.balanceOf(a3POOL.address); expect(curveATokenBalance).to.be.eq('0', 'CRV rewards should be zero'); }); @@ -408,19 +434,19 @@ makeSuite('Curve Rewards Aware aToken', (testEnv: TestEnv) => { ); }); - it('Pass time and withdraw Staked AAVE3', async () => { + it('Pass time and withdraw Staked 3pool', async () => { // Pass time to generate rewards await increaseTime(ONE_DAY); // Withdraw - await withdrawPoolToken(depositor, GAUGE_3POOL, a3POOL.address); + await withdrawPoolToken(depositor, GAUGE_3POOL, a3POOL.address, true); const curveATokenBalance = await crvToken.balanceOf(a3POOL.address); expect(curveATokenBalance).to.be.eq('0', 'CRV rewards should be zero'); }); - it('Claim the remaining CRV', async () => { + it('Claim the remaining CRV, should not reward', async () => { // Claim - await claimFromGauge(depositor, GAUGE_AAVE3, aAAVE3.address); + await claimFromGauge(depositor, GAUGE_AAVE3, aAAVE3.address, false); const curveATokenBalance = await crvToken.balanceOf(a3POOL.address); expect(curveATokenBalance).to.be.eq( '0',