mirror of
https://github.com/Instadapp/aave-protocol-v2.git
synced 2024-07-29 21:47:30 +00:00
Merge branch 'master' of gitlab.com:aave-tech/protocol-v2 into 97-create-a-utility-contract-to-deposit-withdraw-repay-with-eth
This commit is contained in:
commit
2892e69df0
|
@ -99,6 +99,8 @@ interface ILendingPool {
|
||||||
/**
|
/**
|
||||||
* @dev emitted when a flashloan is executed
|
* @dev emitted when a flashloan is executed
|
||||||
* @param target the address of the flashLoanReceiver
|
* @param target the address of the flashLoanReceiver
|
||||||
|
* @param mode Type of the debt to open if the flash loan is not returned. 0 -> Don't open any debt, just revert, 1 -> stable, 2 -> variable
|
||||||
|
* @param onBehalfOf the address incurring the debt, if borrow mode is not 0
|
||||||
* @param assets the address of the assets being flashborrowed
|
* @param assets the address of the assets being flashborrowed
|
||||||
* @param amounts the amount requested
|
* @param amounts the amount requested
|
||||||
* @param premiums the total fee on the amount
|
* @param premiums the total fee on the amount
|
||||||
|
@ -107,6 +109,7 @@ interface ILendingPool {
|
||||||
event FlashLoan(
|
event FlashLoan(
|
||||||
address indexed target,
|
address indexed target,
|
||||||
uint256 mode,
|
uint256 mode,
|
||||||
|
address indexed onBehalfOf,
|
||||||
address[] assets,
|
address[] assets,
|
||||||
uint256[] amounts,
|
uint256[] amounts,
|
||||||
uint256[] premiums,
|
uint256[] premiums,
|
||||||
|
@ -295,6 +298,7 @@ interface ILendingPool {
|
||||||
address[] calldata assets,
|
address[] calldata assets,
|
||||||
uint256[] calldata amounts,
|
uint256[] calldata amounts,
|
||||||
uint256 mode,
|
uint256 mode,
|
||||||
|
address onBehalfOf,
|
||||||
bytes calldata params,
|
bytes calldata params,
|
||||||
uint16 referralCode
|
uint16 referralCode
|
||||||
) external;
|
) external;
|
||||||
|
|
|
@ -503,6 +503,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
|
||||||
* @param assets The addresss of the assets being flashborrowed
|
* @param assets The addresss of the assets being flashborrowed
|
||||||
* @param amounts The amounts requested for this flashloan for each asset
|
* @param amounts The amounts requested for this flashloan for each asset
|
||||||
* @param mode Type of the debt to open if the flash loan is not returned. 0 -> Don't open any debt, just revert, 1 -> stable, 2 -> variable
|
* @param mode Type of the debt to open if the flash loan is not returned. 0 -> Don't open any debt, just revert, 1 -> stable, 2 -> variable
|
||||||
|
* @param onBehalfOf If mode is not 0, then the address to take the debt onBehalfOf. The onBehalfOf address must already have approved `msg.sender` to incur the debt on their behalf.
|
||||||
* @param params Variadic packed params to pass to the receiver as extra information
|
* @param params Variadic packed params to pass to the receiver as extra information
|
||||||
* @param referralCode Referral code of the flash loan
|
* @param referralCode Referral code of the flash loan
|
||||||
**/
|
**/
|
||||||
|
@ -511,6 +512,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
|
||||||
address[] calldata assets,
|
address[] calldata assets,
|
||||||
uint256[] calldata amounts,
|
uint256[] calldata amounts,
|
||||||
uint256 mode,
|
uint256 mode,
|
||||||
|
address onBehalfOf,
|
||||||
bytes calldata params,
|
bytes calldata params,
|
||||||
uint16 referralCode
|
uint16 referralCode
|
||||||
) external override {
|
) external override {
|
||||||
|
@ -568,13 +570,23 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
|
||||||
vars.currentAmountPlusPremium
|
vars.currentAmountPlusPremium
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
|
if (msg.sender != onBehalfOf) {
|
||||||
|
address debtToken = _reserves[vars.currentAsset].getDebtTokenAddress(mode);
|
||||||
|
|
||||||
|
_borrowAllowance[debtToken][onBehalfOf][msg
|
||||||
|
.sender] = _borrowAllowance[debtToken][onBehalfOf][msg.sender].sub(
|
||||||
|
vars.currentAmount,
|
||||||
|
Errors.BORROW_ALLOWANCE_ARE_NOT_ENOUGH
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
//if the user didn't choose to return the funds, the system checks if there
|
//if the user didn't choose to return the funds, the system checks if there
|
||||||
//is enough collateral and eventually open a position
|
//is enough collateral and eventually open a position
|
||||||
_executeBorrow(
|
_executeBorrow(
|
||||||
ExecuteBorrowParams(
|
ExecuteBorrowParams(
|
||||||
vars.currentAsset,
|
vars.currentAsset,
|
||||||
msg.sender,
|
msg.sender,
|
||||||
msg.sender,
|
onBehalfOf,
|
||||||
vars.currentAmount,
|
vars.currentAmount,
|
||||||
mode,
|
mode,
|
||||||
vars.currentATokenAddress,
|
vars.currentATokenAddress,
|
||||||
|
@ -583,7 +595,7 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
emit FlashLoan(receiverAddress, mode, assets, amounts, premiums, referralCode);
|
emit FlashLoan(receiverAddress, mode, onBehalfOf, assets, amounts, premiums, referralCode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -94,6 +94,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'
|
||||||
|
BORROW_ALLOWANCE_ARE_NOT_ENOUGH = '54', // User borrows on behalf, but allowance are too small
|
||||||
INVALID_FLASH_LOAN_EXECUTOR_RETURN = '60', // The flash loan received returned 0 (EOA)
|
INVALID_FLASH_LOAN_EXECUTOR_RETURN = '60', // The flash loan received returned 0 (EOA)
|
||||||
|
|
||||||
// require error messages - aToken
|
// require error messages - aToken
|
||||||
|
|
|
@ -22,6 +22,7 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => {
|
||||||
SAFEERC20_LOWLEVEL_CALL,
|
SAFEERC20_LOWLEVEL_CALL,
|
||||||
IS_PAUSED,
|
IS_PAUSED,
|
||||||
INVALID_FLASH_LOAN_EXECUTOR_RETURN,
|
INVALID_FLASH_LOAN_EXECUTOR_RETURN,
|
||||||
|
BORROW_ALLOWANCE_ARE_NOT_ENOUGH,
|
||||||
} = ProtocolErrors;
|
} = ProtocolErrors;
|
||||||
|
|
||||||
before(async () => {
|
before(async () => {
|
||||||
|
@ -48,6 +49,7 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => {
|
||||||
[weth.address],
|
[weth.address],
|
||||||
[ethers.utils.parseEther('0.8')],
|
[ethers.utils.parseEther('0.8')],
|
||||||
0,
|
0,
|
||||||
|
_mockFlashLoanReceiver.address,
|
||||||
'0x10',
|
'0x10',
|
||||||
'0'
|
'0'
|
||||||
);
|
);
|
||||||
|
@ -77,6 +79,7 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => {
|
||||||
[weth.address],
|
[weth.address],
|
||||||
['1000720000000000000'],
|
['1000720000000000000'],
|
||||||
0,
|
0,
|
||||||
|
_mockFlashLoanReceiver.address,
|
||||||
'0x10',
|
'0x10',
|
||||||
'0'
|
'0'
|
||||||
);
|
);
|
||||||
|
@ -108,6 +111,7 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => {
|
||||||
[weth.address],
|
[weth.address],
|
||||||
[ethers.utils.parseEther('0.8')],
|
[ethers.utils.parseEther('0.8')],
|
||||||
0,
|
0,
|
||||||
|
caller.address,
|
||||||
'0x10',
|
'0x10',
|
||||||
'0'
|
'0'
|
||||||
)
|
)
|
||||||
|
@ -128,6 +132,7 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => {
|
||||||
[weth.address],
|
[weth.address],
|
||||||
[ethers.utils.parseEther('0.8')],
|
[ethers.utils.parseEther('0.8')],
|
||||||
0,
|
0,
|
||||||
|
caller.address,
|
||||||
'0x10',
|
'0x10',
|
||||||
'0'
|
'0'
|
||||||
)
|
)
|
||||||
|
@ -148,6 +153,7 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => {
|
||||||
[weth.address],
|
[weth.address],
|
||||||
[ethers.utils.parseEther('0.8')],
|
[ethers.utils.parseEther('0.8')],
|
||||||
4,
|
4,
|
||||||
|
caller.address,
|
||||||
'0x10',
|
'0x10',
|
||||||
'0'
|
'0'
|
||||||
)
|
)
|
||||||
|
@ -176,6 +182,7 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => {
|
||||||
[weth.address],
|
[weth.address],
|
||||||
[ethers.utils.parseEther('0.8')],
|
[ethers.utils.parseEther('0.8')],
|
||||||
2,
|
2,
|
||||||
|
caller.address,
|
||||||
'0x10',
|
'0x10',
|
||||||
'0'
|
'0'
|
||||||
);
|
);
|
||||||
|
@ -194,14 +201,16 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('tries to take a flashloan that is bigger than the available liquidity (revert expected)', async () => {
|
it('tries to take a flashloan that is bigger than the available liquidity (revert expected)', async () => {
|
||||||
const {pool, weth} = testEnv;
|
const {pool, weth, users} = testEnv;
|
||||||
|
const caller = users[1];
|
||||||
|
|
||||||
await expect(
|
await expect(
|
||||||
pool.flashLoan(
|
pool.connect(caller.signer).flashLoan(
|
||||||
_mockFlashLoanReceiver.address,
|
_mockFlashLoanReceiver.address,
|
||||||
[weth.address],
|
[weth.address],
|
||||||
['1004415000000000000'], //slightly higher than the available liquidity
|
['1004415000000000000'], //slightly higher than the available liquidity
|
||||||
2,
|
2,
|
||||||
|
caller.address,
|
||||||
'0x10',
|
'0x10',
|
||||||
'0'
|
'0'
|
||||||
),
|
),
|
||||||
|
@ -210,10 +219,11 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('tries to take a flashloan using a non contract address as receiver (revert expected)', async () => {
|
it('tries to take a flashloan using a non contract address as receiver (revert expected)', async () => {
|
||||||
const {pool, deployer, weth} = testEnv;
|
const {pool, deployer, weth, users} = testEnv;
|
||||||
|
const caller = users[1];
|
||||||
|
|
||||||
await expect(
|
await expect(
|
||||||
pool.flashLoan(deployer.address, [weth.address], ['1000000000000000000'], 2, '0x10', '0')
|
pool.flashLoan(deployer.address, [weth.address], ['1000000000000000000'], 2, caller.address, '0x10', '0')
|
||||||
).to.be.reverted;
|
).to.be.reverted;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -242,6 +252,7 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => {
|
||||||
[usdc.address],
|
[usdc.address],
|
||||||
[flashloanAmount],
|
[flashloanAmount],
|
||||||
0,
|
0,
|
||||||
|
_mockFlashLoanReceiver.address,
|
||||||
'0x10',
|
'0x10',
|
||||||
'0'
|
'0'
|
||||||
);
|
);
|
||||||
|
@ -284,6 +295,7 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => {
|
||||||
[usdc.address],
|
[usdc.address],
|
||||||
[flashloanAmount],
|
[flashloanAmount],
|
||||||
2,
|
2,
|
||||||
|
caller.address,
|
||||||
'0x10',
|
'0x10',
|
||||||
'0'
|
'0'
|
||||||
)
|
)
|
||||||
|
@ -309,7 +321,7 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => {
|
||||||
|
|
||||||
await pool
|
await pool
|
||||||
.connect(caller.signer)
|
.connect(caller.signer)
|
||||||
.flashLoan(_mockFlashLoanReceiver.address, [usdc.address], [flashloanAmount], 2, '0x10', '0');
|
.flashLoan(_mockFlashLoanReceiver.address, [usdc.address], [flashloanAmount], 2, caller.address, '0x10', '0');
|
||||||
const {variableDebtTokenAddress} = await helpersContract.getReserveTokensAddresses(
|
const {variableDebtTokenAddress} = await helpersContract.getReserveTokensAddresses(
|
||||||
usdc.address
|
usdc.address
|
||||||
);
|
);
|
||||||
|
@ -344,7 +356,15 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => {
|
||||||
await expect(
|
await expect(
|
||||||
pool
|
pool
|
||||||
.connect(caller.signer)
|
.connect(caller.signer)
|
||||||
.flashLoan(_mockFlashLoanReceiver.address, [weth.address], [flashAmount], 0, '0x10', '0')
|
.flashLoan(
|
||||||
|
_mockFlashLoanReceiver.address,
|
||||||
|
[weth.address],
|
||||||
|
[flashAmount],
|
||||||
|
0,
|
||||||
|
caller.address,
|
||||||
|
'0x10',
|
||||||
|
'0'
|
||||||
|
)
|
||||||
).to.be.revertedWith(SAFEERC20_LOWLEVEL_CALL);
|
).to.be.revertedWith(SAFEERC20_LOWLEVEL_CALL);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -359,7 +379,15 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => {
|
||||||
|
|
||||||
await pool
|
await pool
|
||||||
.connect(caller.signer)
|
.connect(caller.signer)
|
||||||
.flashLoan(_mockFlashLoanReceiver.address, [weth.address], [flashAmount], 1, '0x10', '0');
|
.flashLoan(
|
||||||
|
_mockFlashLoanReceiver.address,
|
||||||
|
[weth.address],
|
||||||
|
[flashAmount],
|
||||||
|
1,
|
||||||
|
caller.address,
|
||||||
|
'0x10',
|
||||||
|
'0'
|
||||||
|
);
|
||||||
|
|
||||||
const {stableDebtTokenAddress} = await helpersContract.getReserveTokensAddresses(weth.address);
|
const {stableDebtTokenAddress} = await helpersContract.getReserveTokensAddresses(weth.address);
|
||||||
|
|
||||||
|
@ -372,4 +400,82 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => {
|
||||||
|
|
||||||
expect(callerDebt.toString()).to.be.equal('800000000000000000', 'Invalid user debt');
|
expect(callerDebt.toString()).to.be.equal('800000000000000000', 'Invalid user debt');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('Caller takes a WETH flashloan with mode = 1 onBehalfOf user without allowance', async () => {
|
||||||
|
const {dai, pool, weth, users, helpersContract} = testEnv;
|
||||||
|
|
||||||
|
const caller = users[5];
|
||||||
|
const onBehalfOf = users[4];
|
||||||
|
|
||||||
|
// Deposit 1000 dai for onBehalfOf user
|
||||||
|
await dai.connect(onBehalfOf.signer).mint(await convertToCurrencyDecimals(dai.address, '1000'));
|
||||||
|
|
||||||
|
await dai.connect(onBehalfOf.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL);
|
||||||
|
|
||||||
|
const amountToDeposit = await convertToCurrencyDecimals(dai.address, '1000');
|
||||||
|
|
||||||
|
await pool
|
||||||
|
.connect(onBehalfOf.signer)
|
||||||
|
.deposit(dai.address, amountToDeposit, onBehalfOf.address, '0');
|
||||||
|
|
||||||
|
const flashAmount = ethers.utils.parseEther('0.8');
|
||||||
|
|
||||||
|
await _mockFlashLoanReceiver.setFailExecutionTransfer(true);
|
||||||
|
|
||||||
|
await expect(
|
||||||
|
pool
|
||||||
|
.connect(caller.signer)
|
||||||
|
.flashLoan(
|
||||||
|
_mockFlashLoanReceiver.address,
|
||||||
|
[weth.address],
|
||||||
|
[flashAmount],
|
||||||
|
1,
|
||||||
|
onBehalfOf.address,
|
||||||
|
'0x10',
|
||||||
|
'0'
|
||||||
|
)
|
||||||
|
).to.be.revertedWith(BORROW_ALLOWANCE_ARE_NOT_ENOUGH);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Caller takes a WETH flashloan with mode = 1 onBehalfOf user with allowance. A loan for onBehalfOf is creatd.', async () => {
|
||||||
|
const {dai, pool, weth, users, helpersContract} = testEnv;
|
||||||
|
|
||||||
|
const caller = users[5];
|
||||||
|
const onBehalfOf = users[4];
|
||||||
|
|
||||||
|
const flashAmount = ethers.utils.parseEther('0.8');
|
||||||
|
|
||||||
|
// Deposited for onBehalfOf user already, delegate borrow allowance
|
||||||
|
await pool
|
||||||
|
.connect(onBehalfOf.signer)
|
||||||
|
.delegateBorrowAllowance(weth.address, caller.address, 1, flashAmount);
|
||||||
|
|
||||||
|
await _mockFlashLoanReceiver.setFailExecutionTransfer(true);
|
||||||
|
|
||||||
|
await pool
|
||||||
|
.connect(caller.signer)
|
||||||
|
.flashLoan(
|
||||||
|
_mockFlashLoanReceiver.address,
|
||||||
|
[weth.address],
|
||||||
|
[flashAmount],
|
||||||
|
1,
|
||||||
|
onBehalfOf.address,
|
||||||
|
'0x10',
|
||||||
|
'0'
|
||||||
|
);
|
||||||
|
|
||||||
|
const {stableDebtTokenAddress} = await helpersContract.getReserveTokensAddresses(weth.address);
|
||||||
|
|
||||||
|
const wethDebtToken = await getContract<StableDebtToken>(
|
||||||
|
eContractid.VariableDebtToken,
|
||||||
|
stableDebtTokenAddress
|
||||||
|
);
|
||||||
|
|
||||||
|
const onBehalfOfDebt = await wethDebtToken.balanceOf(onBehalfOf.address);
|
||||||
|
|
||||||
|
expect(onBehalfOfDebt.toString()).to.be.equal(
|
||||||
|
'800000000000000000',
|
||||||
|
'Invalid onBehalfOf user debt'
|
||||||
|
);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -187,7 +187,7 @@ makeSuite('Pausable Pool', (testEnv: TestEnv) => {
|
||||||
await expect(
|
await expect(
|
||||||
pool
|
pool
|
||||||
.connect(caller.signer)
|
.connect(caller.signer)
|
||||||
.flashLoan(_mockFlashLoanReceiver.address, [weth.address], [flashAmount], 1, '0x10', '0')
|
.flashLoan(_mockFlashLoanReceiver.address, [weth.address], [flashAmount], 1, caller.address, '0x10', '0')
|
||||||
).revertedWith(IS_PAUSED);
|
).revertedWith(IS_PAUSED);
|
||||||
|
|
||||||
// Unpause pool
|
// Unpause pool
|
||||||
|
|
Loading…
Reference in New Issue
Block a user