mirror of
https://github.com/Instadapp/aave-protocol-v2.git
synced 2024-07-29 21:47:30 +00:00
Added pausable to Pool actions and aTokens at transfer, triggered by LendingPoolConfigurator. Added basic test to aToken transfer.
This commit is contained in:
parent
4b8962d38f
commit
bbc11eb092
|
@ -129,6 +129,15 @@ interface ILendingPool {
|
||||||
address liquidator,
|
address liquidator,
|
||||||
bool receiveAToken
|
bool receiveAToken
|
||||||
);
|
);
|
||||||
|
/**
|
||||||
|
* @dev Emitted when the pause is triggered by `account`.
|
||||||
|
*/
|
||||||
|
event Paused(address account);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Emitted when the pause is lifted by `account`.
|
||||||
|
*/
|
||||||
|
event Unpaused(address account);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev deposits The underlying asset into the reserve. A corresponding amount of the overlying asset (aTokens)
|
* @dev deposits The underlying asset into the reserve. A corresponding amount of the overlying asset (aTokens)
|
||||||
|
@ -374,4 +383,10 @@ interface ILendingPool {
|
||||||
) external view returns (bool);
|
) external view returns (bool);
|
||||||
|
|
||||||
function getReserves() external view returns (address[] memory);
|
function getReserves() external view returns (address[] memory);
|
||||||
|
|
||||||
|
function pause() external;
|
||||||
|
|
||||||
|
function unpause() external;
|
||||||
|
|
||||||
|
function isPaused() external view returns (bool);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ pragma experimental ABIEncoderV2;
|
||||||
|
|
||||||
import {SafeMath} from '@openzeppelin/contracts/math/SafeMath.sol';
|
import {SafeMath} from '@openzeppelin/contracts/math/SafeMath.sol';
|
||||||
import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol';
|
import {IERC20} from '@openzeppelin/contracts/token/ERC20/IERC20.sol';
|
||||||
|
import {Pausable} from '@openzeppelin/contracts/utils/Pausable.sol';
|
||||||
import {
|
import {
|
||||||
VersionedInitializable
|
VersionedInitializable
|
||||||
} from '../libraries/openzeppelin-upgradeability/VersionedInitializable.sol';
|
} from '../libraries/openzeppelin-upgradeability/VersionedInitializable.sol';
|
||||||
|
@ -31,7 +32,7 @@ import {ILendingPool} from '../interfaces/ILendingPool.sol';
|
||||||
* @author Aave
|
* @author Aave
|
||||||
**/
|
**/
|
||||||
|
|
||||||
contract LendingPool is VersionedInitializable, ILendingPool {
|
contract LendingPool is VersionedInitializable, Pausable, ILendingPool {
|
||||||
using SafeMath for uint256;
|
using SafeMath for uint256;
|
||||||
using WadRayMath for uint256;
|
using WadRayMath for uint256;
|
||||||
using ReserveLogic for ReserveLogic.ReserveData;
|
using ReserveLogic for ReserveLogic.ReserveData;
|
||||||
|
@ -93,7 +94,7 @@ contract LendingPool is VersionedInitializable, ILendingPool {
|
||||||
uint256 amount,
|
uint256 amount,
|
||||||
address onBehalfOf,
|
address onBehalfOf,
|
||||||
uint16 referralCode
|
uint16 referralCode
|
||||||
) external override {
|
) external override whenNotPaused {
|
||||||
ReserveLogic.ReserveData storage reserve = _reserves[asset];
|
ReserveLogic.ReserveData storage reserve = _reserves[asset];
|
||||||
|
|
||||||
ValidationLogic.validateDeposit(reserve, amount);
|
ValidationLogic.validateDeposit(reserve, amount);
|
||||||
|
@ -121,7 +122,7 @@ contract LendingPool is VersionedInitializable, ILendingPool {
|
||||||
* @param asset the address of the reserve
|
* @param asset the address of the reserve
|
||||||
* @param amount the underlying amount to be redeemed
|
* @param amount the underlying amount to be redeemed
|
||||||
**/
|
**/
|
||||||
function withdraw(address asset, uint256 amount) external override {
|
function withdraw(address asset, uint256 amount) external override whenNotPaused {
|
||||||
ReserveLogic.ReserveData storage reserve = _reserves[asset];
|
ReserveLogic.ReserveData storage reserve = _reserves[asset];
|
||||||
|
|
||||||
address aToken = reserve.aTokenAddress;
|
address aToken = reserve.aTokenAddress;
|
||||||
|
@ -172,7 +173,7 @@ contract LendingPool is VersionedInitializable, ILendingPool {
|
||||||
uint256 amount,
|
uint256 amount,
|
||||||
uint256 interestRateMode,
|
uint256 interestRateMode,
|
||||||
uint16 referralCode
|
uint16 referralCode
|
||||||
) external override {
|
) external override whenNotPaused {
|
||||||
_executeBorrow(
|
_executeBorrow(
|
||||||
ExecuteBorrowParams(
|
ExecuteBorrowParams(
|
||||||
asset,
|
asset,
|
||||||
|
@ -199,7 +200,7 @@ contract LendingPool is VersionedInitializable, ILendingPool {
|
||||||
uint256 amount,
|
uint256 amount,
|
||||||
uint256 rateMode,
|
uint256 rateMode,
|
||||||
address onBehalfOf
|
address onBehalfOf
|
||||||
) external override {
|
) external override whenNotPaused {
|
||||||
_executeRepay(asset, msg.sender, amount, rateMode, onBehalfOf);
|
_executeRepay(asset, msg.sender, amount, rateMode, onBehalfOf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -260,7 +261,7 @@ contract LendingPool is VersionedInitializable, ILendingPool {
|
||||||
* @param asset the address of the reserve on which the user borrowed
|
* @param asset the address of the reserve on which the user borrowed
|
||||||
* @param rateMode the rate mode that the user wants to swap
|
* @param rateMode the rate mode that the user wants to swap
|
||||||
**/
|
**/
|
||||||
function swapBorrowRateMode(address asset, uint256 rateMode) external override {
|
function swapBorrowRateMode(address asset, uint256 rateMode) external override whenNotPaused {
|
||||||
ReserveLogic.ReserveData storage reserve = _reserves[asset];
|
ReserveLogic.ReserveData storage reserve = _reserves[asset];
|
||||||
|
|
||||||
(uint256 stableDebt, uint256 variableDebt) = Helpers.getUserCurrentDebt(msg.sender, reserve);
|
(uint256 stableDebt, uint256 variableDebt) = Helpers.getUserCurrentDebt(msg.sender, reserve);
|
||||||
|
@ -303,7 +304,7 @@ contract LendingPool is VersionedInitializable, ILendingPool {
|
||||||
* @param asset the address of the reserve
|
* @param asset the address of the reserve
|
||||||
* @param user the address of the user to be rebalanced
|
* @param user the address of the user to be rebalanced
|
||||||
**/
|
**/
|
||||||
function rebalanceStableBorrowRate(address asset, address user) external override {
|
function rebalanceStableBorrowRate(address asset, address user) external override whenNotPaused {
|
||||||
ReserveLogic.ReserveData storage reserve = _reserves[asset];
|
ReserveLogic.ReserveData storage reserve = _reserves[asset];
|
||||||
|
|
||||||
IStableDebtToken stableDebtToken = IStableDebtToken(reserve.stableDebtTokenAddress);
|
IStableDebtToken stableDebtToken = IStableDebtToken(reserve.stableDebtTokenAddress);
|
||||||
|
@ -348,7 +349,11 @@ contract LendingPool is VersionedInitializable, ILendingPool {
|
||||||
* @param asset the address of the reserve
|
* @param asset the address of the reserve
|
||||||
* @param useAsCollateral true if the user wants to user the deposit as collateral, false otherwise.
|
* @param useAsCollateral true if the user wants to user the deposit as collateral, false otherwise.
|
||||||
**/
|
**/
|
||||||
function setUserUseReserveAsCollateral(address asset, bool useAsCollateral) external override {
|
function setUserUseReserveAsCollateral(address asset, bool useAsCollateral)
|
||||||
|
external
|
||||||
|
override
|
||||||
|
whenNotPaused
|
||||||
|
{
|
||||||
ReserveLogic.ReserveData storage reserve = _reserves[asset];
|
ReserveLogic.ReserveData storage reserve = _reserves[asset];
|
||||||
|
|
||||||
ValidationLogic.validateSetUseReserveAsCollateral(
|
ValidationLogic.validateSetUseReserveAsCollateral(
|
||||||
|
@ -384,7 +389,7 @@ contract LendingPool is VersionedInitializable, ILendingPool {
|
||||||
address user,
|
address user,
|
||||||
uint256 purchaseAmount,
|
uint256 purchaseAmount,
|
||||||
bool receiveAToken
|
bool receiveAToken
|
||||||
) external override {
|
) external override whenNotPaused {
|
||||||
address liquidationManager = _addressesProvider.getLendingPoolLiquidationManager();
|
address liquidationManager = _addressesProvider.getLendingPoolLiquidationManager();
|
||||||
|
|
||||||
//solium-disable-next-line
|
//solium-disable-next-line
|
||||||
|
@ -440,7 +445,7 @@ contract LendingPool is VersionedInitializable, ILendingPool {
|
||||||
uint256 principalAmount,
|
uint256 principalAmount,
|
||||||
address receiver,
|
address receiver,
|
||||||
bytes calldata params
|
bytes calldata params
|
||||||
) external override {
|
) external override whenNotPaused {
|
||||||
require(!_flashLiquidationLocked, Errors.REENTRANCY_NOT_ALLOWED);
|
require(!_flashLiquidationLocked, Errors.REENTRANCY_NOT_ALLOWED);
|
||||||
_flashLiquidationLocked = true;
|
_flashLiquidationLocked = true;
|
||||||
|
|
||||||
|
@ -487,7 +492,7 @@ contract LendingPool is VersionedInitializable, ILendingPool {
|
||||||
uint256 mode,
|
uint256 mode,
|
||||||
bytes calldata params,
|
bytes calldata params,
|
||||||
uint16 referralCode
|
uint16 referralCode
|
||||||
) external override {
|
) external override whenNotPaused {
|
||||||
ReserveLogic.ReserveData storage reserve = _reserves[asset];
|
ReserveLogic.ReserveData storage reserve = _reserves[asset];
|
||||||
FlashLoanLocalVars memory vars;
|
FlashLoanLocalVars memory vars;
|
||||||
|
|
||||||
|
@ -706,7 +711,7 @@ contract LendingPool is VersionedInitializable, ILendingPool {
|
||||||
address stableDebtAddress,
|
address stableDebtAddress,
|
||||||
address variableDebtAddress,
|
address variableDebtAddress,
|
||||||
address interestRateStrategyAddress
|
address interestRateStrategyAddress
|
||||||
) external override onlyLendingPoolConfigurator {
|
) external override onlyLendingPoolConfigurator whenNotPaused {
|
||||||
_reserves[asset].init(
|
_reserves[asset].init(
|
||||||
aTokenAddress,
|
aTokenAddress,
|
||||||
stableDebtAddress,
|
stableDebtAddress,
|
||||||
|
@ -726,6 +731,7 @@ contract LendingPool is VersionedInitializable, ILendingPool {
|
||||||
external
|
external
|
||||||
override
|
override
|
||||||
onlyLendingPoolConfigurator
|
onlyLendingPoolConfigurator
|
||||||
|
whenNotPaused
|
||||||
{
|
{
|
||||||
_reserves[asset].interestRateStrategyAddress = rateStrategyAddress;
|
_reserves[asset].interestRateStrategyAddress = rateStrategyAddress;
|
||||||
}
|
}
|
||||||
|
@ -908,4 +914,25 @@ contract LendingPool is VersionedInitializable, ILendingPool {
|
||||||
function getAddressesProvider() external view returns (ILendingPoolAddressesProvider) {
|
function getAddressesProvider() external view returns (ILendingPoolAddressesProvider) {
|
||||||
return _addressesProvider;
|
return _addressesProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev pause all the Lending Pool actions
|
||||||
|
*/
|
||||||
|
function pause() external override onlyLendingPoolConfigurator {
|
||||||
|
_pause();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev unpause all the Lending Pool actions
|
||||||
|
*/
|
||||||
|
function unpause() external override onlyLendingPoolConfigurator {
|
||||||
|
_unpause();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev Returns true if the contract is paused, and false otherwise.
|
||||||
|
*/
|
||||||
|
function isPaused() public override view returns (bool) {
|
||||||
|
return Pausable.paused();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -582,4 +582,18 @@ contract LendingPoolConfigurator is VersionedInitializable {
|
||||||
|
|
||||||
proxy.upgradeToAndCall(implementation, params);
|
proxy.upgradeToAndCall(implementation, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev pauses LendingPool actions
|
||||||
|
**/
|
||||||
|
function pausePool() external onlyLendingPoolManager {
|
||||||
|
pool.pause();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev unpauses LendingPool actions
|
||||||
|
**/
|
||||||
|
function unpausePool() external onlyLendingPoolManager {
|
||||||
|
pool.unpause();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,7 +67,6 @@ contract AToken is VersionedInitializable, ERC20, IAToken {
|
||||||
uint256 amount,
|
uint256 amount,
|
||||||
uint256 index
|
uint256 index
|
||||||
) external override onlyLendingPool {
|
) external override onlyLendingPool {
|
||||||
|
|
||||||
uint256 currentBalance = balanceOf(user);
|
uint256 currentBalance = balanceOf(user);
|
||||||
|
|
||||||
require(amount <= currentBalance, Errors.INVALID_ATOKEN_BALANCE);
|
require(amount <= currentBalance, Errors.INVALID_ATOKEN_BALANCE);
|
||||||
|
@ -79,7 +78,6 @@ contract AToken is VersionedInitializable, ERC20, IAToken {
|
||||||
//transfers the underlying to the target
|
//transfers the underlying to the target
|
||||||
ERC20(UNDERLYING_ASSET_ADDRESS).safeTransfer(receiverOfUnderlying, amount);
|
ERC20(UNDERLYING_ASSET_ADDRESS).safeTransfer(receiverOfUnderlying, amount);
|
||||||
|
|
||||||
|
|
||||||
emit Burn(msg.sender, receiverOfUnderlying, amount, index);
|
emit Burn(msg.sender, receiverOfUnderlying, amount, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,13 +87,15 @@ contract AToken is VersionedInitializable, ERC20, IAToken {
|
||||||
* @param user the address receiving the minted tokens
|
* @param user the address receiving the minted tokens
|
||||||
* @param amount the amount of tokens to mint
|
* @param amount the amount of tokens to mint
|
||||||
*/
|
*/
|
||||||
function mint(address user, uint256 amount, uint256 index) external override onlyLendingPool {
|
function mint(
|
||||||
|
address user,
|
||||||
|
uint256 amount,
|
||||||
|
uint256 index
|
||||||
|
) external override onlyLendingPool {
|
||||||
uint256 scaledAmount = amount.rayDiv(index);
|
uint256 scaledAmount = amount.rayDiv(index);
|
||||||
|
|
||||||
//mint an equivalent amount of tokens to cover the new deposit
|
//mint an equivalent amount of tokens to cover the new deposit
|
||||||
_mint(user,scaledAmount);
|
_mint(user, scaledAmount);
|
||||||
|
|
||||||
emit Mint(user, amount, index);
|
emit Mint(user, amount, index);
|
||||||
}
|
}
|
||||||
|
@ -150,9 +150,7 @@ contract AToken is VersionedInitializable, ERC20, IAToken {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return currentSupplyScaled.rayMul(POOL.getReserveNormalizedIncome(UNDERLYING_ASSET_ADDRESS));
|
||||||
currentSupplyScaled
|
|
||||||
.rayMul(POOL.getReserveNormalizedIncome(UNDERLYING_ASSET_ADDRESS));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -162,16 +160,16 @@ contract AToken is VersionedInitializable, ERC20, IAToken {
|
||||||
* @return true if the user can transfer amount, false otherwise
|
* @return true if the user can transfer amount, false otherwise
|
||||||
**/
|
**/
|
||||||
function isTransferAllowed(address user, uint256 amount) public override view returns (bool) {
|
function isTransferAllowed(address user, uint256 amount) public override view returns (bool) {
|
||||||
return POOL.balanceDecreaseAllowed(UNDERLYING_ASSET_ADDRESS, user, amount);
|
return !POOL.isPaused() && POOL.balanceDecreaseAllowed(UNDERLYING_ASSET_ADDRESS, user, amount);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev transfers the underlying asset to the target. Used by the lendingpool to transfer
|
* @dev transfers the underlying asset to the target. Used by the lendingpool to transfer
|
||||||
* assets in borrow(), redeem() and flashLoan()
|
* assets in borrow(), redeem() and flashLoan()
|
||||||
* @param target the target of the transfer
|
* @param target the target of the transfer
|
||||||
* @param amount the amount to transfer
|
* @param amount the amount to transfer
|
||||||
* @return the amount transferred
|
* @return the amount transferred
|
||||||
**/
|
**/
|
||||||
function transferUnderlyingTo(address target, uint256 amount)
|
function transferUnderlyingTo(address target, uint256 amount)
|
||||||
external
|
external
|
||||||
override
|
override
|
||||||
|
@ -187,8 +185,8 @@ contract AToken is VersionedInitializable, ERC20, IAToken {
|
||||||
address to,
|
address to,
|
||||||
uint256 amount,
|
uint256 amount,
|
||||||
bool validate
|
bool validate
|
||||||
) internal {
|
) internal {
|
||||||
if(validate){
|
if (validate) {
|
||||||
require(isTransferAllowed(from, amount), Errors.TRANSFER_NOT_ALLOWED);
|
require(isTransferAllowed(from, amount), Errors.TRANSFER_NOT_ALLOWED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -199,17 +197,16 @@ contract AToken is VersionedInitializable, ERC20, IAToken {
|
||||||
super._transfer(from, to, scaledAmount);
|
super._transfer(from, to, scaledAmount);
|
||||||
|
|
||||||
emit BalanceTransfer(from, to, amount, index);
|
emit BalanceTransfer(from, to, amount, index);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function _transfer(
|
function _transfer(
|
||||||
address from,
|
address from,
|
||||||
address to,
|
address to,
|
||||||
uint256 amount
|
uint256 amount
|
||||||
) internal override {
|
) internal override {
|
||||||
|
_transfer(from, to, amount, true);
|
||||||
_transfer(from, to, amount, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev aTokens should not receive ETH
|
* @dev aTokens should not receive ETH
|
||||||
**/
|
**/
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
"test-scenarios": "buidler test test/__setup.spec.ts test/scenario.spec.ts",
|
"test-scenarios": "buidler test test/__setup.spec.ts test/scenario.spec.ts",
|
||||||
"test-repay-with-collateral": "buidler test test/__setup.spec.ts test/repay-with-collateral.spec.ts",
|
"test-repay-with-collateral": "buidler test test/__setup.spec.ts test/repay-with-collateral.spec.ts",
|
||||||
"test-liquidate-with-collateral": "buidler test test/__setup.spec.ts test/flash-liquidation-with-collateral.spec.ts",
|
"test-liquidate-with-collateral": "buidler test test/__setup.spec.ts test/flash-liquidation-with-collateral.spec.ts",
|
||||||
|
"test-transfers": "buidler test test/__setup.spec.ts test/atoken-transfer.spec.ts",
|
||||||
"test-flash": "buidler test test/__setup.spec.ts test/flashloan.spec.ts",
|
"test-flash": "buidler test test/__setup.spec.ts test/flashloan.spec.ts",
|
||||||
"dev:coverage": "buidler coverage --network coverage",
|
"dev:coverage": "buidler coverage --network coverage",
|
||||||
"dev:deployment": "buidler dev-deployment",
|
"dev:deployment": "buidler dev-deployment",
|
||||||
|
|
|
@ -45,7 +45,6 @@ makeSuite('AToken: Transfer', (testEnv: TestEnv) => {
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
it('User 0 deposits 1 WETH and user 1 tries to borrow, but the aTokens received as a transfer are not available as collateral (revert expected)', async () => {
|
it('User 0 deposits 1 WETH and user 1 tries to borrow, but the aTokens received as a transfer are not available as collateral (revert expected)', async () => {
|
||||||
const {users, pool, weth} = testEnv;
|
const {users, pool, weth} = testEnv;
|
||||||
const userAddress = await pool.signer.getAddress();
|
const userAddress = await pool.signer.getAddress();
|
||||||
|
@ -81,4 +80,58 @@ makeSuite('AToken: Transfer', (testEnv: TestEnv) => {
|
||||||
).to.be.revertedWith(TRANSFER_NOT_ALLOWED);
|
).to.be.revertedWith(TRANSFER_NOT_ALLOWED);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('User 0 deposits 1000 DAI. Configurator pauses pool. Transfers to user 1 reverts. Configurator unpauses the network and next transfer succees', async () => {
|
||||||
|
const {users, pool, dai, aDai, configurator} = testEnv;
|
||||||
|
|
||||||
|
const amountDAItoDeposit = await convertToCurrencyDecimals(dai.address, '1000');
|
||||||
|
|
||||||
|
await dai.connect(users[0].signer).mint(amountDAItoDeposit);
|
||||||
|
|
||||||
|
// user 0 deposits 1000 DAI
|
||||||
|
await dai.connect(users[0].signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL);
|
||||||
|
await pool
|
||||||
|
.connect(users[0].signer)
|
||||||
|
.deposit(dai.address, amountDAItoDeposit, users[0].address, '0');
|
||||||
|
|
||||||
|
const user0Balance = await aDai.balanceOf(users[0].address);
|
||||||
|
const user1Balance = await aDai.balanceOf(users[1].address);
|
||||||
|
|
||||||
|
// Configurator pauses the pool
|
||||||
|
await configurator.pausePool();
|
||||||
|
|
||||||
|
// User 0 tries the transfer to User 1
|
||||||
|
await expect(
|
||||||
|
aDai.connect(users[0].signer).transfer(users[1].address, amountDAItoDeposit)
|
||||||
|
).to.revertedWith(TRANSFER_NOT_ALLOWED);
|
||||||
|
|
||||||
|
const pausedFromBalance = await aDai.balanceOf(users[0].address);
|
||||||
|
const pausedToBalance = await aDai.balanceOf(users[1].address);
|
||||||
|
|
||||||
|
expect(pausedFromBalance).to.be.equal(
|
||||||
|
user0Balance.toString(),
|
||||||
|
INVALID_TO_BALANCE_AFTER_TRANSFER
|
||||||
|
);
|
||||||
|
expect(pausedToBalance.toString()).to.be.equal(
|
||||||
|
user1Balance.toString(),
|
||||||
|
INVALID_FROM_BALANCE_AFTER_TRANSFER
|
||||||
|
);
|
||||||
|
|
||||||
|
// Configurator unpauses the pool
|
||||||
|
await configurator.unpausePool();
|
||||||
|
|
||||||
|
// User 0 succeeds transfer to User 1
|
||||||
|
await aDai.connect(users[0].signer).transfer(users[1].address, amountDAItoDeposit);
|
||||||
|
|
||||||
|
const fromBalance = await aDai.balanceOf(users[0].address);
|
||||||
|
const toBalance = await aDai.balanceOf(users[1].address);
|
||||||
|
|
||||||
|
expect(fromBalance.toString()).to.be.equal(
|
||||||
|
user0Balance.sub(amountDAItoDeposit),
|
||||||
|
INVALID_FROM_BALANCE_AFTER_TRANSFER
|
||||||
|
);
|
||||||
|
expect(toBalance.toString()).to.be.equal(
|
||||||
|
user1Balance.add(amountDAItoDeposit),
|
||||||
|
INVALID_TO_BALANCE_AFTER_TRANSFER
|
||||||
|
);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue
Block a user