- Moved index update on flashLoan() to before the executeOperation.

- Refactor to remove try..catch.
- Change on _executeBorrow() to not consider liquidityTaken when coming from flash loan.
This commit is contained in:
eboado 2020-08-28 16:44:14 +02:00
parent 5435620e41
commit e0c27fef3f
2 changed files with 53 additions and 50 deletions
contracts/lendingpool
test

View File

@ -220,7 +220,7 @@ contract LendingPool is VersionedInitializable, ILendingPool {
IVariableDebtToken(reserve.variableDebtTokenAddress).mint(vars.user, vars.amount);
}
reserve.updateInterestRates(vars.asset, 0, vars.amount);
reserve.updateInterestRates(vars.asset, 0, (vars.releaseUnderlying) ? vars.amount : 0);
if (!userConfig.isBorrowing(reserve.index)) {
userConfig.setBorrowing(reserve.index, true);
@ -453,7 +453,7 @@ contract LendingPool is VersionedInitializable, ILendingPool {
uint256 amountPlusPremiumInETH;
uint256 receiverBalance;
uint256 receiverAllowance;
uint256 balanceToPull;
uint256 availableBalance;
uint256 assetPrice;
IFlashLoanReceiver receiver;
address aTokenAddress;
@ -484,72 +484,76 @@ contract LendingPool is VersionedInitializable, ILendingPool {
vars.aTokenAddress = reserve.aTokenAddress;
//calculate amount fee
vars.premium = amount.mul(FLASHLOAN_PREMIUM_TOTAL).div(10000);
require(vars.premium > 0, 'The requested amount is too small for a FlashLoan.');
//get the FlashLoanReceiver instance
vars.receiver = IFlashLoanReceiver(receiverAddress);
// Update of the indexes until the current moment
reserve.updateCumulativeIndexesAndTimestamp();
//transfer funds to the receiver
IAToken(vars.aTokenAddress).transferUnderlyingTo(receiverAddress, amount);
//execute action of the receiver
vars.receiver.executeOperation(asset, amount, vars.premium, params);
//compounding the cumulated interest
reserve.updateCumulativeIndexesAndTimestamp();
vars.amountPlusPremium = amount.add(vars.premium);
//transfer from the receiver the amount plus the fee
try IERC20(asset).transferFrom(receiverAddress, vars.aTokenAddress, vars.amountPlusPremium) {
//if the transfer succeeded, the executor has repaid the flashloan.
//the fee is compounded into the reserve
if (debtType == 0) { // To not fetch balance/allowance if no debt needs to be opened
IERC20(asset).transferFrom(receiverAddress, vars.aTokenAddress, vars.amountPlusPremium);
reserve.cumulateToLiquidityIndex(IERC20(vars.aTokenAddress).totalSupply(), vars.premium);
//refresh interest rates
reserve.updateInterestRates(asset, vars.premium, 0);
emit FlashLoan(receiverAddress, asset, amount, vars.premium, referralCode);
} catch (bytes memory reason) {
if (debtType == 1 || debtType == 2) {
// If the transfer didn't succeed, the receiver either didn't return the funds, or didn't approve the transfer.
// We will try to pull all the available funds from the receiver and create a debt position with the rest owed
// if it has collateral enough
vars.receiverBalance = IERC20(asset).balanceOf(receiverAddress);
vars.receiverAllowance = IERC20(asset).allowance(receiverAddress, address(this));
vars.balanceToPull = (vars.receiverBalance > vars.receiverAllowance)
? vars.receiverAllowance
: vars.receiverBalance;
if (vars.balanceToPull > 0) {
IERC20(asset).transferFrom(receiverAddress, vars.aTokenAddress, vars.balanceToPull);
reserve.cumulateToLiquidityIndex(
IERC20(vars.aTokenAddress).totalSupply(),
(vars.balanceToPull > vars.premium) ? vars.premium : vars.balanceToPull
);
reserve.updateInterestRates(
asset,
(vars.balanceToPull > vars.premium) ? vars.premium : vars.balanceToPull,
0
);
}
_executeBorrow(
BorrowLocalVars(
asset,
msg.sender,
vars.amountPlusPremium.sub(vars.balanceToPull),
debtType,
false,
referralCode
)
);
} else {
vars.receiverBalance = IERC20(asset).balanceOf(receiverAddress);
vars.receiverAllowance = IERC20(asset).allowance(receiverAddress, address(this));
if (vars.receiverBalance >= vars.amountPlusPremium && vars.receiverAllowance >= vars.amountPlusPremium) {
IERC20(asset).transferFrom(receiverAddress, vars.aTokenAddress, vars.amountPlusPremium);
reserve.cumulateToLiquidityIndex(IERC20(vars.aTokenAddress).totalSupply(), vars.premium);
reserve.updateInterestRates(asset, vars.premium, 0);
} else {
revert(string(reason));
if (debtType == 1 || debtType == 2) {
// If the transfer didn't succeed, the receiver either didn't return the funds, or didn't approve the transfer.
// We will try to pull all the available funds from the receiver and create a debt position with the rest owed
// if it has collateral enough
vars.availableBalance = (vars.receiverBalance > vars.receiverAllowance)
? vars.receiverAllowance
: vars.receiverBalance;
if (vars.availableBalance > 0) {
// If not enough premium, include as premium all the funds available to pull
if (vars.availableBalance < vars.premium) {
vars.premium = vars.availableBalance;
}
IERC20(asset).transferFrom(receiverAddress, vars.aTokenAddress, vars.availableBalance);
reserve.cumulateToLiquidityIndex(
IERC20(vars.aTokenAddress).totalSupply(),
vars.premium
);
reserve.updateInterestRates(
asset,
vars.premium,
0
);
}
_executeBorrow(
BorrowLocalVars(
asset,
msg.sender,
vars.amountPlusPremium.sub(vars.availableBalance),
debtType,
false,
referralCode
)
);
} else {
revert("INSUFFICIENT_FUNDS_TO_PULL");
}
}
}
emit FlashLoan(receiverAddress, asset, amount, vars.premium, referralCode);
}
/**

View File

@ -301,7 +301,6 @@ makeSuite('LendingPool FlashLoan function', (testEnv: TestEnv) => {
await _mockFlashLoanReceiver.setFailExecutionTransfer(false);
await _mockFlashLoanReceiver.setAmountToApprove(flashloanAmount.div(2));
console.log((await _mockFlashLoanReceiver.amountToApprove()).toString());
await pool
.connect(caller.signer)