mirror of
https://github.com/Instadapp/aave-protocol-v2.git
synced 2024-07-29 21:47:30 +00:00
feat: adapted prior curve reward aware token tests. Added 3pool support.
This commit is contained in:
parent
b5ba303e8f
commit
5b56182157
|
@ -36,12 +36,14 @@ interface ICurveTreasury {
|
||||||
* @param entities Entities addresses list
|
* @param entities Entities addresses list
|
||||||
* @param tokens Curve LP Token addresses list
|
* @param tokens Curve LP Token addresses list
|
||||||
* @param gauges Curve Gauge Staking tokens list, use zero address to disable staking
|
* @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
|
* @param whitelisted Flag to determine if the entity should be enabled or disabled
|
||||||
*/
|
*/
|
||||||
function setWhitelist(
|
function setWhitelist(
|
||||||
address[] calldata entities,
|
address[] calldata entities,
|
||||||
address[] calldata tokens,
|
address[] calldata tokens,
|
||||||
address[] calldata gauges,
|
address[] calldata gauges,
|
||||||
|
bool[] memory areGaugesV2,
|
||||||
bool[] memory whitelisted
|
bool[] memory whitelisted
|
||||||
) external;
|
) external;
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ import {ICurveMinter} from '../../interfaces/curve/ICurveMinter.sol';
|
||||||
import {ICurveGauge, ICurveGaugeView} from '../../interfaces/curve/ICurveGauge.sol';
|
import {ICurveGauge, ICurveGaugeView} from '../../interfaces/curve/ICurveGauge.sol';
|
||||||
import {IAaveIncentivesController} from '../../../interfaces/IAaveIncentivesController.sol';
|
import {IAaveIncentivesController} from '../../../interfaces/IAaveIncentivesController.sol';
|
||||||
import {ICurveTreasury} from '../../interfaces/curve/ICurveTreasury.sol';
|
import {ICurveTreasury} from '../../interfaces/curve/ICurveTreasury.sol';
|
||||||
|
import 'hardhat/console.sol';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @title Curve Rewards Aware AToken
|
* @title Curve Rewards Aware AToken
|
||||||
|
@ -82,17 +83,20 @@ contract CurveGaugeRewardsAwareAToken is RewardsAwareAToken {
|
||||||
_underlyingAsset = underlyingAsset;
|
_underlyingAsset = underlyingAsset;
|
||||||
_incentivesController = incentivesController;
|
_incentivesController = incentivesController;
|
||||||
|
|
||||||
_gaugeController = _decodeParams(params);
|
_gaugeController = _decodeGaugeAddress(params);
|
||||||
|
|
||||||
// Initialize Curve Gauge rewards
|
// Initialize Curve Gauge rewards
|
||||||
_rewardTokens[0] = CRV_TOKEN;
|
_rewardTokens[0] = CRV_TOKEN;
|
||||||
|
|
||||||
// Start for loop with index = 1 to not rewrite first element of rewardTokens
|
// If Gauge is version V2, them discover reward tokens
|
||||||
for (uint256 index = 1; index < MAX_REWARD_TOKENS; index++) {
|
if (_decodeGaugeVersion(params) == true) {
|
||||||
address reward = ICurveGaugeView(_decodeParams(params)).reward_tokens(index - 1);
|
// Start for loop with index = 1 to not rewrite first element of rewardTokens
|
||||||
if (reward == address(0)) break;
|
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);
|
IERC20(underlyingAsset).safeApprove(CURVE_TREASURY, type(uint256).max);
|
||||||
|
@ -160,7 +164,6 @@ contract CurveGaugeRewardsAwareAToken is RewardsAwareAToken {
|
||||||
function _computeExternalLifetimeRewards(address token) internal override returns (uint256) {
|
function _computeExternalLifetimeRewards(address token) internal override returns (uint256) {
|
||||||
// The Curve Gauge can give exact lifetime rewards and accrued rewards for the CRV token
|
// The Curve Gauge can give exact lifetime rewards and accrued rewards for the CRV token
|
||||||
if (token == CRV_TOKEN) {
|
if (token == CRV_TOKEN) {
|
||||||
ICurveGauge(_gaugeController).user_checkpoint(CURVE_TREASURY);
|
|
||||||
return _getExternalLifetimeCurve();
|
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.
|
// 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));
|
priorTokenBalances[index] = IERC20(rewardToken).balanceOf(address(this));
|
||||||
}
|
}
|
||||||
// Mint other rewards to aToken
|
// Mint other rewards to aToken
|
||||||
ICurveTreasury(CURVE_TREASURY).claimGaugeRewards(_gaugeController);
|
ICurveTreasury(CURVE_TREASURY).claimGaugeRewards(_underlyingAsset);
|
||||||
|
|
||||||
for (uint256 index = 1; index < MAX_REWARD_TOKENS; index++) {
|
for (uint256 index = 1; index < MAX_REWARD_TOKENS; index++) {
|
||||||
address rewardToken = _getRewardsTokenAddress(index);
|
address rewardToken = _getRewardsTokenAddress(index);
|
||||||
|
@ -220,7 +223,9 @@ contract CurveGaugeRewardsAwareAToken is RewardsAwareAToken {
|
||||||
* @param amount Amount of tokens to deposit
|
* @param amount Amount of tokens to deposit
|
||||||
*/
|
*/
|
||||||
function _stake(address token, uint256 amount) internal override returns (uint256) {
|
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;
|
return amount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -230,21 +235,34 @@ contract CurveGaugeRewardsAwareAToken is RewardsAwareAToken {
|
||||||
* @param amount Amount of tokens to withdraw
|
* @param amount Amount of tokens to withdraw
|
||||||
*/
|
*/
|
||||||
function _unstake(address token, uint256 amount) internal override returns (uint256) {
|
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;
|
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:
|
* @param params Additional variadic field to include extra params. Expected parameters:
|
||||||
* @return address of gauge
|
* @return address of gauge
|
||||||
*/
|
*/
|
||||||
function _decodeParams(bytes memory params) internal pure returns (address) {
|
function _decodeGaugeAddress(bytes memory params) internal pure returns (address) {
|
||||||
address gauge = abi.decode(params, (address));
|
(address gauge, bool _isGaugeV2) = abi.decode(params, (address, bool));
|
||||||
|
|
||||||
return gauge;
|
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 */
|
/** End of Rewards Aware AToken functions */
|
||||||
|
|
||||||
/** Start of External getters */
|
/** Start of External getters */
|
||||||
|
|
|
@ -13,6 +13,7 @@ import {
|
||||||
} from '../../../protocol/libraries/aave-upgradeability/VersionedInitializable.sol';
|
} from '../../../protocol/libraries/aave-upgradeability/VersionedInitializable.sol';
|
||||||
import {ICurveFeeDistributor} from '../../interfaces/curve/ICurveFeeDistributor.sol';
|
import {ICurveFeeDistributor} from '../../interfaces/curve/ICurveFeeDistributor.sol';
|
||||||
import {ICurveTreasury} from '../../interfaces/curve/ICurveTreasury.sol';
|
import {ICurveTreasury} from '../../interfaces/curve/ICurveTreasury.sol';
|
||||||
|
import 'hardhat/console.sol';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @title Curve Treasury that holds Curve LP and Gauge tokens
|
* @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 => bool)) internal _entityTokenWhitelist;
|
||||||
mapping(address => mapping(address => address)) internal _entityTokenGauge;
|
mapping(address => mapping(address => address)) internal _entityTokenGauge;
|
||||||
|
mapping(address => bool) internal _isGaugeV2Compatible;
|
||||||
|
|
||||||
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
|
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
|
* @dev Revert if caller and selected token is not a whitelisted entity
|
||||||
*/
|
*/
|
||||||
modifier onlyWhitelistedEntity(address token) {
|
modifier onlyWhitelistedEntity(address token) {
|
||||||
|
console.log(msg.sender, token, _entityTokenWhitelist[msg.sender][token]);
|
||||||
require(_entityTokenWhitelist[msg.sender][token] == true, 'ENTITY_NOT_WHITELISTED');
|
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 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(
|
function initialize(address owner) external virtual initializer {
|
||||||
address owner,
|
|
||||||
address[] calldata entities,
|
|
||||||
address[] calldata tokens,
|
|
||||||
address[] calldata gauges
|
|
||||||
) external virtual initializer {
|
|
||||||
_owner = owner;
|
_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
|
/// @inheritdoc ICurveTreasury
|
||||||
|
@ -131,9 +119,23 @@ contract CurveTreasury is ICurveTreasury, VersionedInitializable {
|
||||||
address[] calldata entities,
|
address[] calldata entities,
|
||||||
address[] calldata tokens,
|
address[] calldata tokens,
|
||||||
address[] calldata gauges,
|
address[] calldata gauges,
|
||||||
|
bool[] memory areGaugesV2,
|
||||||
bool[] memory whitelisted
|
bool[] memory whitelisted
|
||||||
) external override onlyOwner {
|
) 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
|
/// @inheritdoc ICurveTreasury
|
||||||
|
@ -155,28 +157,30 @@ contract CurveTreasury is ICurveTreasury, VersionedInitializable {
|
||||||
IERC20(CRV_TOKEN).safeTransfer(msg.sender, crvRewards);
|
IERC20(CRV_TOKEN).safeTransfer(msg.sender, crvRewards);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Claim the extra rewards from Gauge Staking
|
if (_isGaugeV2Compatible[gauge] == true) {
|
||||||
uint256[] memory priorRewardsBalance = new uint256[](MAX_REWARD_TOKENS);
|
// Claim the extra rewards from Gauge Staking
|
||||||
uint256[] memory afterRewardsBalance = new uint256[](MAX_REWARD_TOKENS);
|
uint256[] memory priorRewardsBalance = new uint256[](MAX_REWARD_TOKENS);
|
||||||
|
uint256[] memory afterRewardsBalance = new uint256[](MAX_REWARD_TOKENS);
|
||||||
|
|
||||||
// Calculate balances prior claiming rewards
|
// Calculate balances prior claiming rewards
|
||||||
for (uint256 index = 1; index < MAX_REWARD_TOKENS; index++) {
|
for (uint256 index = 1; index < MAX_REWARD_TOKENS; index++) {
|
||||||
address rewardToken = ICurveGaugeView(gauge).reward_tokens(index - 1);
|
address rewardToken = ICurveGaugeView(gauge).reward_tokens(index - 1);
|
||||||
if (rewardToken == address(0)) break;
|
if (rewardToken == address(0)) break;
|
||||||
priorRewardsBalance[index] = IERC20(rewardToken).balanceOf(address(this));
|
priorRewardsBalance[index] = IERC20(rewardToken).balanceOf(address(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Claim extra rewards
|
// Claim extra rewards
|
||||||
ICurveGauge(gauge).claim_rewards();
|
ICurveGauge(gauge).claim_rewards();
|
||||||
|
|
||||||
// Transfer extra rewards to entity
|
// Transfer extra rewards to entity
|
||||||
for (uint256 index = 1; index < MAX_REWARD_TOKENS; index++) {
|
for (uint256 index = 1; index < MAX_REWARD_TOKENS; index++) {
|
||||||
address rewardToken = ICurveGaugeView(gauge).reward_tokens(index - 1);
|
address rewardToken = ICurveGaugeView(gauge).reward_tokens(index - 1);
|
||||||
if (rewardToken == address(0)) break;
|
if (rewardToken == address(0)) break;
|
||||||
afterRewardsBalance[index] = IERC20(rewardToken).balanceOf(address(this));
|
afterRewardsBalance[index] = IERC20(rewardToken).balanceOf(address(this));
|
||||||
uint256 rewardsAmount = afterRewardsBalance[index].sub(priorRewardsBalance[index]);
|
uint256 rewardsAmount = afterRewardsBalance[index].sub(priorRewardsBalance[index]);
|
||||||
if (rewardsAmount > 0) {
|
if (rewardsAmount > 0) {
|
||||||
IERC20(rewardToken).safeTransfer(msg.sender, rewardsAmount);
|
IERC20(rewardToken).safeTransfer(msg.sender, rewardsAmount);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -246,33 +250,6 @@ contract CurveTreasury is ICurveTreasury, VersionedInitializable {
|
||||||
return TREASURY_REVISION;
|
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
|
* @dev ERC20 approval to allow entity and gauge staking contracts to pull whitelisted tokens and rewards from the treasury
|
||||||
* @param entity Entity address
|
* @param entity Entity address
|
||||||
|
@ -284,6 +261,7 @@ contract CurveTreasury is ICurveTreasury, VersionedInitializable {
|
||||||
address entity,
|
address entity,
|
||||||
address token,
|
address token,
|
||||||
address gauge,
|
address gauge,
|
||||||
|
bool isGaugeV2,
|
||||||
uint256 amount
|
uint256 amount
|
||||||
) internal {
|
) internal {
|
||||||
IERC20(token).safeApprove(entity, 0);
|
IERC20(token).safeApprove(entity, 0);
|
||||||
|
@ -291,11 +269,15 @@ contract CurveTreasury is ICurveTreasury, VersionedInitializable {
|
||||||
if (gauge != address(0)) {
|
if (gauge != address(0)) {
|
||||||
IERC20(token).safeApprove(gauge, 0);
|
IERC20(token).safeApprove(gauge, 0);
|
||||||
IERC20(token).safeApprove(gauge, amount);
|
IERC20(token).safeApprove(gauge, amount);
|
||||||
for (uint256 index = 0; index < MAX_REWARD_TOKENS; index++) {
|
IERC20(CRV_TOKEN).safeApprove(entity, 0);
|
||||||
address reward = ICurveGaugeView(gauge).reward_tokens(index - 1);
|
IERC20(CRV_TOKEN).safeApprove(entity, amount);
|
||||||
if (reward == address(0)) break;
|
if (isGaugeV2 == true) {
|
||||||
IERC20(reward).safeApprove(entity, 0);
|
for (uint256 index = 0; index < MAX_REWARD_TOKENS; index++) {
|
||||||
IERC20(reward).safeApprove(entity, amount);
|
address reward = ICurveGaugeView(gauge).reward_tokens(index);
|
||||||
|
if (reward == address(0)) break;
|
||||||
|
IERC20(reward).safeApprove(entity, 0);
|
||||||
|
IERC20(reward).safeApprove(entity, amount);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -115,7 +115,6 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
|
||||||
|
|
||||||
reserve.updateState();
|
reserve.updateState();
|
||||||
reserve.updateInterestRates(asset, aToken, amount, 0);
|
reserve.updateInterestRates(asset, aToken, amount, 0);
|
||||||
|
|
||||||
IERC20(asset).safeTransferFrom(msg.sender, aToken, amount);
|
IERC20(asset).safeTransferFrom(msg.sender, aToken, amount);
|
||||||
|
|
||||||
bool isFirstDeposit = IAToken(aToken).mint(onBehalfOf, amount, reserve.liquidityIndex);
|
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) {
|
function FLASHLOAN_PREMIUM_TOTAL() public view returns (uint256) {
|
||||||
return _flashLoanPremiumTotal;
|
return _flashLoanPremiumTotal;
|
||||||
|
|
|
@ -84,12 +84,12 @@ export const CURVE_TREASURY = {
|
||||||
|
|
||||||
export const CURVE_CONFIG = {
|
export const CURVE_CONFIG = {
|
||||||
votingEscrow: {
|
votingEscrow: {
|
||||||
[eEthereumNetwork.main]: ZERO_ADDRESS,
|
[eEthereumNetwork.main]: '0x5f3b5DfEb7B28CDbD7FAba78963EE202a494e2A2',
|
||||||
},
|
},
|
||||||
curveFeeDistributor: {
|
curveFeeDistributor: {
|
||||||
[eEthereumNetwork.main]: ZERO_ADDRESS,
|
[eEthereumNetwork.main]: '0xA464e6DCda8AC41e03616F95f4BC98a13b8922Dc',
|
||||||
},
|
},
|
||||||
gaugeController: {
|
gaugeController: {
|
||||||
[eEthereumNetwork.main]: ZERO_ADDRESS,
|
[eEthereumNetwork.main]: '0x2F50D538606Fa9EDD2B11E2446BEb18C9D5846bB',
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -15,7 +15,7 @@ task(`deploy-curve-treasury`, `Deploys the CurveTreasury contract`)
|
||||||
.setAction(async ({ verify, proxyAdmin, treasuryAdmin, collector }, localBRE) => {
|
.setAction(async ({ verify, proxyAdmin, treasuryAdmin, collector }, localBRE) => {
|
||||||
await localBRE.run('set-DRE');
|
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`);
|
console.log(`\n- Curve Treasury deployment`);
|
||||||
const aaveCollector = collector || ZERO_ADDRESS;
|
const aaveCollector = collector || ZERO_ADDRESS;
|
||||||
|
|
||||||
|
@ -30,18 +30,15 @@ task(`deploy-curve-treasury`, `Deploys the CurveTreasury contract`)
|
||||||
);
|
);
|
||||||
|
|
||||||
// Freeze implementatation
|
// Freeze implementatation
|
||||||
await waitForTx(await implementation.initialize(ZERO_ADDRESS, [], [], []));
|
await waitForTx(await implementation.initialize(ZERO_ADDRESS));
|
||||||
|
|
||||||
// Deploy proxy
|
// Deploy proxy
|
||||||
const proxy = await deployInitializableAdminUpgradeabilityProxy(verify);
|
const proxy = await deployInitializableAdminUpgradeabilityProxy(verify);
|
||||||
|
|
||||||
const encoded = implementation.interface.encodeFunctionData('initialize', [
|
const encoded = implementation.interface.encodeFunctionData('initialize', [treasuryAdmin]);
|
||||||
treasuryAdmin,
|
await waitForTx(
|
||||||
[],
|
await proxy['initialize(address,address,bytes)'](implementation.address, proxyAdmin, encoded)
|
||||||
[],
|
);
|
||||||
[],
|
|
||||||
]);
|
|
||||||
await waitForTx(await proxy.initialize(implementation.address, proxyAdmin, encoded));
|
|
||||||
|
|
||||||
console.log(`\tFinished CurveTreasury deployment`);
|
console.log(`\tFinished CurveTreasury deployment`);
|
||||||
console.log(`\tProxy:`, proxy.address);
|
console.log(`\tProxy:`, proxy.address);
|
||||||
|
|
|
@ -15,20 +15,21 @@ import {
|
||||||
getLendingPoolAddressesProvider,
|
getLendingPoolAddressesProvider,
|
||||||
getLendingPoolConfiguratorProxy,
|
getLendingPoolConfiguratorProxy,
|
||||||
} from '../../../helpers/contracts-getters';
|
} from '../../../helpers/contracts-getters';
|
||||||
import {
|
import { deployCurveGaugeReserveInterestRateStrategy } from '../../../helpers/contracts-deployments';
|
||||||
deployCurveGaugeReserveInterestRateStrategy,
|
|
||||||
deployDefaultReserveInterestRateStrategy,
|
|
||||||
} from '../../../helpers/contracts-deployments';
|
|
||||||
import { IERC20Factory } from '../../../types/IERC20Factory';
|
import { IERC20Factory } from '../../../types/IERC20Factory';
|
||||||
import BigNumberJs from 'bignumber.js';
|
import BigNumberJs from 'bignumber.js';
|
||||||
import { CurveGaugeRewardsAwareATokenFactory } from '../../../types';
|
import {
|
||||||
|
CurveGaugeRewardsAwareATokenFactory,
|
||||||
|
CurveTreasury,
|
||||||
|
CurveTreasuryFactory,
|
||||||
|
} from '../../../types';
|
||||||
import { eContractid, eEthereumNetwork, tEthereumAddress } from '../../../helpers/types';
|
import { eContractid, eEthereumNetwork, tEthereumAddress } from '../../../helpers/types';
|
||||||
import { strategyWBTC } from '../../../markets/aave/reservesConfigs';
|
import { strategyWBTC } from '../../../markets/aave/reservesConfigs';
|
||||||
import { checkRewards } from '../helpers/rewards-distribution/verify';
|
import { checkRewards } from '../helpers/rewards-distribution/verify';
|
||||||
import { IRewardsAwareAToken } from '../../../types/IRewardsAwareAToken';
|
import { IRewardsAwareAToken } from '../../../types/IRewardsAwareAToken';
|
||||||
import { IRewardsAwareATokenFactory } from '../../../types/IRewardsAwareATokenFactory';
|
import { IRewardsAwareATokenFactory } from '../../../types/IRewardsAwareATokenFactory';
|
||||||
import { BigNumber } from 'ethers';
|
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 { IERC20 } from '../../../types/IERC20';
|
||||||
import {
|
import {
|
||||||
getContractAddressWithJsonFallback,
|
getContractAddressWithJsonFallback,
|
||||||
|
@ -46,7 +47,6 @@ interface GaugeInfo {
|
||||||
symbol: string;
|
symbol: string;
|
||||||
rewardTokens: tEthereumAddress[];
|
rewardTokens: tEthereumAddress[];
|
||||||
}
|
}
|
||||||
const BLOCK_HEIGHT = '';
|
|
||||||
const USER_ADDRESS = '0x9c5083dd4838E120Dbeac44C052179692Aa5dAC5';
|
const USER_ADDRESS = '0x9c5083dd4838E120Dbeac44C052179692Aa5dAC5';
|
||||||
|
|
||||||
const CRV_TOKEN = '0xd533a949740bb3306d119cc777fa900ba034cd52';
|
const CRV_TOKEN = '0xd533a949740bb3306d119cc777fa900ba034cd52';
|
||||||
|
@ -86,12 +86,18 @@ const GAUGE_ANKR: GaugeInfo = {
|
||||||
'0x8290333ceF9e6D528dD5618Fb97a76f268f3EDD4',
|
'0x8290333ceF9e6D528dD5618Fb97a76f268f3EDD4',
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
const isGaugeV2 = (address: tEthereumAddress) =>
|
||||||
|
GAUGE_3POOL.address.toLowerCase() !== address.toLowerCase();
|
||||||
|
|
||||||
const unstakeAllGauges = async (key: SignerWithAddress, gauges: tEthereumAddress[]) => {
|
const unstakeAllGauges = async (key: SignerWithAddress, gauges: tEthereumAddress[]) => {
|
||||||
for (let x = 0; x < gauges.length; x++) {
|
for (let x = 0; x < gauges.length; x++) {
|
||||||
await waitForTx(
|
if (isGaugeV2(gauges[x])) {
|
||||||
await ICurveGaugeFactory.connect(gauges[x], key.signer).withdraw(MAX_UINT_AMOUNT)
|
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
|
false
|
||||||
);
|
);
|
||||||
const interestRateStrategyAddress = interestStrategy.address;
|
const interestRateStrategyAddress = interestStrategy.address;
|
||||||
const encodedParams = defaultAbiCoder.encode(['string'], [gauge.address]);
|
const encodedParams = defaultAbiCoder.encode(
|
||||||
|
['address', 'bool'],
|
||||||
|
[gauge.address, isGaugeV2(gauge.address)]
|
||||||
|
);
|
||||||
const curveReserveInitParams = [
|
const curveReserveInitParams = [
|
||||||
{
|
{
|
||||||
aTokenImpl,
|
aTokenImpl,
|
||||||
|
@ -175,7 +184,8 @@ const depositPoolToken = async (
|
||||||
const pool = await getLendingPool();
|
const pool = await getLendingPool();
|
||||||
const curveReserveToken = IERC20Factory.connect(gauge.underlying, key.signer);
|
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(
|
const txDeposit = await waitForTx(
|
||||||
await pool.connect(key.signer).deposit(gauge.underlying, amount, key.address, '0')
|
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 crvToken: IERC20;
|
||||||
let snxToken: IERC20;
|
let snxToken: IERC20;
|
||||||
|
|
||||||
|
let curveTreasury: CurveTreasury;
|
||||||
|
|
||||||
before('Initializing configuration', async () => {
|
before('Initializing configuration', async () => {
|
||||||
// Sets BigNumber for this suite, instead of globally
|
// Sets BigNumber for this suite, instead of globally
|
||||||
BigNumberJs.config({ DECIMAL_PLACES: 0, ROUNDING_MODE: BigNumberJs.ROUND_DOWN });
|
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
|
// Depositor should have 3pool, EURS, AAVE3, and ANKR balance
|
||||||
const curve3poolBalance = await curve3poolErc20.balanceOf(USER_ADDRESS);
|
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 curveEursBalance = await curveEursErc20.balanceOf(USER_ADDRESS);
|
||||||
const curveAave3Balance = await curveAave3Erc20.balanceOf(USER_ADDRESS);
|
const curveAave3Balance = await curveAave3Erc20.balanceOf(USER_ADDRESS);
|
||||||
const curveAnkrBalance = await curveAnkrErc20.balanceOf(USER_ADDRESS);
|
const curveAnkrBalance = await curveAnkrErc20.balanceOf(USER_ADDRESS);
|
||||||
|
@ -292,16 +300,17 @@ makeSuite('Curve Rewards Aware aToken', (testEnv: TestEnv) => {
|
||||||
eEthereumNetwork.main
|
eEthereumNetwork.main
|
||||||
);
|
);
|
||||||
|
|
||||||
const { proxy: curveTreasury } = await DRE.run('deploy-curve-treasury', {
|
const { proxy: curveTreasuryAddress } = await DRE.run('deploy-curve-treasury', {
|
||||||
proxyAdmin: ZERO_ADDRESS,
|
proxyAdmin: testEnv.users[1].address,
|
||||||
treasuryAdmin: ZERO_ADDRESS,
|
treasuryAdmin: testEnv.users[0].address,
|
||||||
collector,
|
collector,
|
||||||
});
|
});
|
||||||
|
|
||||||
// Gauge tokens should be listed at Aave test deployment
|
// Gauge tokens should be listed at Aave test deployment
|
||||||
await listCurveLPToken(GAUGE_3POOL, curveTreasury);
|
await listCurveLPToken(GAUGE_3POOL, curveTreasuryAddress);
|
||||||
await listCurveLPToken(GAUGE_EURS, curveTreasury);
|
await listCurveLPToken(GAUGE_EURS, curveTreasuryAddress);
|
||||||
await listCurveLPToken(GAUGE_AAVE3, curveTreasury);
|
await listCurveLPToken(GAUGE_AAVE3, curveTreasuryAddress);
|
||||||
await listCurveLPToken(GAUGE_ANKR, curveTreasury);
|
await listCurveLPToken(GAUGE_ANKR, curveTreasuryAddress);
|
||||||
|
|
||||||
const allTokens = await testEnv.helpersContract.getAllATokens();
|
const allTokens = await testEnv.helpersContract.getAllATokens();
|
||||||
|
|
||||||
|
@ -319,9 +328,26 @@ makeSuite('Curve Rewards Aware aToken', (testEnv: TestEnv) => {
|
||||||
);
|
);
|
||||||
aANKR = IRewardsAwareATokenFactory.connect(
|
aANKR = IRewardsAwareATokenFactory.connect(
|
||||||
allTokens.find((aToken) => aToken.symbol.includes('ankr'))?.tokenAddress || ZERO_ADDRESS,
|
allTokens.find((aToken) => aToken.symbol.includes('ankr'))?.tokenAddress || ZERO_ADDRESS,
|
||||||
|
|
||||||
await getFirstSigner()
|
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', () => {
|
after('Reset', () => {
|
||||||
|
@ -390,7 +416,7 @@ makeSuite('Curve Rewards Aware aToken', (testEnv: TestEnv) => {
|
||||||
|
|
||||||
it('Deposit and generate user reward checkpoints', async () => {
|
it('Deposit and generate user reward checkpoints', async () => {
|
||||||
// Deposits
|
// 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);
|
const curveATokenBalance = await crvToken.balanceOf(a3POOL.address);
|
||||||
expect(curveATokenBalance).to.be.eq('0', 'CRV rewards should be zero');
|
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
|
// Pass time to generate rewards
|
||||||
await increaseTime(ONE_DAY);
|
await increaseTime(ONE_DAY);
|
||||||
|
|
||||||
// Withdraw
|
// Withdraw
|
||||||
await withdrawPoolToken(depositor, GAUGE_3POOL, a3POOL.address);
|
await withdrawPoolToken(depositor, GAUGE_3POOL, a3POOL.address, true);
|
||||||
const curveATokenBalance = await crvToken.balanceOf(a3POOL.address);
|
const curveATokenBalance = await crvToken.balanceOf(a3POOL.address);
|
||||||
expect(curveATokenBalance).to.be.eq('0', 'CRV rewards should be zero');
|
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
|
// Claim
|
||||||
await claimFromGauge(depositor, GAUGE_AAVE3, aAAVE3.address);
|
await claimFromGauge(depositor, GAUGE_AAVE3, aAAVE3.address, false);
|
||||||
const curveATokenBalance = await crvToken.balanceOf(a3POOL.address);
|
const curveATokenBalance = await crvToken.balanceOf(a3POOL.address);
|
||||||
expect(curveATokenBalance).to.be.eq(
|
expect(curveATokenBalance).to.be.eq(
|
||||||
'0',
|
'0',
|
||||||
|
|
Loading…
Reference in New Issue
Block a user