mirror of
https://github.com/Instadapp/aave-protocol-v2.git
synced 2024-07-29 21:47:30 +00:00
fix: Use virtual rewards/balances when possible (update tests accordingly)
This commit is contained in:
parent
6c34a062af
commit
782d8acca2
|
@ -54,11 +54,16 @@ contract StaticATokenLM is ERC20 {
|
|||
mapping(address => uint256) public _nonces;
|
||||
|
||||
uint256 public accRewardstokenPerShare;
|
||||
uint256 public lifeTimeRewardsClaimed;
|
||||
uint256 public lifeTimeRewards;
|
||||
uint256 public lastRewardBlock;
|
||||
mapping(address => uint256) public rewardDebts; // Measured in Rays
|
||||
mapping(address => uint256) public unclaimedRewards; // Measured in Rays
|
||||
IAaveIncentivesController internal _incentivesController;
|
||||
|
||||
// user => rewardDebt (in RAYs)
|
||||
mapping(address => uint256) public rewardDebts;
|
||||
// user => unclaimedRewards (in RAYs)
|
||||
mapping(address => uint256) public unclaimedRewards;
|
||||
|
||||
IAaveIncentivesController internal _incentivesController;
|
||||
address public immutable currentRewardToken;
|
||||
|
||||
constructor(
|
||||
|
@ -357,8 +362,7 @@ contract StaticATokenLM is ERC20 {
|
|||
bool fromUnderlying
|
||||
) internal returns (uint256) {
|
||||
require(recipient != address(0), 'INVALID_RECIPIENT');
|
||||
updateRewards();
|
||||
|
||||
_updateRewards();
|
||||
_updateUnclaimedRewards(recipient);
|
||||
|
||||
if (fromUnderlying) {
|
||||
|
@ -384,8 +388,7 @@ contract StaticATokenLM is ERC20 {
|
|||
) internal returns (uint256, uint256) {
|
||||
require(recipient != address(0), 'INVALID_RECIPIENT');
|
||||
require(staticAmount == 0 || dynamicAmount == 0, 'ONLY_ONE_AMOUNT_FORMAT_ALLOWED');
|
||||
updateRewards();
|
||||
|
||||
_updateRewards();
|
||||
_updateUnclaimedRewards(owner);
|
||||
|
||||
uint256 userBalance = balanceOf(owner);
|
||||
|
@ -446,32 +449,65 @@ contract StaticATokenLM is ERC20 {
|
|||
/**
|
||||
* @dev Claims rewards from the `_incentivesController` and update `accRewardstokenPerShare`
|
||||
*/
|
||||
function updateRewards() public {
|
||||
function _updateRewards() internal {
|
||||
// Update the virtual rewards without actually claiming.
|
||||
if (block.number > lastRewardBlock) {
|
||||
lastRewardBlock = block.number;
|
||||
uint256 _supply = totalSupply();
|
||||
if (_supply == 0) {
|
||||
// No rewards can have accrued since last because there were no funds.
|
||||
return;
|
||||
}
|
||||
|
||||
address[] memory assets = new address[](1);
|
||||
assets[0] = address(ATOKEN);
|
||||
|
||||
uint256 freshReward =
|
||||
_incentivesController.claimRewards(assets, type(uint256).max, address(this)).wadToRay();
|
||||
uint256 freshRewards = _incentivesController.getRewardsBalance(assets, address(this));
|
||||
uint256 externalLifetimeRewards = lifeTimeRewardsClaimed.add(freshRewards);
|
||||
uint256 diff = externalLifetimeRewards.sub(lifeTimeRewards).wadToRay();
|
||||
|
||||
accRewardstokenPerShare = accRewardstokenPerShare.add(
|
||||
freshReward.rayDivNoRounding(_supply.wadToRay())
|
||||
(diff).rayDivNoRounding(_supply.wadToRay())
|
||||
);
|
||||
|
||||
lifeTimeRewards = externalLifetimeRewards;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Update the rewards and claim rewards for the user
|
||||
* @param user The address of the user to claim rewards for
|
||||
*/
|
||||
function updateAndClaimRewards(address user) public {
|
||||
updateRewards();
|
||||
claimRewards(user);
|
||||
function collectAndUpdateRewards() public {
|
||||
if (block.number > lastRewardBlock) {
|
||||
lastRewardBlock = block.number;
|
||||
uint256 _supply = totalSupply();
|
||||
|
||||
// We need to perform the check even though there is no supply, as rewards can have accrued before it was removed
|
||||
|
||||
address[] memory assets = new address[](1);
|
||||
assets[0] = address(ATOKEN);
|
||||
|
||||
uint256 freshlyClaimed =
|
||||
_incentivesController.claimRewards(assets, type(uint256).max, address(this));
|
||||
uint256 externalLifetimeRewards = lifeTimeRewardsClaimed.add(freshlyClaimed);
|
||||
uint256 diff = externalLifetimeRewards.sub(lifeTimeRewards).wadToRay();
|
||||
|
||||
if (_supply > 0 && diff > 0) {
|
||||
accRewardstokenPerShare = accRewardstokenPerShare.add(
|
||||
(diff).rayDivNoRounding(_supply.wadToRay())
|
||||
);
|
||||
}
|
||||
|
||||
if (diff > 0) {
|
||||
lifeTimeRewards = externalLifetimeRewards;
|
||||
}
|
||||
// Unsure if we can also move this in
|
||||
lifeTimeRewardsClaimed = externalLifetimeRewards;
|
||||
}
|
||||
/*
|
||||
// This one could just as well do both?
|
||||
address[] memory assets = new address[](1);
|
||||
assets[0] = address(ATOKEN);
|
||||
uint256 freshlyClaimed =
|
||||
_incentivesController.claimRewards(assets, type(uint256).max, address(this));
|
||||
lifeTimeRewardsClaimed = lifeTimeRewardsClaimed.add(freshlyClaimed);*/
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -479,10 +515,18 @@ contract StaticATokenLM is ERC20 {
|
|||
* makes sense for small holders
|
||||
* @param user The address of the user to claim rewards for
|
||||
*/
|
||||
function claimRewards(address user) public {
|
||||
// Claim rewards without collecting the latest rewards
|
||||
function claimRewards(address user, bool forceUpdate) public {
|
||||
if (forceUpdate) {
|
||||
collectAndUpdateRewards();
|
||||
}
|
||||
|
||||
uint256 balance = balanceOf(user);
|
||||
uint256 reward = _getClaimableRewards(user, balance); // Remember that this is converting to wad
|
||||
uint256 reward = _getClaimableRewards(user, balance, false);
|
||||
uint256 totBal = IERC20(currentRewardToken).balanceOf(address(this));
|
||||
if (reward > totBal) {
|
||||
// Throw away excess rewards
|
||||
reward = totBal;
|
||||
}
|
||||
if (reward > 0) {
|
||||
unclaimedRewards[user] = 0;
|
||||
IERC20(currentRewardToken).safeTransfer(user, reward);
|
||||
|
@ -508,21 +552,48 @@ contract StaticATokenLM is ERC20 {
|
|||
function _updateUnclaimedRewards(address user) internal {
|
||||
uint256 balance = balanceOf(user);
|
||||
if (balance > 0) {
|
||||
uint256 pending = _getPendingRewards(user, balance);
|
||||
uint256 pending = _getPendingRewards(user, balance, false);
|
||||
unclaimedRewards[user] = unclaimedRewards[user].add(pending);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Compute the pending in RAY (rounded down). Pending is the amount to add (not yet unclaimed) rewards in RAY (rounded down).
|
||||
* @dev Compute the pending in RAY (rounded down). Pending is the amount to add (not yet unclaimed) rewards in RAY (rounded down).
|
||||
* @param user The user to compute for
|
||||
* @param balance The balance of the user
|
||||
* @return The amound of pending rewards in RAY
|
||||
*/
|
||||
function _getPendingRewards(address user, uint256 balance) internal view returns (uint256) {
|
||||
function _getPendingRewards(
|
||||
address user,
|
||||
uint256 balance,
|
||||
bool fresh
|
||||
) internal view returns (uint256) {
|
||||
if (balance == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// TODO: This could retrieve the last such that we know the most up to date stuff :eyes:
|
||||
// Compute the pending rewards in ray, rounded down.
|
||||
uint256 rayBalance = balance.wadToRay();
|
||||
uint256 _reward = rayBalance.rayMulNoRounding(accRewardstokenPerShare);
|
||||
|
||||
uint256 _supply = totalSupply();
|
||||
uint256 _accRewardstokenPerShare = accRewardstokenPerShare;
|
||||
|
||||
if (_supply != 0 && fresh) {
|
||||
// Done purely virtually, this is used for retrieving up to date rewards for the ui
|
||||
address[] memory assets = new address[](1);
|
||||
assets[0] = address(ATOKEN);
|
||||
|
||||
uint256 freshReward = _incentivesController.getRewardsBalance(assets, address(this));
|
||||
uint256 externalLifetimeRewards = lifeTimeRewardsClaimed.add(freshReward);
|
||||
uint256 diff = externalLifetimeRewards.sub(lifeTimeRewards).wadToRay();
|
||||
|
||||
_accRewardstokenPerShare = _accRewardstokenPerShare.add(
|
||||
(diff).rayDivNoRounding(_supply.wadToRay())
|
||||
);
|
||||
}
|
||||
|
||||
uint256 _reward = rayBalance.rayMulNoRounding(_accRewardstokenPerShare);
|
||||
uint256 _debt = rewardDebts[user];
|
||||
if (_reward > _debt) {
|
||||
// Safe because line above
|
||||
|
@ -531,17 +602,32 @@ contract StaticATokenLM is ERC20 {
|
|||
return 0;
|
||||
}
|
||||
|
||||
function _getClaimableRewards(address user, uint256 balance) internal view returns (uint256) {
|
||||
uint256 reward = unclaimedRewards[user].add(_getPendingRewards(user, balance));
|
||||
function _getClaimableRewards(
|
||||
address user,
|
||||
uint256 balance,
|
||||
bool fresh
|
||||
) internal view returns (uint256) {
|
||||
uint256 reward = unclaimedRewards[user].add(_getPendingRewards(user, balance, fresh));
|
||||
return reward.rayToWadNoRounding();
|
||||
}
|
||||
|
||||
function getTotalClaimableRewards() public view returns (uint256) {
|
||||
address[] memory assets = new address[](1);
|
||||
assets[0] = address(ATOKEN);
|
||||
uint256 freshRewards = _incentivesController.getRewardsBalance(assets, address(this));
|
||||
return IERC20(currentRewardToken).balanceOf(address(this)).add(freshRewards);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Get the total claimable rewards for a user in WAD cliam
|
||||
* @param user The address of the user
|
||||
* @return The claimable amount of rewards in WAD
|
||||
*/
|
||||
function getClaimableRewards(address user) public view returns (uint256) {
|
||||
return _getClaimableRewards(user, balanceOf(user));
|
||||
return _getClaimableRewards(user, balanceOf(user), true);
|
||||
}
|
||||
|
||||
function getUnclaimedRewards(address user) public view returns (uint256) {
|
||||
return unclaimedRewards[user].rayToWadNoRounding();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ import {
|
|||
advanceTimeAndBlock,
|
||||
} from '../../../../helpers/misc-utils';
|
||||
import { BigNumber, providers, Signer, utils } from 'ethers';
|
||||
import { MAX_UINT_AMOUNT } from '../../../../helpers/constants';
|
||||
import { MAX_UINT_AMOUNT, USD_ADDRESS } from '../../../../helpers/constants';
|
||||
import { AbiCoder, formatEther, verifyTypedData } from 'ethers/lib/utils';
|
||||
|
||||
import { _TypedDataEncoder } from 'ethers/lib/utils';
|
||||
|
@ -143,7 +143,7 @@ describe('StaticATokenLM: aToken wrapper with static balances and liquidity mini
|
|||
|
||||
const pendingRewards2 = await staticAToken.getClaimableRewards(userSigner._address);
|
||||
|
||||
await waitForTx(await staticAToken.updateRewards());
|
||||
await waitForTx(await staticAToken.collectAndUpdateRewards());
|
||||
|
||||
const pendingRewards3 = await staticAToken.getClaimableRewards(userSigner._address);
|
||||
|
||||
|
@ -153,20 +153,36 @@ describe('StaticATokenLM: aToken wrapper with static balances and liquidity mini
|
|||
);
|
||||
|
||||
const pendingRewards4 = await staticAToken.getClaimableRewards(userSigner._address);
|
||||
const totPendingRewards4 = await staticAToken.getTotalClaimableRewards();
|
||||
const claimedRewards4 = await stkAave.balanceOf(userSigner._address);
|
||||
const stkAaveStatic4 = await stkAave.balanceOf(staticAToken.address);
|
||||
|
||||
await waitForTx(await staticAToken.claimRewards(userSigner._address));
|
||||
await waitForTx(await staticAToken.claimRewards(userSigner._address, false));
|
||||
|
||||
const pendingRewards5 = await staticAToken.getClaimableRewards(userSigner._address);
|
||||
const totPendingRewards5 = await staticAToken.getTotalClaimableRewards();
|
||||
const claimedRewards5 = await stkAave.balanceOf(userSigner._address);
|
||||
const stkAaveStatic5 = await stkAave.balanceOf(staticAToken.address);
|
||||
|
||||
await waitForTx(await staticAToken.collectAndUpdateRewards());
|
||||
const pendingRewards6 = await staticAToken.getClaimableRewards(userSigner._address);
|
||||
|
||||
// Checks
|
||||
|
||||
expect(pendingRewards2).to.be.gt(pendingRewards1);
|
||||
expect(pendingRewards3).to.be.gt(pendingRewards2);
|
||||
expect(pendingRewards4).to.be.gt(pendingRewards3);
|
||||
expect(pendingRewards5).to.be.eq(0);
|
||||
expect(totPendingRewards4).to.be.gte(pendingRewards4);
|
||||
expect(pendingRewards5).to.be.eq(0); // User "sacrifice" excess rewards to save on gas-costs
|
||||
expect(pendingRewards6).to.be.eq(0);
|
||||
|
||||
expect(claimedRewards4).to.be.eq(0);
|
||||
expect(claimedRewards5).to.be.eq(pendingRewards4);
|
||||
|
||||
// Expect the user to have withdrawn everything.
|
||||
expect(claimedRewards5).to.be.eq(stkAaveStatic4);
|
||||
expect(stkAaveStatic5).to.be.eq(0);
|
||||
|
||||
expect(totPendingRewards5).to.be.gt(0);
|
||||
});
|
||||
|
||||
it('Check getters', async () => {
|
||||
|
@ -193,7 +209,50 @@ describe('StaticATokenLM: aToken wrapper with static balances and liquidity mini
|
|||
expect(dynamicBalance).to.be.eq(dynamicBalanceFromStatic);
|
||||
});
|
||||
|
||||
it.skip('Multiple updates in one block (Breaks if GasReport enabled)', async () => {
|
||||
it.skip('Multiple deposits in one block (Breaks if GasReport enabled)', async () => {
|
||||
const amountToDeposit = utils.parseEther('5');
|
||||
|
||||
// Just preparation
|
||||
await waitForTx(await weth.deposit({ value: amountToDeposit.mul(2) }));
|
||||
await waitForTx(
|
||||
await weth.approve(staticAToken.address, amountToDeposit.mul(2), defaultTxParams)
|
||||
);
|
||||
|
||||
await DRE.network.provider.send('evm_setAutomine', [false]);
|
||||
|
||||
// Depositing
|
||||
let a = await staticAToken.deposit(
|
||||
userSigner._address,
|
||||
amountToDeposit,
|
||||
0,
|
||||
true,
|
||||
defaultTxParams
|
||||
);
|
||||
|
||||
// Depositing
|
||||
let b = await staticAToken.deposit(
|
||||
userSigner._address,
|
||||
amountToDeposit,
|
||||
0,
|
||||
true,
|
||||
defaultTxParams
|
||||
);
|
||||
|
||||
await DRE.network.provider.send('evm_mine', []);
|
||||
|
||||
const aReceipt = await DRE.network.provider.send('eth_getTransactionReceipt', [a.hash]);
|
||||
const bReceipt = await DRE.network.provider.send('eth_getTransactionReceipt', [b.hash]);
|
||||
|
||||
const aGas = BigNumber.from(aReceipt['gasUsed']);
|
||||
const bGas = BigNumber.from(bReceipt['gasUsed']);
|
||||
|
||||
expect(aGas).to.be.gt(300000);
|
||||
expect(bGas).to.be.lt(250000);
|
||||
|
||||
await DRE.network.provider.send('evm_setAutomine', [true]);
|
||||
});
|
||||
|
||||
it.skip('Multiple collectAndUpdate in one block (Breaks if GasReport enabled)', async () => {
|
||||
const amountToDeposit = utils.parseEther('5');
|
||||
|
||||
// Just preparation
|
||||
|
@ -209,8 +268,8 @@ describe('StaticATokenLM: aToken wrapper with static balances and liquidity mini
|
|||
|
||||
await DRE.network.provider.send('evm_setAutomine', [false]);
|
||||
|
||||
let a = await staticAToken.updateRewards();
|
||||
let b = await staticAToken.updateRewards();
|
||||
let a = await staticAToken.collectAndUpdateRewards();
|
||||
let b = await staticAToken.collectAndUpdateRewards();
|
||||
|
||||
await DRE.network.provider.send('evm_mine', []);
|
||||
|
||||
|
@ -249,12 +308,12 @@ describe('StaticATokenLM: aToken wrapper with static balances and liquidity mini
|
|||
|
||||
const pendingRewards2 = await staticAToken.getClaimableRewards(userSigner._address);
|
||||
|
||||
await waitForTx(await staticAToken.updateRewards());
|
||||
await waitForTx(await staticAToken.collectAndUpdateRewards());
|
||||
|
||||
const pendingRewards3 = await staticAToken.getClaimableRewards(userSigner._address);
|
||||
const claimedRewards3 = await stkAave.balanceOf(userSigner._address);
|
||||
|
||||
await waitForTx(await staticAToken.updateAndClaimRewards(userSigner._address));
|
||||
await waitForTx(await staticAToken.claimRewards(userSigner._address, true));
|
||||
|
||||
const pendingRewards4 = await staticAToken.getClaimableRewards(userSigner._address);
|
||||
const claimedRewards4 = await stkAave.balanceOf(userSigner._address);
|
||||
|
@ -301,6 +360,137 @@ describe('StaticATokenLM: aToken wrapper with static balances and liquidity mini
|
|||
expect(recipientPendingRewards1).to.be.eq(0);
|
||||
expect(recipientPendingRewards2).to.be.eq(0);
|
||||
});
|
||||
|
||||
it('Deposit, Wait, Withdraw, claim?', async () => {
|
||||
const amountToDeposit = utils.parseEther('5');
|
||||
const amountToWithdraw = MAX_UINT_AMOUNT;
|
||||
|
||||
// Just preparation
|
||||
await waitForTx(await weth.deposit({ value: amountToDeposit.mul(2) }));
|
||||
await waitForTx(
|
||||
await weth.approve(staticAToken.address, amountToDeposit.mul(2), defaultTxParams)
|
||||
);
|
||||
|
||||
// Depositing
|
||||
await waitForTx(
|
||||
await staticAToken.deposit(userSigner._address, amountToDeposit, 0, true, defaultTxParams)
|
||||
);
|
||||
|
||||
const pendingRewards1 = await staticAToken.getClaimableRewards(userSigner._address);
|
||||
|
||||
await advanceTimeAndBlock(60 * 60);
|
||||
|
||||
const pendingRewards2 = await staticAToken.getClaimableRewards(userSigner._address);
|
||||
|
||||
// Withdrawing all.
|
||||
await waitForTx(
|
||||
await staticAToken.withdraw(userSigner._address, amountToWithdraw, true, defaultTxParams)
|
||||
);
|
||||
|
||||
// How will my pending look now
|
||||
const pendingRewards3 = await staticAToken.getClaimableRewards(userSigner._address);
|
||||
|
||||
await waitForTx(await staticAToken.claimRewards(userSigner._address, true));
|
||||
|
||||
const pendingRewards4 = await staticAToken.getClaimableRewards(userSigner._address);
|
||||
const userBalance4 = await stkAave.balanceOf(userSigner._address);
|
||||
|
||||
expect(pendingRewards1).to.be.eq(0);
|
||||
expect(pendingRewards2).to.be.gt(pendingRewards1);
|
||||
expect(pendingRewards3).to.be.gt(pendingRewards2);
|
||||
expect(pendingRewards4).to.be.eq(0);
|
||||
expect(userBalance4).to.be.eq(pendingRewards3);
|
||||
});
|
||||
|
||||
it('Deposit, Wait, collectAndUpdate, Withdraw, claim?', async () => {
|
||||
const amountToDeposit = utils.parseEther('5');
|
||||
const amountToWithdraw = MAX_UINT_AMOUNT;
|
||||
|
||||
// Just preparation
|
||||
await waitForTx(await weth.deposit({ value: amountToDeposit.mul(2) }));
|
||||
await waitForTx(
|
||||
await weth.approve(staticAToken.address, amountToDeposit.mul(2), defaultTxParams)
|
||||
);
|
||||
|
||||
// Depositing
|
||||
await waitForTx(
|
||||
await staticAToken.deposit(userSigner._address, amountToDeposit, 0, true, defaultTxParams)
|
||||
);
|
||||
|
||||
const pendingRewards1 = await staticAToken.getClaimableRewards(userSigner._address);
|
||||
|
||||
await advanceTimeAndBlock(60 * 60);
|
||||
await waitForTx(await staticAToken.collectAndUpdateRewards());
|
||||
|
||||
const pendingRewards2 = await staticAToken.getClaimableRewards(userSigner._address);
|
||||
|
||||
// Withdrawing all.
|
||||
await waitForTx(
|
||||
await staticAToken.withdraw(userSigner._address, amountToWithdraw, true, defaultTxParams)
|
||||
);
|
||||
|
||||
const pendingRewards3 = await staticAToken.getClaimableRewards(userSigner._address);
|
||||
|
||||
await waitForTx(await staticAToken.claimRewards(userSigner._address, true));
|
||||
|
||||
const pendingRewards4 = await staticAToken.getClaimableRewards(userSigner._address);
|
||||
const userBalance4 = await stkAave.balanceOf(userSigner._address);
|
||||
|
||||
expect(pendingRewards1).to.be.eq(0);
|
||||
expect(pendingRewards2).to.be.gt(pendingRewards1);
|
||||
expect(pendingRewards3).to.be.gt(pendingRewards2);
|
||||
expect(pendingRewards4).to.be.eq(0);
|
||||
expect(userBalance4).to.be.eq(pendingRewards3);
|
||||
});
|
||||
|
||||
it('Throw away as much as possible: Deposit, collectAndUpdate, wait, Withdraw, claim', async () => {
|
||||
const amountToDeposit = utils.parseEther('5');
|
||||
const amountToWithdraw = MAX_UINT_AMOUNT;
|
||||
|
||||
// Just preparation
|
||||
await waitForTx(await weth.deposit({ value: amountToDeposit.mul(2) }));
|
||||
await waitForTx(
|
||||
await weth.approve(staticAToken.address, amountToDeposit.mul(2), defaultTxParams)
|
||||
);
|
||||
|
||||
// Depositing
|
||||
await waitForTx(
|
||||
await staticAToken.deposit(userSigner._address, amountToDeposit, 0, true, defaultTxParams)
|
||||
);
|
||||
|
||||
const pendingRewards1 = await staticAToken.getClaimableRewards(userSigner._address);
|
||||
|
||||
await waitForTx(await staticAToken.collectAndUpdateRewards());
|
||||
await advanceTimeAndBlock(60 * 60);
|
||||
|
||||
const pendingRewards2 = await staticAToken.getClaimableRewards(userSigner._address);
|
||||
|
||||
// Withdrawing all.
|
||||
await waitForTx(
|
||||
await staticAToken.withdraw(userSigner._address, amountToWithdraw, true, defaultTxParams)
|
||||
);
|
||||
|
||||
// How will my pending look now
|
||||
const pendingRewards3 = await staticAToken.getClaimableRewards(userSigner._address);
|
||||
const unclaimedRewards3 = await staticAToken.getUnclaimedRewards(userSigner._address);
|
||||
|
||||
await waitForTx(await staticAToken.claimRewards(userSigner._address, false));
|
||||
|
||||
const pendingRewards4 = await staticAToken.getClaimableRewards(userSigner._address);
|
||||
const userBalance4 = await stkAave.balanceOf(userSigner._address);
|
||||
const totClaimable4 = await staticAToken.getTotalClaimableRewards();
|
||||
const unclaimedRewards4 = await staticAToken.getUnclaimedRewards(userSigner._address);
|
||||
|
||||
expect(pendingRewards1).to.be.eq(0);
|
||||
expect(pendingRewards2).to.be.gt(0);
|
||||
expect(pendingRewards3).to.be.gt(pendingRewards2);
|
||||
expect(pendingRewards4).to.be.eq(0);
|
||||
expect(userBalance4).to.be.gt(0);
|
||||
expect(userBalance4).to.be.lt(unclaimedRewards3);
|
||||
expect(totClaimable4).to.be.gt(0);
|
||||
expect(totClaimable4).to.be.gt(userBalance4);
|
||||
expect(unclaimedRewards4).to.be.eq(0);
|
||||
});
|
||||
});
|
||||
|
||||
it('Multiple users deposit WETH on stataWETH, wait 1 hour, update rewards, one user transfer, then claim and update rewards.', async () => {
|
||||
|
@ -340,9 +530,9 @@ describe('StaticATokenLM: aToken wrapper with static balances and liquidity mini
|
|||
|
||||
// Advance time to accrue significant rewards.
|
||||
await advanceTimeAndBlock(60 * 60);
|
||||
await staticAToken.updateRewards();
|
||||
await staticAToken.collectAndUpdateRewards();
|
||||
|
||||
let staticATokenStkAaveBalInitial = await stkAave.balanceOf(staticAToken.address);
|
||||
let staticATokenTotClaimableInitial = await staticAToken.getTotalClaimableRewards();
|
||||
let usersDataInitial = await getUserData(users, _debugUserData, { staticAToken, stkAave });
|
||||
|
||||
await waitForTx(
|
||||
|
@ -357,18 +547,19 @@ describe('StaticATokenLM: aToken wrapper with static balances and liquidity mini
|
|||
await advanceTimeAndBlock(60 * 60);
|
||||
|
||||
for (let i = 0; i < 5; i++) {
|
||||
await waitForTx(await staticAToken.claimRewards(await users[i].getAddress()));
|
||||
// This will claim the first half of the collected tokens (those collected at `collectAndUpdateRewards`)
|
||||
await waitForTx(await staticAToken.claimRewards(await users[i].getAddress(), false));
|
||||
}
|
||||
|
||||
let staticATokenStkAaveBalAfterTransferAndClaim = await stkAave.balanceOf(staticAToken.address);
|
||||
let staticATokenTotClaimableAfterTransferAndClaim = await staticAToken.getTotalClaimableRewards();
|
||||
let usersDataAfterTransferAndClaim = await getUserData(users, _debugUserData, {
|
||||
staticAToken,
|
||||
stkAave,
|
||||
});
|
||||
|
||||
await waitForTx(await staticAToken.updateRewards());
|
||||
await waitForTx(await staticAToken.collectAndUpdateRewards());
|
||||
|
||||
let staticATokenStkAaveBalFinal = await stkAave.balanceOf(staticAToken.address);
|
||||
let staticATokenTotClaimableFinal = await staticAToken.getTotalClaimableRewards();
|
||||
let usersDataFinal = await getUserData(users, _debugUserData, { staticAToken, stkAave });
|
||||
|
||||
// Time for checks
|
||||
|
@ -386,6 +577,16 @@ describe('StaticATokenLM: aToken wrapper with static balances and liquidity mini
|
|||
usersDataAfterTransferAndClaim[i].staticBalance
|
||||
);
|
||||
expect(usersDataInitial[i].staticBalance).to.be.eq(usersDataFinal[i].staticBalance);
|
||||
expect(usersDataInitial[i].pendingRewards.add(usersDataInitial[i].stkAaveBalance)).to.be.lt(
|
||||
usersDataAfterTransferAndClaim[i].pendingRewards.add(
|
||||
usersDataAfterTransferAndClaim[i].stkAaveBalance
|
||||
)
|
||||
);
|
||||
expect(
|
||||
usersDataAfterTransferAndClaim[i].pendingRewards.add(
|
||||
usersDataAfterTransferAndClaim[i].stkAaveBalance
|
||||
)
|
||||
).to.be.lt(usersDataFinal[i].pendingRewards.add(usersDataFinal[i].stkAaveBalance));
|
||||
}
|
||||
|
||||
pendingRewardsSumInitial = pendingRewardsSumInitial.add(usersDataInitial[i].pendingRewards);
|
||||
|
@ -419,14 +620,16 @@ describe('StaticATokenLM: aToken wrapper with static balances and liquidity mini
|
|||
);
|
||||
|
||||
// Expect there to be excess stkAave in the contract. Expect it to be dust. This ensure that everyone can claim full amount of rewards.
|
||||
expect(pendingRewardsSumInitial).to.be.lte(staticATokenStkAaveBalInitial);
|
||||
expect(staticATokenStkAaveBalInitial.sub(pendingRewardsSumInitial)).to.be.lte(DUST);
|
||||
expect(pendingRewardsSumInitial).to.be.lte(staticATokenTotClaimableInitial);
|
||||
expect(staticATokenTotClaimableInitial.sub(pendingRewardsSumInitial)).to.be.lte(DUST);
|
||||
|
||||
expect(pendingRewardsSumAfter).to.be.lte(staticATokenStkAaveBalAfterTransferAndClaim);
|
||||
expect(staticATokenStkAaveBalAfterTransferAndClaim.sub(pendingRewardsSumAfter)).to.be.lte(DUST);
|
||||
expect(pendingRewardsSumAfter).to.be.lte(staticATokenTotClaimableAfterTransferAndClaim);
|
||||
expect(staticATokenTotClaimableAfterTransferAndClaim.sub(pendingRewardsSumAfter)).to.be.lte(
|
||||
DUST
|
||||
);
|
||||
|
||||
expect(pendingRewardsSumFinal).to.be.lte(staticATokenStkAaveBalFinal);
|
||||
expect(staticATokenStkAaveBalFinal.sub(pendingRewardsSumFinal)).to.be.lte(DUST);
|
||||
expect(pendingRewardsSumFinal).to.be.lte(staticATokenTotClaimableFinal);
|
||||
expect(staticATokenTotClaimableFinal.sub(pendingRewardsSumFinal)).to.be.lte(DUST);
|
||||
});
|
||||
|
||||
it('Multiple users deposit WETH on stataWETH, wait 1 hour, one user transfer, then claim and update rewards.', async () => {
|
||||
|
@ -468,7 +671,7 @@ describe('StaticATokenLM: aToken wrapper with static balances and liquidity mini
|
|||
// Advance time to accrue significant rewards.
|
||||
await advanceTimeAndBlock(60 * 60);
|
||||
|
||||
let staticATokenStkAaveBalInitial = await stkAave.balanceOf(staticAToken.address);
|
||||
let staticATokenTotClaimableInitial = await staticAToken.getTotalClaimableRewards();
|
||||
let usersDataInitial = await getUserData(users, _debugUserData, { staticAToken, stkAave });
|
||||
|
||||
// User 0 transfer full balance of staticATokens to user 1. This will also transfer the rewards since last update as well.
|
||||
|
@ -484,18 +687,19 @@ describe('StaticATokenLM: aToken wrapper with static balances and liquidity mini
|
|||
await advanceTimeAndBlock(60 * 60);
|
||||
|
||||
for (let i = 0; i < 5; i++) {
|
||||
await waitForTx(await staticAToken.claimRewards(await users[i].getAddress()));
|
||||
// This will not do anything, hence there is no rewards in the current contract.
|
||||
await waitForTx(await staticAToken.claimRewards(await users[i].getAddress(), false));
|
||||
}
|
||||
|
||||
let staticATokenStkAaveBalAfterTransfer = await stkAave.balanceOf(staticAToken.address);
|
||||
let staticATokenTotClaimableAfterTransfer = await staticAToken.getTotalClaimableRewards();
|
||||
let usersDataAfterTransfer = await getUserData(users, _debugUserData, {
|
||||
staticAToken,
|
||||
stkAave,
|
||||
});
|
||||
|
||||
await waitForTx(await staticAToken.updateRewards());
|
||||
await waitForTx(await staticAToken.collectAndUpdateRewards());
|
||||
|
||||
let staticATokenStkAaveBalFinal = await stkAave.balanceOf(staticAToken.address);
|
||||
let staticATokenTotClaimableFinal = await staticAToken.getTotalClaimableRewards();
|
||||
let usersDataFinal = await getUserData(users, _debugUserData, { staticAToken, stkAave });
|
||||
|
||||
// Time for checks
|
||||
|
@ -504,9 +708,8 @@ describe('StaticATokenLM: aToken wrapper with static balances and liquidity mini
|
|||
let pendingRewardsSumFinal = BigNumber.from(0);
|
||||
for (let i = 0; i < 5; i++) {
|
||||
expect(usersDataInitial[i].stkAaveBalance).to.be.eq(0);
|
||||
// Everyone else than i == 1, should have no change in pending rewards.
|
||||
// i == 1, will get additional rewards that have accrue
|
||||
expect(usersDataAfterTransfer[i].stkAaveBalance).to.be.eq(usersDataInitial[i].pendingRewards);
|
||||
expect(usersDataAfterTransfer[i].stkAaveBalance).to.be.eq(0);
|
||||
expect(usersDataFinal[i].stkAaveBalance).to.be.eq(0);
|
||||
if (i > 1) {
|
||||
// Expect initial static balance == after transfer == after claiming
|
||||
expect(usersDataInitial[i].staticBalance).to.be.eq(usersDataAfterTransfer[i].staticBalance);
|
||||
|
@ -518,40 +721,45 @@ describe('StaticATokenLM: aToken wrapper with static balances and liquidity mini
|
|||
pendingRewardsSumFinal = pendingRewardsSumFinal.add(usersDataFinal[i].pendingRewards);
|
||||
}
|
||||
|
||||
// Expect user 0 to accrue zero fees after the transfer
|
||||
expect(usersDataAfterTransfer[0].pendingRewards).to.be.eq(0);
|
||||
expect(await staticAToken.getTotalClaimableRewards()).to.be.eq(
|
||||
await stkAave.balanceOf(staticAToken.address)
|
||||
);
|
||||
|
||||
// Another dude gets our unclaimed rewards
|
||||
expect(usersDataInitial[0].pendingRewards).to.be.gt(usersDataAfterTransfer[0].pendingRewards);
|
||||
expect(usersDataAfterTransfer[0].pendingRewards).to.be.eq(usersDataFinal[0].pendingRewards);
|
||||
|
||||
expect(usersDataAfterTransfer[0].staticBalance).to.be.eq(0);
|
||||
expect(usersDataFinal[0].pendingRewards).to.be.eq(0);
|
||||
expect(usersDataFinal[0].staticBalance).to.be.eq(0);
|
||||
|
||||
// Expect user 1 to have received funds
|
||||
expect(usersDataAfterTransfer[1].staticBalance).to.be.eq(
|
||||
usersDataInitial[1].staticBalance.add(usersDataInitial[0].staticBalance)
|
||||
);
|
||||
|
||||
/*
|
||||
* Expect user 1 to have pending more than twice the rewards as the last user.
|
||||
* Expect user 1 to have pending almost twice the rewards as the last user.
|
||||
* Note that he should have accrued this, even though he did not have 2x bal for the full time,
|
||||
* as he also received the "uncollected" rewards from user1 at the transfer.
|
||||
* Lack of precision due to small initial diff.
|
||||
*/
|
||||
expect(usersDataFinal[1].pendingRewards).to.be.gt(usersDataFinal[2].pendingRewards.mul(2));
|
||||
// Expect his total fees to be almost twice as large. Because of the small initial diff
|
||||
expect(usersDataFinal[1].pendingRewards.add(usersDataFinal[1].stkAaveBalance)).to.be.gt(
|
||||
usersDataFinal[2].pendingRewards.add(usersDataFinal[2].stkAaveBalance).mul(195).div(100)
|
||||
expect(usersDataFinal[1].pendingRewards).to.be.gt(
|
||||
usersDataFinal[2].pendingRewards.mul(195).div(100)
|
||||
);
|
||||
expect(usersDataFinal[1].pendingRewards.add(usersDataFinal[1].stkAaveBalance)).to.be.lt(
|
||||
usersDataFinal[2].pendingRewards.add(usersDataFinal[2].stkAaveBalance).mul(205).div(100)
|
||||
expect(usersDataFinal[1].pendingRewards).to.be.lt(
|
||||
usersDataFinal[2].pendingRewards.mul(205).div(100)
|
||||
);
|
||||
|
||||
// Expect there to be excess stkAave in the contract.
|
||||
// Expect it to be dust. This ensure that everyone can claim full amount of rewards.
|
||||
expect(pendingRewardsSumInitial).to.be.lte(staticATokenStkAaveBalInitial);
|
||||
expect(staticATokenStkAaveBalInitial.sub(pendingRewardsSumInitial)).to.be.lte(DUST);
|
||||
expect(pendingRewardsSumInitial).to.be.lte(staticATokenTotClaimableInitial);
|
||||
expect(staticATokenTotClaimableInitial.sub(pendingRewardsSumInitial)).to.be.lte(DUST);
|
||||
|
||||
expect(pendingRewardsSumAfter).to.be.lte(staticATokenStkAaveBalAfterTransfer);
|
||||
expect(staticATokenStkAaveBalAfterTransfer.sub(pendingRewardsSumAfter)).to.be.lte(DUST);
|
||||
expect(pendingRewardsSumAfter).to.be.lte(staticATokenTotClaimableAfterTransfer);
|
||||
expect(staticATokenTotClaimableAfterTransfer.sub(pendingRewardsSumAfter)).to.be.lte(DUST);
|
||||
|
||||
expect(pendingRewardsSumFinal).to.be.lte(staticATokenStkAaveBalFinal);
|
||||
expect(staticATokenStkAaveBalFinal.sub(pendingRewardsSumFinal)).to.be.lte(DUST); // How small should we say dust is?
|
||||
expect(pendingRewardsSumFinal).to.be.lte(staticATokenTotClaimableFinal);
|
||||
expect(staticATokenTotClaimableFinal.sub(pendingRewardsSumFinal)).to.be.lte(DUST); // How small should we say dust is?
|
||||
});
|
||||
|
||||
it('Mass deposit, then mass claim', async () => {
|
||||
|
@ -580,17 +788,22 @@ describe('StaticATokenLM: aToken wrapper with static balances and liquidity mini
|
|||
|
||||
// Advance time to accrue significant rewards.
|
||||
await advanceTimeAndBlock(60 * 60);
|
||||
await waitForTx(await staticAToken.updateRewards());
|
||||
await waitForTx(await staticAToken.collectAndUpdateRewards());
|
||||
|
||||
let pendingRewards: BigNumber[] = [];
|
||||
|
||||
for (let i = 0; i < users.length; i++) {
|
||||
const pendingReward = await staticAToken.getClaimableRewards(await users[i].getAddress());
|
||||
await waitForTx(await staticAToken.claimRewards(await users[i].getAddress()));
|
||||
expect(await stkAave.balanceOf(await users[i].getAddress())).to.be.eq(pendingReward);
|
||||
pendingRewards.push(pendingReward);
|
||||
}
|
||||
for (let i = 0; i < users.length; i++) {
|
||||
await waitForTx(await staticAToken.claimRewards(await users[i].getAddress(), false));
|
||||
expect(await stkAave.balanceOf(await users[i].getAddress())).to.be.eq(pendingRewards[i]);
|
||||
}
|
||||
expect(await stkAave.balanceOf(staticAToken.address)).to.be.lt(DUST);
|
||||
});
|
||||
|
||||
it('Multiple deposits, withdraws and claims', async () => {
|
||||
it('mass deposits, mass withdraws and mass claims', async () => {
|
||||
const amountToDeposit = utils.parseEther('1.135359735917531199'); // 18 decimals should be the worst here //1.135359735917531199
|
||||
const users = await DRE.ethers.getSigners();
|
||||
|
||||
|
@ -622,9 +835,8 @@ describe('StaticATokenLM: aToken wrapper with static balances and liquidity mini
|
|||
);
|
||||
|
||||
const pendingReward = await staticAToken.getClaimableRewards(await users[i].getAddress());
|
||||
await waitForTx(await staticAToken.updateAndClaimRewards(await users[i].getAddress()));
|
||||
await waitForTx(await staticAToken.claimRewards(await users[i].getAddress(), true));
|
||||
expect(await stkAave.balanceOf(await users[i].getAddress())).to.be.eq(pendingReward);
|
||||
}
|
||||
expect(await stkAave.balanceOf(staticAToken.address)).to.be.lt(DUST);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -67,6 +67,7 @@ type tBalancesInvolved = {
|
|||
staticATokenStkAaveBalance: BigNumber;
|
||||
staticATokenUnderlyingBalance: BigNumber;
|
||||
staticATokenScaledBalanceAToken: BigNumber;
|
||||
staticATokenTotalClaimableRewards: BigNumber;
|
||||
userStkAaveBalance: BigNumber;
|
||||
userATokenBalance: BigNumber;
|
||||
userScaledBalanceAToken: BigNumber;
|
||||
|
@ -108,6 +109,7 @@ const getContext = async ({
|
|||
staticATokenStkAaveBalance: await stkAave.balanceOf(staticAToken.address),
|
||||
staticATokenUnderlyingBalance: await underlying.balanceOf(staticAToken.address),
|
||||
staticATokenScaledBalanceAToken: await aToken.scaledBalanceOf(staticAToken.address),
|
||||
staticATokenTotalClaimableRewards: await staticAToken.getTotalClaimableRewards(),
|
||||
userStaticATokenBalance: await staticAToken.balanceOf(user),
|
||||
userStkAaveBalance: await stkAave.balanceOf(user),
|
||||
userATokenBalance: await aToken.balanceOf(user),
|
||||
|
@ -214,9 +216,13 @@ describe('StaticATokenLM: aToken wrapper with static balances and liquidity mini
|
|||
const ctxtAfterWithdrawal = await getContext(ctxtParams);
|
||||
|
||||
// Claiming the rewards
|
||||
await waitForTx(await staticAToken.claimRewards(userSigner._address));
|
||||
await waitForTx(await staticAToken.claimRewards(userSigner._address, false));
|
||||
|
||||
const ctxtAfterClaim = await getContext(ctxtParams);
|
||||
const ctxtAfterClaimNoForce = await getContext(ctxtParams);
|
||||
|
||||
await waitForTx(await staticAToken.claimRewards(userSigner._address, true));
|
||||
|
||||
const ctxtAfterClaimForce = await getContext(ctxtParams);
|
||||
|
||||
// Check that scaledAToken balance is equal to the static aToken supply at every stage.
|
||||
expect(ctxtInitial.staticATokenScaledBalanceAToken).to.be.eq(ctxtInitial.staticATokenSupply);
|
||||
|
@ -226,8 +232,8 @@ describe('StaticATokenLM: aToken wrapper with static balances and liquidity mini
|
|||
expect(ctxtAfterWithdrawal.staticATokenScaledBalanceAToken).to.be.eq(
|
||||
ctxtAfterWithdrawal.staticATokenSupply
|
||||
);
|
||||
expect(ctxtAfterClaim.staticATokenScaledBalanceAToken).to.be.eq(
|
||||
ctxtAfterClaim.staticATokenSupply
|
||||
expect(ctxtAfterClaimNoForce.staticATokenScaledBalanceAToken).to.be.eq(
|
||||
ctxtAfterClaimNoForce.staticATokenSupply
|
||||
);
|
||||
|
||||
expect(ctxtAfterDeposit.staticATokenATokenBalance).to.be.eq(
|
||||
|
@ -253,18 +259,29 @@ describe('StaticATokenLM: aToken wrapper with static balances and liquidity mini
|
|||
expect(ctxtAfterWithdrawal.staticATokenATokenBalance).to.be.eq(0);
|
||||
expect(ctxtAfterWithdrawal.staticATokenSupply).to.be.eq(0);
|
||||
expect(ctxtAfterWithdrawal.staticATokenUnderlyingBalance).to.be.eq(0);
|
||||
expect(ctxtAfterWithdrawal.staticATokenStkAaveBalance).to.be.eq(0);
|
||||
|
||||
// Check with possible rounding error.
|
||||
expect(ctxtAfterWithdrawal.staticATokenStkAaveBalance).to.be.gte(
|
||||
// Check with possible rounding error. Ahhh, it is because we have not claimed the shit after withdraw
|
||||
expect(ctxtAfterWithdrawal.staticATokenTotalClaimableRewards).to.be.gte(
|
||||
ctxtAfterWithdrawal.userPendingRewards
|
||||
);
|
||||
expect(ctxtAfterWithdrawal.staticATokenStkAaveBalance).to.be.lte(
|
||||
|
||||
expect(ctxtAfterWithdrawal.staticATokenTotalClaimableRewards).to.be.lte(
|
||||
ctxtAfterWithdrawal.userPendingRewards.add(1)
|
||||
);
|
||||
expect(ctxtAfterWithdrawal.userStkAaveBalance).to.be.eq(0);
|
||||
|
||||
expect(ctxtAfterClaim.userStkAaveBalance).to.be.eq(ctxtAfterWithdrawal.userPendingRewards);
|
||||
expect(ctxtAfterClaim.staticATokenStkAaveBalance).to.be.lte(1);
|
||||
expect(ctxtAfterClaimNoForce.userStkAaveBalance).to.be.eq(0);
|
||||
expect(ctxtAfterClaimNoForce.staticATokenStkAaveBalance).to.be.eq(0);
|
||||
|
||||
expect(ctxtAfterClaimForce.userStkAaveBalance).to.be.eq(
|
||||
ctxtAfterClaimNoForce.userPendingRewards
|
||||
);
|
||||
expect(ctxtAfterClaimForce.staticATokenStkAaveBalance).to.be.eq(
|
||||
ctxtAfterClaimNoForce.staticATokenTotalClaimableRewards.sub(
|
||||
ctxtAfterClaimNoForce.userPendingRewards
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
it('Deposit WETH on stataWETH and then withdraw some balance in underlying', async () => {
|
||||
|
@ -293,9 +310,15 @@ describe('StaticATokenLM: aToken wrapper with static balances and liquidity mini
|
|||
const ctxtAfterWithdrawal = await getContext(ctxtParams);
|
||||
|
||||
// Claim
|
||||
await waitForTx(await staticAToken.claimRewards(userSigner._address));
|
||||
await waitForTx(await staticAToken.claimRewards(userSigner._address, false));
|
||||
const ctxtAfterClaim = await getContext(ctxtParams);
|
||||
|
||||
await waitForTx(await staticAToken.collectAndUpdateRewards());
|
||||
const ctxtAfterUpdate = await getContext(ctxtParams);
|
||||
|
||||
await waitForTx(await staticAToken.claimRewards(userSigner._address, false));
|
||||
const ctxtAfterClaim2 = await getContext(ctxtParams);
|
||||
|
||||
expect(ctxtInitial.userStaticATokenBalance).to.be.eq(0);
|
||||
expect(ctxtInitial.staticATokenSupply).to.be.eq(0);
|
||||
expect(ctxtInitial.staticATokenUnderlyingBalance).to.be.eq(0);
|
||||
|
@ -317,7 +340,27 @@ describe('StaticATokenLM: aToken wrapper with static balances and liquidity mini
|
|||
ctxtAfterDeposit.userStaticATokenBalance.sub(amountToWithdraw)
|
||||
);
|
||||
|
||||
expect(ctxtAfterClaim.userStkAaveBalance).to.be.eq(ctxtAfterWithdrawal.userPendingRewards);
|
||||
expect(ctxtAfterUpdate.userStkAaveBalance).to.be.eq(0);
|
||||
expect(ctxtAfterClaim2.userStkAaveBalance).to.be.eq(ctxtAfterUpdate.userPendingRewards);
|
||||
expect(ctxtAfterClaim2.userPendingRewards).to.be.gt(0);
|
||||
|
||||
// Check that rewards are always covered
|
||||
expect(ctxtInitial.staticATokenTotalClaimableRewards).to.be.gte(ctxtInitial.userPendingRewards);
|
||||
expect(ctxtAfterDeposit.staticATokenTotalClaimableRewards).to.be.gte(
|
||||
ctxtAfterDeposit.userPendingRewards
|
||||
);
|
||||
expect(ctxtAfterWithdrawal.staticATokenTotalClaimableRewards).to.be.gte(
|
||||
ctxtAfterWithdrawal.userPendingRewards
|
||||
);
|
||||
expect(ctxtAfterClaim.staticATokenTotalClaimableRewards).to.be.gte(
|
||||
ctxtAfterClaim.userPendingRewards
|
||||
);
|
||||
expect(ctxtAfterUpdate.staticATokenTotalClaimableRewards).to.be.gte(
|
||||
ctxtAfterUpdate.userPendingRewards
|
||||
);
|
||||
expect(ctxtAfterClaim2.staticATokenTotalClaimableRewards).to.be.gte(
|
||||
ctxtAfterClaim2.userPendingRewards
|
||||
);
|
||||
});
|
||||
|
||||
it('Deposit WETH on stataWETH and then withdraw all the balance in aToken', async () => {
|
||||
|
@ -719,10 +762,6 @@ describe('StaticATokenLM: aToken wrapper with static balances and liquidity mini
|
|||
|
||||
const ctxtAfterWithdrawal = await getContext(ctxtParams);
|
||||
|
||||
// Claim
|
||||
await waitForTx(await staticAToken.claimRewards(userSigner._address));
|
||||
const ctxtAfterClaim = await getContext(ctxtParams);
|
||||
|
||||
expect(ctxtBeforeWithdrawal.userATokenBalance).to.be.eq(0);
|
||||
expect(ctxtBeforeWithdrawal.staticATokenATokenBalance).to.be.eq(amountToDeposit);
|
||||
expect(ctxtAfterWithdrawal.userATokenBalance).to.be.eq(amountToWithdraw);
|
||||
|
@ -736,7 +775,6 @@ describe('StaticATokenLM: aToken wrapper with static balances and liquidity mini
|
|||
);
|
||||
|
||||
expect(ctxtAfterWithdrawal.userStkAaveBalance).to.be.eq(0);
|
||||
expect(ctxtAfterClaim.userStkAaveBalance).to.be.eq(ctxtAfterWithdrawal.userPendingRewards);
|
||||
});
|
||||
|
||||
it('Withdraw using metaWithdraw()', async () => {
|
||||
|
@ -985,7 +1023,7 @@ describe('StaticATokenLM: aToken wrapper with static balances and liquidity mini
|
|||
const ctxtAfterWithdrawal = await getContext(ctxtParams);
|
||||
|
||||
// Claim
|
||||
await waitForTx(await staticAToken.claimRewards(user2Signer._address));
|
||||
await waitForTx(await staticAToken.claimRewards(user2Signer._address, true));
|
||||
const ctxtAfterClaim = await getContext(ctxtParams);
|
||||
|
||||
// Checks
|
||||
|
@ -1000,17 +1038,25 @@ describe('StaticATokenLM: aToken wrapper with static balances and liquidity mini
|
|||
);
|
||||
expect(ctxtAfterTransfer.userStaticATokenBalance).to.be.eq(0);
|
||||
expect(ctxtAfterTransfer.userPendingRewards).to.be.eq(0);
|
||||
expect(ctxtAfterTransfer.user2PendingRewards).to.be.eq(0);
|
||||
expect(ctxtAfterTransfer.user2PendingRewards).to.be.gt(0);
|
||||
expect(ctxtAfterWithdrawal.staticATokenSupply).to.be.eq(0);
|
||||
expect(ctxtAfterWithdrawal.staticATokenATokenBalance).to.be.eq(0);
|
||||
expect(ctxtAfterWithdrawal.userPendingRewards).to.be.eq(0);
|
||||
expect(ctxtAfterWithdrawal.user2PendingRewards).to.be.lte(
|
||||
ctxtAfterWithdrawal.staticATokenStkAaveBalance
|
||||
expect(ctxtAfterWithdrawal.staticATokenTotalClaimableRewards).to.be.gte(
|
||||
ctxtAfterWithdrawal.user2PendingRewards
|
||||
);
|
||||
expect(ctxtAfterClaim.user2StkAaveBalance).to.be.eq(ctxtAfterWithdrawal.user2PendingRewards);
|
||||
console.log('All the way down here');
|
||||
|
||||
console.log(`${formatEther(ctxtAfterClaim.staticATokenTotalClaimableRewards)}`);
|
||||
console.log(`${formatEther(ctxtAfterClaim.user2StkAaveBalance)}`);
|
||||
console.log(`${formatEther(ctxtAfterClaim.staticATokenStkAaveBalance)}`);
|
||||
|
||||
expect(ctxtAfterClaim.userStkAaveBalance).to.be.eq(0);
|
||||
expect(ctxtAfterClaim.user2StkAaveBalance).to.be.eq(ctxtAfterWithdrawal.user2PendingRewards);
|
||||
expect(ctxtAfterClaim.staticATokenStkAaveBalance).to.be.eq(
|
||||
ctxtAfterWithdrawal.staticATokenStkAaveBalance.sub(ctxtAfterWithdrawal.user2PendingRewards)
|
||||
ctxtAfterWithdrawal.staticATokenTotalClaimableRewards.sub(
|
||||
ctxtAfterWithdrawal.user2PendingRewards
|
||||
)
|
||||
);
|
||||
// Expect dust to be left in the contract
|
||||
expect(ctxtAfterClaim.staticATokenStkAaveBalance).to.be.lt(5);
|
||||
|
|
Loading…
Reference in New Issue
Block a user