mirror of
https://github.com/Instadapp/aave-protocol-v2.git
synced 2024-07-29 21:47:30 +00:00
Merge branch 'master' into feat/18
This commit is contained in:
commit
53d6114775
|
@ -13,5 +13,5 @@ interface IFlashLoanReceiver {
|
||||||
uint256 amount,
|
uint256 amount,
|
||||||
uint256 fee,
|
uint256 fee,
|
||||||
bytes calldata params
|
bytes calldata params
|
||||||
) external;
|
) external returns (bool);
|
||||||
}
|
}
|
||||||
|
|
|
@ -579,7 +579,10 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
|
||||||
IAToken(vars.aTokenAddress).transferUnderlyingTo(receiverAddress, amount);
|
IAToken(vars.aTokenAddress).transferUnderlyingTo(receiverAddress, amount);
|
||||||
|
|
||||||
//execute action of the receiver
|
//execute action of the receiver
|
||||||
vars.receiver.executeOperation(asset, amount, vars.premium, params);
|
require(
|
||||||
|
vars.receiver.executeOperation(asset, amount, vars.premium, params),
|
||||||
|
Errors.INVALID_FLASH_LOAN_EXECUTOR_RETURN
|
||||||
|
);
|
||||||
|
|
||||||
vars.amountPlusPremium = amount.add(vars.premium);
|
vars.amountPlusPremium = amount.add(vars.premium);
|
||||||
|
|
||||||
|
|
|
@ -239,12 +239,15 @@ contract LendingPoolCollateralManager is VersionedInitializable, LendingPoolStor
|
||||||
principalReserve.variableBorrowIndex
|
principalReserve.variableBorrowIndex
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
IVariableDebtToken(principalReserve.variableDebtTokenAddress).burn(
|
//if the user does not have variable debt, no need to try to burn variable
|
||||||
user,
|
//debt tokens
|
||||||
vars.userVariableDebt,
|
if (vars.userVariableDebt > 0) {
|
||||||
principalReserve.variableBorrowIndex
|
IVariableDebtToken(principalReserve.variableDebtTokenAddress).burn(
|
||||||
);
|
user,
|
||||||
|
vars.userVariableDebt,
|
||||||
|
principalReserve.variableBorrowIndex
|
||||||
|
);
|
||||||
|
}
|
||||||
IStableDebtToken(principalReserve.stableDebtTokenAddress).burn(
|
IStableDebtToken(principalReserve.stableDebtTokenAddress).burn(
|
||||||
user,
|
user,
|
||||||
vars.actualAmountToLiquidate.sub(vars.userVariableDebt)
|
vars.actualAmountToLiquidate.sub(vars.userVariableDebt)
|
||||||
|
|
|
@ -44,11 +44,14 @@ library Errors {
|
||||||
string public constant FAILED_COLLATERAL_SWAP = '55';
|
string public constant FAILED_COLLATERAL_SWAP = '55';
|
||||||
string public constant INVALID_EQUAL_ASSETS_TO_SWAP = '56';
|
string public constant INVALID_EQUAL_ASSETS_TO_SWAP = '56';
|
||||||
string public constant NO_MORE_RESERVES_ALLOWED = '59';
|
string public constant NO_MORE_RESERVES_ALLOWED = '59';
|
||||||
|
string public constant INVALID_FLASH_LOAN_EXECUTOR_RETURN = '60';
|
||||||
|
|
||||||
// require error messages - aToken
|
// require error messages - aToken - DebtTokens
|
||||||
string public constant CALLER_MUST_BE_LENDING_POOL = '28'; // 'The caller of this function must be a lending pool'
|
string public constant CALLER_MUST_BE_LENDING_POOL = '28'; // 'The caller of this function must be a lending pool'
|
||||||
string public constant CANNOT_GIVE_ALLOWANCE_TO_HIMSELF = '30'; // 'User cannot give allowance to himself'
|
string public constant CANNOT_GIVE_ALLOWANCE_TO_HIMSELF = '30'; // 'User cannot give allowance to himself'
|
||||||
string public constant TRANSFER_AMOUNT_NOT_GT_0 = '31'; // 'Transferred amount needs to be greater than zero'
|
string public constant TRANSFER_AMOUNT_NOT_GT_0 = '31'; // 'Transferred amount needs to be greater than zero'
|
||||||
|
string public constant INVALID_MINT_AMOUNT = '53'; //invalid amount to mint
|
||||||
|
string public constant INVALID_BURN_AMOUNT = '54'; //invalid amount to burn
|
||||||
|
|
||||||
// require error messages - ReserveLogic
|
// require error messages - ReserveLogic
|
||||||
string public constant RESERVE_ALREADY_INITIALIZED = '34'; // 'Reserve has already been initialized'
|
string public constant RESERVE_ALREADY_INITIALIZED = '34'; // 'Reserve has already been initialized'
|
||||||
|
|
|
@ -20,6 +20,7 @@ contract MockFlashLoanReceiver is FlashLoanReceiverBase {
|
||||||
|
|
||||||
bool _failExecution;
|
bool _failExecution;
|
||||||
uint256 _amountToApprove;
|
uint256 _amountToApprove;
|
||||||
|
bool _simulateEOA;
|
||||||
|
|
||||||
constructor(ILendingPoolAddressesProvider provider) public FlashLoanReceiverBase(provider) {}
|
constructor(ILendingPoolAddressesProvider provider) public FlashLoanReceiverBase(provider) {}
|
||||||
|
|
||||||
|
@ -31,16 +32,25 @@ contract MockFlashLoanReceiver is FlashLoanReceiverBase {
|
||||||
_amountToApprove = amountToApprove;
|
_amountToApprove = amountToApprove;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function setSimulateEOA(bool flag) public {
|
||||||
|
_simulateEOA = flag;
|
||||||
|
}
|
||||||
|
|
||||||
function amountToApprove() public view returns (uint256) {
|
function amountToApprove() public view returns (uint256) {
|
||||||
return _amountToApprove;
|
return _amountToApprove;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function simulateEOA() public view returns (bool) {
|
||||||
|
return _simulateEOA;
|
||||||
|
}
|
||||||
|
|
||||||
function executeOperation(
|
function executeOperation(
|
||||||
address reserve,
|
address reserve,
|
||||||
uint256 amount,
|
uint256 amount,
|
||||||
uint256 fee,
|
uint256 fee,
|
||||||
bytes memory params
|
bytes memory params
|
||||||
) public override {
|
) public override returns (bool) {
|
||||||
|
params;
|
||||||
//mint to this contract the specific amount
|
//mint to this contract the specific amount
|
||||||
MintableERC20 token = MintableERC20(reserve);
|
MintableERC20 token = MintableERC20(reserve);
|
||||||
|
|
||||||
|
@ -51,7 +61,7 @@ contract MockFlashLoanReceiver is FlashLoanReceiverBase {
|
||||||
|
|
||||||
if (_failExecution) {
|
if (_failExecution) {
|
||||||
emit ExecutedWithFail(reserve, amount, fee);
|
emit ExecutedWithFail(reserve, amount, fee);
|
||||||
return;
|
return !_simulateEOA;
|
||||||
}
|
}
|
||||||
|
|
||||||
//execution does not fail - mint tokens and return them to the _destination
|
//execution does not fail - mint tokens and return them to the _destination
|
||||||
|
@ -62,5 +72,7 @@ contract MockFlashLoanReceiver is FlashLoanReceiverBase {
|
||||||
IERC20(reserve).approve(_addressesProvider.getLendingPool(), amountToReturn);
|
IERC20(reserve).approve(_addressesProvider.getLendingPool(), amountToReturn);
|
||||||
|
|
||||||
emit ExecutedWithSuccess(reserve, amount, fee);
|
emit ExecutedWithSuccess(reserve, amount, fee);
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -101,7 +101,9 @@ contract AToken is VersionedInitializable, IncentivizedERC20, IAToken {
|
||||||
uint256 amount,
|
uint256 amount,
|
||||||
uint256 index
|
uint256 index
|
||||||
) external override onlyLendingPool {
|
) external override onlyLendingPool {
|
||||||
_burn(user, amount.rayDiv(index));
|
uint256 amountScaled = amount.rayDiv(index);
|
||||||
|
require(amountScaled != 0, Errors.INVALID_BURN_AMOUNT);
|
||||||
|
_burn(user, amountScaled);
|
||||||
|
|
||||||
//transfers the underlying to the target
|
//transfers the underlying to the target
|
||||||
IERC20(UNDERLYING_ASSET_ADDRESS).safeTransfer(receiverOfUnderlying, amount);
|
IERC20(UNDERLYING_ASSET_ADDRESS).safeTransfer(receiverOfUnderlying, amount);
|
||||||
|
@ -116,22 +118,39 @@ contract AToken is VersionedInitializable, IncentivizedERC20, IAToken {
|
||||||
* only lending pools can call this function
|
* only lending pools can call this function
|
||||||
* @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
|
||||||
|
* @param index the the last index of the reserve
|
||||||
*/
|
*/
|
||||||
function mint(
|
function mint(
|
||||||
address user,
|
address user,
|
||||||
uint256 amount,
|
uint256 amount,
|
||||||
uint256 index
|
uint256 index
|
||||||
) external override onlyLendingPool {
|
) external override onlyLendingPool {
|
||||||
//mint an equivalent amount of tokens to cover the new deposit
|
uint256 amountScaled = amount.rayDiv(index);
|
||||||
_mint(user, amount.rayDiv(index));
|
require(amountScaled != 0, Errors.INVALID_MINT_AMOUNT);
|
||||||
|
_mint(user, amountScaled);
|
||||||
|
|
||||||
//transfer event to track balances
|
//transfer event to track balances
|
||||||
emit Transfer(address(0), user, amount);
|
emit Transfer(address(0), user, amount);
|
||||||
emit Mint(user, amount, index);
|
emit Mint(user, amount, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @dev mints aTokens to reserve treasury
|
||||||
|
* only lending pools can call this function
|
||||||
|
* @param amount the amount of tokens to mint to the treasury
|
||||||
|
* @param index the the last index of the reserve
|
||||||
|
*/
|
||||||
function mintToTreasury(uint256 amount, uint256 index) external override onlyLendingPool {
|
function mintToTreasury(uint256 amount, uint256 index) external override onlyLendingPool {
|
||||||
_mint(RESERVE_TREASURY_ADDRESS, amount.div(index));
|
if (amount == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//compared to the normal mint, we don't check for rounding errors.
|
||||||
|
//the amount to mint can easily be very small since is a fraction of the interest
|
||||||
|
//accrued. in that case, the treasury will experience a (very small) loss, but it
|
||||||
|
//wont cause potentially valid transactions to fail.
|
||||||
|
|
||||||
|
_mint(RESERVE_TREASURY_ADDRESS, amount.rayDiv(index));
|
||||||
|
|
||||||
//transfer event to track balances
|
//transfer event to track balances
|
||||||
emit Transfer(address(0), RESERVE_TREASURY_ADDRESS, amount);
|
emit Transfer(address(0), RESERVE_TREASURY_ADDRESS, amount);
|
||||||
|
|
|
@ -7,6 +7,7 @@ import {SafeMath} from '@openzeppelin/contracts/math/SafeMath.sol';
|
||||||
import {DebtTokenBase} from './base/DebtTokenBase.sol';
|
import {DebtTokenBase} from './base/DebtTokenBase.sol';
|
||||||
import {WadRayMath} from '../libraries/math/WadRayMath.sol';
|
import {WadRayMath} from '../libraries/math/WadRayMath.sol';
|
||||||
import {IVariableDebtToken} from './interfaces/IVariableDebtToken.sol';
|
import {IVariableDebtToken} from './interfaces/IVariableDebtToken.sol';
|
||||||
|
import {Errors} from '../libraries/helpers/Errors.sol';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @title contract VariableDebtToken
|
* @title contract VariableDebtToken
|
||||||
|
@ -59,7 +60,10 @@ contract VariableDebtToken is DebtTokenBase, IVariableDebtToken {
|
||||||
uint256 amount,
|
uint256 amount,
|
||||||
uint256 index
|
uint256 index
|
||||||
) external override onlyLendingPool {
|
) external override onlyLendingPool {
|
||||||
_mint(user, amount.rayDiv(index));
|
uint256 amountScaled = amount.rayDiv(index);
|
||||||
|
require(amountScaled != 0, Errors.INVALID_MINT_AMOUNT);
|
||||||
|
|
||||||
|
_mint(user, amountScaled);
|
||||||
|
|
||||||
emit Transfer(address(0), user, amount);
|
emit Transfer(address(0), user, amount);
|
||||||
emit Mint(user, amount, index);
|
emit Mint(user, amount, index);
|
||||||
|
@ -75,7 +79,10 @@ contract VariableDebtToken is DebtTokenBase, IVariableDebtToken {
|
||||||
uint256 amount,
|
uint256 amount,
|
||||||
uint256 index
|
uint256 index
|
||||||
) external override onlyLendingPool {
|
) external override onlyLendingPool {
|
||||||
_burn(user, amount.rayDiv(index));
|
uint256 amountScaled = amount.rayDiv(index);
|
||||||
|
require(amountScaled != 0, Errors.INVALID_BURN_AMOUNT);
|
||||||
|
|
||||||
|
_burn(user, amountScaled);
|
||||||
|
|
||||||
emit Transfer(user, address(0), amount);
|
emit Transfer(user, address(0), amount);
|
||||||
emit Burn(user, amount, index);
|
emit Burn(user, amount, index);
|
||||||
|
|
|
@ -90,6 +90,7 @@ export enum ProtocolErrors {
|
||||||
REQUESTED_AMOUNT_TOO_SMALL = '25', // 'The requested amount is too small for a FlashLoan.'
|
REQUESTED_AMOUNT_TOO_SMALL = '25', // 'The requested amount is too small for a FlashLoan.'
|
||||||
INCONSISTENT_PROTOCOL_ACTUAL_BALANCE = '26', // 'The actual balance of the protocol is inconsistent'
|
INCONSISTENT_PROTOCOL_ACTUAL_BALANCE = '26', // 'The actual balance of the protocol is inconsistent'
|
||||||
CALLER_NOT_LENDING_POOL_CONFIGURATOR = '27', // 'The actual balance of the protocol is inconsistent'
|
CALLER_NOT_LENDING_POOL_CONFIGURATOR = '27', // 'The actual balance of the protocol is inconsistent'
|
||||||
|
INVALID_FLASH_LOAN_EXECUTOR_RETURN = '60', // The flash loan received returned 0 (EOA)
|
||||||
|
|
||||||
// require error messages - aToken
|
// require error messages - aToken
|
||||||
CALLER_MUST_BE_LENDING_POOL = '28', // 'The caller of this function must be a lending pool'
|
CALLER_MUST_BE_LENDING_POOL = '28', // 'The caller of this function must be a lending pool'
|
||||||
|
|
|
@ -24,6 +24,7 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => {
|
||||||
INVALID_FLASHLOAN_MODE,
|
INVALID_FLASHLOAN_MODE,
|
||||||
SAFEERC20_LOWLEVEL_CALL,
|
SAFEERC20_LOWLEVEL_CALL,
|
||||||
IS_PAUSED,
|
IS_PAUSED,
|
||||||
|
INVALID_FLASH_LOAN_EXECUTOR_RETURN,
|
||||||
} = ProtocolErrors;
|
} = ProtocolErrors;
|
||||||
|
|
||||||
before(async () => {
|
before(async () => {
|
||||||
|
@ -116,9 +117,30 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => {
|
||||||
).to.be.revertedWith(TRANSFER_AMOUNT_EXCEEDS_BALANCE);
|
).to.be.revertedWith(TRANSFER_AMOUNT_EXCEEDS_BALANCE);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('Takes WETH flashloan, simulating a receiver as EOA (revert expected)', async () => {
|
||||||
|
const {pool, weth, users} = testEnv;
|
||||||
|
const caller = users[1];
|
||||||
|
await _mockFlashLoanReceiver.setFailExecutionTransfer(true);
|
||||||
|
await _mockFlashLoanReceiver.setSimulateEOA(true);
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
pool
|
||||||
|
.connect(caller.signer)
|
||||||
|
.flashLoan(
|
||||||
|
_mockFlashLoanReceiver.address,
|
||||||
|
weth.address,
|
||||||
|
ethers.utils.parseEther('0.8'),
|
||||||
|
0,
|
||||||
|
'0x10',
|
||||||
|
'0'
|
||||||
|
)
|
||||||
|
).to.be.revertedWith(INVALID_FLASH_LOAN_EXECUTOR_RETURN);
|
||||||
|
});
|
||||||
|
|
||||||
it('Takes a WETH flashloan with an invalid mode. (revert expected)', async () => {
|
it('Takes a WETH flashloan with an invalid mode. (revert expected)', async () => {
|
||||||
const {pool, weth, users} = testEnv;
|
const {pool, weth, users} = testEnv;
|
||||||
const caller = users[1];
|
const caller = users[1];
|
||||||
|
await _mockFlashLoanReceiver.setSimulateEOA(false);
|
||||||
await _mockFlashLoanReceiver.setFailExecutionTransfer(true);
|
await _mockFlashLoanReceiver.setFailExecutionTransfer(true);
|
||||||
|
|
||||||
await expect(
|
await expect(
|
||||||
|
|
Loading…
Reference in New Issue
Block a user