mirror of
https://github.com/Instadapp/aave-protocol-v2.git
synced 2024-07-29 21:47:30 +00:00
feat: Detect extra rewards at AToken when deposit and withdrawal of Curve gauge tokens.
This commit is contained in:
parent
5b56182157
commit
5e66335375
|
@ -224,7 +224,30 @@ contract CurveGaugeRewardsAwareAToken is RewardsAwareAToken {
|
||||||
*/
|
*/
|
||||||
function _stake(address token, uint256 amount) internal override returns (uint256) {
|
function _stake(address token, uint256 amount) internal override returns (uint256) {
|
||||||
if (token == UNDERLYING_ASSET_ADDRESS()) {
|
if (token == UNDERLYING_ASSET_ADDRESS()) {
|
||||||
ICurveTreasury(CURVE_TREASURY).deposit(token, amount, true);
|
if (_rewardTokens[1] != address(0)) {
|
||||||
|
// Track the pending rewards to distribute at `_retrieveAvailableReward` call
|
||||||
|
uint256[MAX_REWARD_TOKENS] memory priorTokenBalances;
|
||||||
|
for (uint256 index = 1; index < MAX_REWARD_TOKENS; index++) {
|
||||||
|
address rewardToken = _getRewardsTokenAddress(index);
|
||||||
|
if (rewardToken == address(0)) break;
|
||||||
|
if (rewardToken == CRV_TOKEN) continue;
|
||||||
|
priorTokenBalances[index] = IERC20(rewardToken).balanceOf(address(this));
|
||||||
|
}
|
||||||
|
// At deposits it sends extra rewards to aToken
|
||||||
|
ICurveTreasury(CURVE_TREASURY).deposit(token, amount, true);
|
||||||
|
|
||||||
|
for (uint256 index = 1; index < MAX_REWARD_TOKENS; index++) {
|
||||||
|
address rewardToken = _getRewardsTokenAddress(index);
|
||||||
|
if (rewardToken == address(0)) break;
|
||||||
|
if (rewardToken == CRV_TOKEN) continue;
|
||||||
|
uint256 balance = IERC20(rewardToken).balanceOf(address(this));
|
||||||
|
_pendingRewards[rewardToken] = _pendingRewards[rewardToken].add(
|
||||||
|
balance.sub(priorTokenBalances[index])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ICurveTreasury(CURVE_TREASURY).deposit(token, amount, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return amount;
|
return amount;
|
||||||
}
|
}
|
||||||
|
@ -236,7 +259,30 @@ contract CurveGaugeRewardsAwareAToken is RewardsAwareAToken {
|
||||||
*/
|
*/
|
||||||
function _unstake(address token, uint256 amount) internal override returns (uint256) {
|
function _unstake(address token, uint256 amount) internal override returns (uint256) {
|
||||||
if (token == UNDERLYING_ASSET_ADDRESS()) {
|
if (token == UNDERLYING_ASSET_ADDRESS()) {
|
||||||
ICurveTreasury(CURVE_TREASURY).withdraw(token, amount, true);
|
// Claim other Curve gauge tokens, and track the pending rewards to distribute at `_retrieveAvailableReward` call
|
||||||
|
if (_rewardTokens[1] != address(0)) {
|
||||||
|
uint256[MAX_REWARD_TOKENS] memory priorTokenBalances;
|
||||||
|
for (uint256 index = 1; index < MAX_REWARD_TOKENS; index++) {
|
||||||
|
address rewardToken = _getRewardsTokenAddress(index);
|
||||||
|
if (rewardToken == address(0)) break;
|
||||||
|
if (rewardToken == CRV_TOKEN) continue;
|
||||||
|
priorTokenBalances[index] = IERC20(rewardToken).balanceOf(address(this));
|
||||||
|
}
|
||||||
|
// Mint other rewards to aToken
|
||||||
|
ICurveTreasury(CURVE_TREASURY).withdraw(token, amount, true);
|
||||||
|
|
||||||
|
for (uint256 index = 1; index < MAX_REWARD_TOKENS; index++) {
|
||||||
|
address rewardToken = _getRewardsTokenAddress(index);
|
||||||
|
if (rewardToken == address(0)) break;
|
||||||
|
if (rewardToken == CRV_TOKEN) continue;
|
||||||
|
uint256 balance = IERC20(rewardToken).balanceOf(address(this));
|
||||||
|
_pendingRewards[rewardToken] = _pendingRewards[rewardToken].add(
|
||||||
|
balance.sub(priorTokenBalances[index])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ICurveTreasury(CURVE_TREASURY).withdraw(token, amount, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return amount;
|
return amount;
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,7 +68,6 @@ 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');
|
||||||
_;
|
_;
|
||||||
}
|
}
|
||||||
|
@ -98,7 +97,35 @@ contract CurveTreasury is ICurveTreasury, VersionedInitializable {
|
||||||
IERC20(token).safeTransferFrom(msg.sender, address(this), amount);
|
IERC20(token).safeTransferFrom(msg.sender, address(this), amount);
|
||||||
|
|
||||||
if (useGauge && _entityTokenGauge[msg.sender][token] != address(0)) {
|
if (useGauge && _entityTokenGauge[msg.sender][token] != address(0)) {
|
||||||
_stakeGauge(_entityTokenGauge[msg.sender][token], amount);
|
address gauge = _entityTokenGauge[msg.sender][token];
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Claim extra rewards
|
||||||
|
_stakeGauge(_entityTokenGauge[msg.sender][token], amount);
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_stakeGauge(_entityTokenGauge[msg.sender][token], amount);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,7 +136,35 @@ contract CurveTreasury is ICurveTreasury, VersionedInitializable {
|
||||||
bool useGauge
|
bool useGauge
|
||||||
) external override onlyWhitelistedEntity(token) {
|
) external override onlyWhitelistedEntity(token) {
|
||||||
if (useGauge && _entityTokenGauge[msg.sender][token] != address(0)) {
|
if (useGauge && _entityTokenGauge[msg.sender][token] != address(0)) {
|
||||||
_unstakeGauge(_entityTokenGauge[msg.sender][token], amount);
|
address gauge = _entityTokenGauge[msg.sender][token];
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Claim extra rewards
|
||||||
|
_unstakeGauge(_entityTokenGauge[msg.sender][token], amount);
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_unstakeGauge(_entityTokenGauge[msg.sender][token], amount);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
IERC20(token).safeTransfer(msg.sender, amount);
|
IERC20(token).safeTransfer(msg.sender, amount);
|
||||||
}
|
}
|
||||||
|
|
|
@ -107,6 +107,4 @@ export const checkRewards = async (
|
||||||
expect(userRewardsBefore[i]).to.be.eq(userRewardsAfter[i], 'Rewards should stay the same');
|
expect(userRewardsBefore[i]).to.be.eq(userRewardsAfter[i], 'Rewards should stay the same');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -333,7 +333,6 @@ makeSuite('Curve Rewards Aware aToken', (testEnv: TestEnv) => {
|
||||||
curveTreasury = CurveTreasuryFactory.connect(curveTreasuryAddress, testEnv.users[0].signer);
|
curveTreasury = CurveTreasuryFactory.connect(curveTreasuryAddress, testEnv.users[0].signer);
|
||||||
|
|
||||||
// Enable atoken entities into Curve Treasury
|
// Enable atoken entities into Curve Treasury
|
||||||
console.log(a3POOL.address, aEURS.address, aAAVE3.address, aANKR.address);
|
|
||||||
await waitForTx(
|
await waitForTx(
|
||||||
await curveTreasury.setWhitelist(
|
await curveTreasury.setWhitelist(
|
||||||
[a3POOL.address, aEURS.address, aAAVE3.address, aANKR.address],
|
[a3POOL.address, aEURS.address, aAAVE3.address, aANKR.address],
|
||||||
|
@ -466,11 +465,18 @@ 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_EURS, aEURS.address, parseEther('100000'));
|
await depositPoolToken(depositor, GAUGE_EURS, aEURS.address, parseEther('10000'), false);
|
||||||
const curveATokenBalance = await crvToken.balanceOf(aEURS.address);
|
const curveATokenBalance = await crvToken.balanceOf(aEURS.address);
|
||||||
expect(curveATokenBalance).to.be.eq('0', 'CRV should be zero');
|
expect(curveATokenBalance).to.be.eq('0', 'CRV should be zero');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('Second deposit should add user reward checkpoints', async () => {
|
||||||
|
// Pass time to generate rewards
|
||||||
|
await advanceTimeAndBlock(ONE_DAY * 14);
|
||||||
|
|
||||||
|
await depositPoolToken(depositor, GAUGE_EURS, aEURS.address, parseEther('10000'), true);
|
||||||
|
});
|
||||||
|
|
||||||
it('Increase time and claim CRV and SNX', async () => {
|
it('Increase time and claim CRV and SNX', async () => {
|
||||||
// Pass time to generate rewards
|
// Pass time to generate rewards
|
||||||
await advanceTimeAndBlock(ONE_DAY * 14);
|
await advanceTimeAndBlock(ONE_DAY * 14);
|
||||||
|
@ -484,7 +490,7 @@ makeSuite('Curve Rewards Aware aToken', (testEnv: TestEnv) => {
|
||||||
await increaseTime(ONE_DAY);
|
await increaseTime(ONE_DAY);
|
||||||
|
|
||||||
// Withdraw
|
// Withdraw
|
||||||
await withdrawPoolToken(depositor, GAUGE_EURS, aEURS.address);
|
await withdrawPoolToken(depositor, GAUGE_EURS, aEURS.address, true);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('Claim the remaining CRV and SNX', async () => {
|
it('Claim the remaining CRV and SNX', async () => {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user