mirror of
https://github.com/Instadapp/aave-protocol-v2.git
synced 2024-07-29 21:47:30 +00:00
Merge branch 'feat/transferToReserve-removal' into '1-universal-token'
Transfer funds related logic of the LendingPool from Core See merge request aave-tech/protocol-v2!2
This commit is contained in:
commit
5e52e8ced0
|
@ -36,7 +36,7 @@ contract MockKyberProxy {
|
||||||
) external payable returns (uint256) {
|
) external payable returns (uint256) {
|
||||||
require(tokenToBurn.mint(1 ether), "TRADE_WITH_HINT. Reverted mint()");
|
require(tokenToBurn.mint(1 ether), "TRADE_WITH_HINT. Reverted mint()");
|
||||||
if (!_fromToken.isETH()) {
|
if (!_fromToken.isETH()) {
|
||||||
_fromToken.universalTransferFrom(msg.sender, address(this), _amount, false);
|
_fromToken.universalTransferFromSenderToThis(_amount, true);
|
||||||
}
|
}
|
||||||
tokenToBurn.universalTransfer(msg.sender, 1 ether);
|
tokenToBurn.universalTransfer(msg.sender, 1 ether);
|
||||||
return 1 ether;
|
return 1 ether;
|
||||||
|
|
|
@ -55,7 +55,7 @@ contract MockOneSplit is IOneSplit {
|
||||||
) public override payable {
|
) public override payable {
|
||||||
require(tokenToBurn.mint(10000 ether), "TRADE_WITH_HINT. Reverted mint()");
|
require(tokenToBurn.mint(10000 ether), "TRADE_WITH_HINT. Reverted mint()");
|
||||||
if (!fromToken.isETH()) {
|
if (!fromToken.isETH()) {
|
||||||
fromToken.universalTransferFrom(msg.sender, address(this), amount, false);
|
fromToken.universalTransferFromSenderToThis(amount, true);
|
||||||
}
|
}
|
||||||
tokenToBurn.universalTransfer(msg.sender, 10000 ether);
|
tokenToBurn.universalTransfer(msg.sender, 10000 ether);
|
||||||
}
|
}
|
||||||
|
|
|
@ -315,8 +315,14 @@ contract LendingPool is ReentrancyGuard, VersionedInitializable {
|
||||||
//minting AToken to user 1:1 with the specific exchange rate
|
//minting AToken to user 1:1 with the specific exchange rate
|
||||||
aToken.mintOnDeposit(msg.sender, _amount);
|
aToken.mintOnDeposit(msg.sender, _amount);
|
||||||
|
|
||||||
//transfer to the core contract
|
//transfer to the pool
|
||||||
core.transferToReserve{value: msg.value}(_reserve, msg.sender, _amount);
|
if (!IERC20(_reserve).isETH()) { //TODO: review needed, most probably we can remove it
|
||||||
|
require(
|
||||||
|
msg.value == 0,
|
||||||
|
"User is sending ETH along with the ERC20 transfer."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
IERC20(_reserve).universalTransferFromSenderToThis(_amount, true);
|
||||||
|
|
||||||
//solium-disable-next-line
|
//solium-disable-next-line
|
||||||
emit Deposit(_reserve, msg.sender, _amount, _referralCode, block.timestamp);
|
emit Deposit(_reserve, msg.sender, _amount, _referralCode, block.timestamp);
|
||||||
|
@ -342,7 +348,7 @@ contract LendingPool is ReentrancyGuard, VersionedInitializable {
|
||||||
onlyActiveReserve(_reserve)
|
onlyActiveReserve(_reserve)
|
||||||
onlyAmountGreaterThanZero(_amount)
|
onlyAmountGreaterThanZero(_amount)
|
||||||
{
|
{
|
||||||
uint256 currentAvailableLiquidity = core.getReserveAvailableLiquidity(_reserve);
|
uint256 currentAvailableLiquidity = IERC20(_reserve).universalBalanceOf(address(this));
|
||||||
require(
|
require(
|
||||||
currentAvailableLiquidity >= _amount,
|
currentAvailableLiquidity >= _amount,
|
||||||
"There is not enough liquidity available to redeem"
|
"There is not enough liquidity available to redeem"
|
||||||
|
@ -350,7 +356,7 @@ contract LendingPool is ReentrancyGuard, VersionedInitializable {
|
||||||
|
|
||||||
core.updateStateOnRedeem(_reserve, _user, _amount, _aTokenBalanceAfterRedeem == 0);
|
core.updateStateOnRedeem(_reserve, _user, _amount, _aTokenBalanceAfterRedeem == 0);
|
||||||
|
|
||||||
core.transferToUser(_reserve, _user, _amount);
|
IERC20(_reserve).universalTransfer(_user, _amount);
|
||||||
|
|
||||||
//solium-disable-next-line
|
//solium-disable-next-line
|
||||||
emit RedeemUnderlying(_reserve, _user, _amount, block.timestamp);
|
emit RedeemUnderlying(_reserve, _user, _amount, block.timestamp);
|
||||||
|
@ -415,7 +421,7 @@ contract LendingPool is ReentrancyGuard, VersionedInitializable {
|
||||||
vars.rateMode = CoreLibrary.InterestRateMode(_interestRateMode);
|
vars.rateMode = CoreLibrary.InterestRateMode(_interestRateMode);
|
||||||
|
|
||||||
//check that the amount is available in the reserve
|
//check that the amount is available in the reserve
|
||||||
vars.availableLiquidity = core.getReserveAvailableLiquidity(_reserve);
|
vars.availableLiquidity = IERC20(_reserve).universalBalanceOf(address(this)); // TODO: review needed, most probably useless
|
||||||
|
|
||||||
require(
|
require(
|
||||||
vars.availableLiquidity >= _amount,
|
vars.availableLiquidity >= _amount,
|
||||||
|
@ -496,7 +502,7 @@ contract LendingPool is ReentrancyGuard, VersionedInitializable {
|
||||||
);
|
);
|
||||||
|
|
||||||
//if we reached this point, we can transfer
|
//if we reached this point, we can transfer
|
||||||
core.transferToUser(_reserve, msg.sender, _amount);
|
IERC20(_reserve).universalTransfer(msg.sender, _amount);
|
||||||
|
|
||||||
emit Borrow(
|
emit Borrow(
|
||||||
_reserve,
|
_reserve,
|
||||||
|
@ -566,7 +572,7 @@ contract LendingPool is ReentrancyGuard, VersionedInitializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
require(
|
require(
|
||||||
!vars.isETH || msg.value >= vars.paybackAmount,
|
(!vars.isETH && msg.value == 0) || msg.value >= vars.paybackAmount,
|
||||||
"Invalid msg.value sent for the repayment"
|
"Invalid msg.value sent for the repayment"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -581,11 +587,11 @@ contract LendingPool is ReentrancyGuard, VersionedInitializable {
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
|
|
||||||
core.transferToFeeCollectionAddress{ value: vars.isETH ? vars.paybackAmount : 0 }(
|
IERC20(_reserve).universalTransferFrom(
|
||||||
_reserve,
|
|
||||||
_onBehalfOf,
|
_onBehalfOf,
|
||||||
|
addressesProvider.getTokenDistributor(),
|
||||||
vars.paybackAmount,
|
vars.paybackAmount,
|
||||||
addressesProvider.getTokenDistributor()
|
false
|
||||||
);
|
);
|
||||||
|
|
||||||
emit Repay(
|
emit Repay(
|
||||||
|
@ -613,23 +619,26 @@ contract LendingPool is ReentrancyGuard, VersionedInitializable {
|
||||||
);
|
);
|
||||||
|
|
||||||
//if the user didn't repay the origination fee, transfer the fee to the fee collection address
|
//if the user didn't repay the origination fee, transfer the fee to the fee collection address
|
||||||
if(vars.originationFee > 0) {
|
if (vars.originationFee > 0) {
|
||||||
core.transferToFeeCollectionAddress{ value: vars.isETH ? vars.originationFee : 0 }(
|
IERC20(_reserve).universalTransferFrom(
|
||||||
_reserve,
|
|
||||||
_onBehalfOf,
|
_onBehalfOf,
|
||||||
|
addressesProvider.getTokenDistributor(),
|
||||||
vars.originationFee,
|
vars.originationFee,
|
||||||
addressesProvider.getTokenDistributor()
|
false
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
//sending the total msg.value if the transfer is ETH.
|
IERC20(_reserve).universalTransferFromSenderToThis(vars.paybackAmountMinusFees, false);
|
||||||
//the transferToReserve() function will take care of sending the
|
|
||||||
//excess ETH back to the caller
|
if (vars.isETH) {
|
||||||
core.transferToReserve{ value: vars.isETH ? msg.value.sub(vars.originationFee) : 0 }(
|
uint256 exceedAmount = msg.value
|
||||||
_reserve,
|
.sub(vars.originationFee)
|
||||||
msg.sender,
|
.sub(vars.paybackAmountMinusFees);
|
||||||
vars.paybackAmountMinusFees
|
//send excess ETH back to the caller if needed
|
||||||
);
|
if (exceedAmount > 0) {
|
||||||
|
IERC20(_reserve).universalTransfer(msg.sender, exceedAmount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
emit Repay(
|
emit Repay(
|
||||||
_reserve,
|
_reserve,
|
||||||
|
@ -872,10 +881,8 @@ contract LendingPool is ReentrancyGuard, VersionedInitializable {
|
||||||
//get the FlashLoanReceiver instance
|
//get the FlashLoanReceiver instance
|
||||||
IFlashLoanReceiver receiver = IFlashLoanReceiver(_receiver);
|
IFlashLoanReceiver receiver = IFlashLoanReceiver(_receiver);
|
||||||
|
|
||||||
address payable userPayable = payable(_receiver);
|
|
||||||
|
|
||||||
//transfer funds to the receiver
|
//transfer funds to the receiver
|
||||||
core.transferToUser(_reserve, userPayable, _amount);
|
IERC20(_reserve).universalTransfer(_receiver, _amount);
|
||||||
|
|
||||||
//execute action of the receiver
|
//execute action of the receiver
|
||||||
receiver.executeOperation(_reserve, _amount, amountFee, _params);
|
receiver.executeOperation(_reserve, _amount, amountFee, _params);
|
||||||
|
@ -888,6 +895,11 @@ contract LendingPool is ReentrancyGuard, VersionedInitializable {
|
||||||
"The actual balance of the protocol is inconsistent"
|
"The actual balance of the protocol is inconsistent"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// transfer protocol fee to the Distributor contract
|
||||||
|
IERC20(_reserve).universalTransfer(
|
||||||
|
addressesProvider.getTokenDistributor(),
|
||||||
|
protocolFee
|
||||||
|
);
|
||||||
core.updateStateOnFlashLoan(
|
core.updateStateOnFlashLoan(
|
||||||
_reserve,
|
_reserve,
|
||||||
availableLiquidityBefore,
|
availableLiquidityBefore,
|
||||||
|
|
|
@ -174,8 +174,6 @@ contract LendingPoolCore is VersionedInitializable {
|
||||||
uint256 _income,
|
uint256 _income,
|
||||||
uint256 _protocolFee
|
uint256 _protocolFee
|
||||||
) external onlyLendingPool {
|
) external onlyLendingPool {
|
||||||
transferFlashLoanProtocolFeeInternal(_reserve, _protocolFee);
|
|
||||||
|
|
||||||
//compounding the cumulated interest
|
//compounding the cumulated interest
|
||||||
reserves[_reserve].updateCumulativeIndexes();
|
reserves[_reserve].updateCumulativeIndexes();
|
||||||
|
|
||||||
|
@ -408,97 +406,6 @@ contract LendingPoolCore is VersionedInitializable {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @dev transfers to the user a specific amount from the reserve.
|
|
||||||
* @param _reserve the address of the reserve where the transfer is happening
|
|
||||||
* @param _user the address of the user receiving the transfer
|
|
||||||
* @param _amount the amount being transferred
|
|
||||||
**/
|
|
||||||
function transferToUser(address _reserve, address payable _user, uint256 _amount)
|
|
||||||
external
|
|
||||||
onlyLendingPool
|
|
||||||
{
|
|
||||||
IERC20(_reserve).universalTransfer(_user, _amount);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @dev transfers the protocol fees to the fees collection address
|
|
||||||
* @param _token the address of the token being transferred
|
|
||||||
* @param _user the address of the user from where the transfer is happening
|
|
||||||
* @param _amount the amount being transferred
|
|
||||||
* @param _feeAddress the fee receiver address
|
|
||||||
**/
|
|
||||||
|
|
||||||
function transferToFeeCollectionAddress(
|
|
||||||
address _token,
|
|
||||||
address _user,
|
|
||||||
uint256 _amount,
|
|
||||||
address _feeAddress
|
|
||||||
) external payable onlyLendingPool {
|
|
||||||
IERC20 token = IERC20(_token);
|
|
||||||
|
|
||||||
if (!token.isETH()) {
|
|
||||||
require(
|
|
||||||
msg.value == 0,
|
|
||||||
"User is sending ETH along with the ERC20 transfer. Check the value attribute of the transaction"
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
require(msg.value >= _amount, "The amount and the value sent to deposit do not match");
|
|
||||||
}
|
|
||||||
IERC20(_token).universalTransferFrom(
|
|
||||||
_user,
|
|
||||||
_feeAddress,
|
|
||||||
_amount,
|
|
||||||
false
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @dev transfers the fees to the fees collection address in the case of liquidation
|
|
||||||
* @param _token the address of the token being transferred
|
|
||||||
* @param _amount the amount being transferred
|
|
||||||
* @param _feeAddress the fee receiver address
|
|
||||||
**/
|
|
||||||
function liquidateFee(
|
|
||||||
address _token,
|
|
||||||
uint256 _amount,
|
|
||||||
address _feeAddress
|
|
||||||
) external payable onlyLendingPool {
|
|
||||||
require(
|
|
||||||
msg.value == 0,
|
|
||||||
"Fee liquidation does not require any transfer of value"
|
|
||||||
);
|
|
||||||
|
|
||||||
IERC20(_token).universalTransfer(_feeAddress, _amount);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @dev transfers an amount from a user to the destination reserve
|
|
||||||
* @param _reserve the address of the reserve where the amount is being transferred
|
|
||||||
* @param _user the address of the user from where the transfer is happening
|
|
||||||
* @param _amount the amount being transferred
|
|
||||||
**/
|
|
||||||
function transferToReserve(address _reserve, address payable _user, uint256 _amount)
|
|
||||||
external
|
|
||||||
payable
|
|
||||||
onlyLendingPool
|
|
||||||
{
|
|
||||||
IERC20 reserve = IERC20(_reserve);
|
|
||||||
|
|
||||||
if (!reserve.isETH()) {
|
|
||||||
require(
|
|
||||||
msg.value == 0,
|
|
||||||
"User is sending ETH along with the ERC20 transfer."
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
require(
|
|
||||||
msg.value >= _amount,
|
|
||||||
"The amount and the value sent to deposit do not match"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
reserve.universalTransferFrom(_user, address(this), _amount, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @notice data access functions
|
* @notice data access functions
|
||||||
**/
|
**/
|
||||||
|
@ -594,15 +501,6 @@ contract LendingPoolCore is VersionedInitializable {
|
||||||
return reserve.aTokenAddress;
|
return reserve.aTokenAddress;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @dev gets the available liquidity in the reserve. The available liquidity is the balance of the core contract
|
|
||||||
* @param _reserve the reserve address
|
|
||||||
* @return the available liquidity
|
|
||||||
**/
|
|
||||||
function getReserveAvailableLiquidity(address _reserve) public view returns (uint256) {
|
|
||||||
return IERC20(_reserve).universalBalanceOf(address(this));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev gets the total liquidity in the reserve. The total liquidity is the balance of the core contract + total borrows
|
* @dev gets the total liquidity in the reserve. The total liquidity is the balance of the core contract + total borrows
|
||||||
* @param _reserve the reserve address
|
* @param _reserve the reserve address
|
||||||
|
@ -610,7 +508,10 @@ contract LendingPoolCore is VersionedInitializable {
|
||||||
**/
|
**/
|
||||||
function getReserveTotalLiquidity(address _reserve) public view returns (uint256) {
|
function getReserveTotalLiquidity(address _reserve) public view returns (uint256) {
|
||||||
CoreLibrary.ReserveData storage reserve = reserves[_reserve];
|
CoreLibrary.ReserveData storage reserve = reserves[_reserve];
|
||||||
return getReserveAvailableLiquidity(_reserve).add(reserve.getTotalBorrows());
|
|
||||||
|
return IERC20(_reserve)
|
||||||
|
.universalBalanceOf(addressesProvider.getLendingPool())
|
||||||
|
.add(reserve.getTotalBorrows());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -877,8 +778,9 @@ contract LendingPoolCore is VersionedInitializable {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint256 availableLiquidity = getReserveAvailableLiquidity(_reserve);
|
uint256 availableLiquidity = IERC20(_reserve).universalBalanceOf(
|
||||||
|
addressesProvider.getLendingPool()
|
||||||
|
);
|
||||||
return totalBorrows.rayDiv(availableLiquidity.add(totalBorrows));
|
return totalBorrows.rayDiv(availableLiquidity.add(totalBorrows));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1707,14 +1609,15 @@ contract LendingPoolCore is VersionedInitializable {
|
||||||
CoreLibrary.ReserveData storage reserve = reserves[_reserve];
|
CoreLibrary.ReserveData storage reserve = reserves[_reserve];
|
||||||
|
|
||||||
uint256 currentAvgStableRate = reserve.currentAverageStableBorrowRate;
|
uint256 currentAvgStableRate = reserve.currentAverageStableBorrowRate;
|
||||||
|
uint256 avialableLiquidity = IERC20(_reserve).universalBalanceOf(addressesProvider.getLendingPool())
|
||||||
|
.add(_liquidityAdded)
|
||||||
|
.sub(_liquidityTaken);
|
||||||
|
|
||||||
(uint256 newLiquidityRate, uint256 newStableRate, uint256 newVariableRate) = IReserveInterestRateStrategy(
|
(uint256 newLiquidityRate, uint256 newStableRate, uint256 newVariableRate) = IReserveInterestRateStrategy(
|
||||||
reserve
|
reserve.interestRateStrategyAddress
|
||||||
.interestRateStrategyAddress
|
).calculateInterestRates(
|
||||||
)
|
|
||||||
.calculateInterestRates(
|
|
||||||
_reserve,
|
_reserve,
|
||||||
getReserveAvailableLiquidity(_reserve).add(_liquidityAdded).sub(_liquidityTaken),
|
avialableLiquidity,
|
||||||
reserve.totalBorrowsStable,
|
reserve.totalBorrowsStable,
|
||||||
reserve.totalBorrowsVariable,
|
reserve.totalBorrowsVariable,
|
||||||
currentAvgStableRate
|
currentAvgStableRate
|
||||||
|
@ -1738,19 +1641,6 @@ contract LendingPoolCore is VersionedInitializable {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @dev transfers to the protocol fees of a flashloan to the fees collection address
|
|
||||||
* @param _token the address of the token being transferred
|
|
||||||
* @param _amount the amount being transferred
|
|
||||||
**/
|
|
||||||
|
|
||||||
function transferFlashLoanProtocolFeeInternal(address _token, uint256 _amount) internal {
|
|
||||||
IERC20(_token).universalTransfer(
|
|
||||||
addressesProvider.getTokenDistributor(),
|
|
||||||
_amount
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev updates the internal configuration of the core
|
* @dev updates the internal configuration of the core
|
||||||
**/
|
**/
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
pragma solidity ^0.6.8;
|
pragma solidity ^0.6.8;
|
||||||
|
|
||||||
import "@openzeppelin/contracts/math/SafeMath.sol";
|
import "@openzeppelin/contracts/math/SafeMath.sol";
|
||||||
|
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
||||||
import "../libraries/openzeppelin-upgradeability/VersionedInitializable.sol";
|
import "../libraries/openzeppelin-upgradeability/VersionedInitializable.sol";
|
||||||
|
|
||||||
import "../libraries/CoreLibrary.sol";
|
import "../libraries/CoreLibrary.sol";
|
||||||
|
@ -10,6 +11,7 @@ import "../libraries/WadRayMath.sol";
|
||||||
import "../interfaces/IPriceOracleGetter.sol";
|
import "../interfaces/IPriceOracleGetter.sol";
|
||||||
import "../interfaces/IFeeProvider.sol";
|
import "../interfaces/IFeeProvider.sol";
|
||||||
import "../tokenization/AToken.sol";
|
import "../tokenization/AToken.sol";
|
||||||
|
import "../libraries/UniversalERC20.sol";
|
||||||
|
|
||||||
import "./LendingPoolCore.sol";
|
import "./LendingPoolCore.sol";
|
||||||
|
|
||||||
|
@ -22,6 +24,7 @@ import "./LendingPoolCore.sol";
|
||||||
contract LendingPoolDataProvider is VersionedInitializable {
|
contract LendingPoolDataProvider is VersionedInitializable {
|
||||||
using SafeMath for uint256;
|
using SafeMath for uint256;
|
||||||
using WadRayMath for uint256;
|
using WadRayMath for uint256;
|
||||||
|
using UniversalERC20 for IERC20;
|
||||||
|
|
||||||
LendingPoolCore public core;
|
LendingPoolCore public core;
|
||||||
LendingPoolAddressesProvider public addressesProvider;
|
LendingPoolAddressesProvider public addressesProvider;
|
||||||
|
@ -395,7 +398,7 @@ contract LendingPoolDataProvider is VersionedInitializable {
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
totalLiquidity = core.getReserveTotalLiquidity(_reserve);
|
totalLiquidity = core.getReserveTotalLiquidity(_reserve);
|
||||||
availableLiquidity = core.getReserveAvailableLiquidity(_reserve);
|
availableLiquidity = IERC20(_reserve).universalBalanceOf(addressesProvider.getLendingPool());
|
||||||
totalBorrowsStable = core.getReserveTotalBorrowsStable(_reserve);
|
totalBorrowsStable = core.getReserveTotalBorrowsStable(_reserve);
|
||||||
totalBorrowsVariable = core.getReserveTotalBorrowsVariable(_reserve);
|
totalBorrowsVariable = core.getReserveTotalBorrowsVariable(_reserve);
|
||||||
liquidityRate = core.getReserveCurrentLiquidityRate(_reserve);
|
liquidityRate = core.getReserveCurrentLiquidityRate(_reserve);
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
pragma solidity ^0.6.8;
|
pragma solidity ^0.6.8;
|
||||||
|
|
||||||
import "@openzeppelin/contracts/math/SafeMath.sol";
|
import "@openzeppelin/contracts/math/SafeMath.sol";
|
||||||
|
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
||||||
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
|
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
|
||||||
import "@openzeppelin/contracts/utils/Address.sol";
|
import "@openzeppelin/contracts/utils/Address.sol";
|
||||||
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
|
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
|
||||||
|
@ -15,6 +16,7 @@ import "../libraries/WadRayMath.sol";
|
||||||
import "./LendingPoolCore.sol";
|
import "./LendingPoolCore.sol";
|
||||||
import "./LendingPoolDataProvider.sol";
|
import "./LendingPoolDataProvider.sol";
|
||||||
import "../interfaces/IPriceOracleGetter.sol";
|
import "../interfaces/IPriceOracleGetter.sol";
|
||||||
|
import "../libraries/UniversalERC20.sol";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @title LendingPoolLiquidationManager contract
|
* @title LendingPoolLiquidationManager contract
|
||||||
|
@ -25,6 +27,7 @@ contract LendingPoolLiquidationManager is ReentrancyGuard, VersionedInitializabl
|
||||||
using SafeMath for uint256;
|
using SafeMath for uint256;
|
||||||
using WadRayMath for uint256;
|
using WadRayMath for uint256;
|
||||||
using Address for address;
|
using Address for address;
|
||||||
|
using UniversalERC20 for IERC20;
|
||||||
|
|
||||||
LendingPoolAddressesProvider public addressesProvider;
|
LendingPoolAddressesProvider public addressesProvider;
|
||||||
LendingPoolCore core;
|
LendingPoolCore core;
|
||||||
|
@ -216,7 +219,7 @@ contract LendingPoolLiquidationManager is ReentrancyGuard, VersionedInitializabl
|
||||||
|
|
||||||
//if liquidator reclaims the underlying asset, we make sure there is enough available collateral in the reserve
|
//if liquidator reclaims the underlying asset, we make sure there is enough available collateral in the reserve
|
||||||
if (!_receiveAToken) {
|
if (!_receiveAToken) {
|
||||||
uint256 currentAvailableCollateral = core.getReserveAvailableLiquidity(_collateral);
|
uint256 currentAvailableCollateral = IERC20(_collateral).universalBalanceOf(address(this));
|
||||||
if (currentAvailableCollateral < maxCollateralToLiquidate) {
|
if (currentAvailableCollateral < maxCollateralToLiquidate) {
|
||||||
return (
|
return (
|
||||||
uint256(LiquidationErrors.NOT_ENOUGH_LIQUIDITY),
|
uint256(LiquidationErrors.NOT_ENOUGH_LIQUIDITY),
|
||||||
|
@ -246,11 +249,15 @@ contract LendingPoolLiquidationManager is ReentrancyGuard, VersionedInitializabl
|
||||||
//otherwise receives the underlying asset
|
//otherwise receives the underlying asset
|
||||||
//burn the equivalent amount of atoken
|
//burn the equivalent amount of atoken
|
||||||
collateralAtoken.burnOnLiquidation(_user, maxCollateralToLiquidate);
|
collateralAtoken.burnOnLiquidation(_user, maxCollateralToLiquidate);
|
||||||
core.transferToUser(_collateral, msg.sender, maxCollateralToLiquidate);
|
// because liquidate function executed as delegated call this will be LendingPool contract address
|
||||||
|
// and funds will be transferred from there
|
||||||
|
IERC20(_collateral).universalTransfer(msg.sender, maxCollateralToLiquidate);
|
||||||
}
|
}
|
||||||
|
|
||||||
//transfers the principal currency to the pool
|
//transfers the principal currency to the pool
|
||||||
core.transferToReserve{value: msg.value}(_reserve, msg.sender, vars.actualAmountToLiquidate);
|
IERC20(_reserve).universalTransferFromSenderToThis(
|
||||||
|
vars.actualAmountToLiquidate, true
|
||||||
|
);
|
||||||
|
|
||||||
if (vars.feeLiquidated > 0) {
|
if (vars.feeLiquidated > 0) {
|
||||||
//if there is enough collateral to liquidate the fee, first transfer burn an equivalent amount of
|
//if there is enough collateral to liquidate the fee, first transfer burn an equivalent amount of
|
||||||
|
@ -258,10 +265,9 @@ contract LendingPoolLiquidationManager is ReentrancyGuard, VersionedInitializabl
|
||||||
collateralAtoken.burnOnLiquidation(_user, vars.liquidatedCollateralForFee);
|
collateralAtoken.burnOnLiquidation(_user, vars.liquidatedCollateralForFee);
|
||||||
|
|
||||||
//then liquidate the fee by transferring it to the fee collection address
|
//then liquidate the fee by transferring it to the fee collection address
|
||||||
core.liquidateFee(
|
IERC20(_collateral).universalTransfer(
|
||||||
_collateral,
|
addressesProvider.getTokenDistributor(),
|
||||||
vars.liquidatedCollateralForFee,
|
vars.liquidatedCollateralForFee
|
||||||
addressesProvider.getTokenDistributor()
|
|
||||||
);
|
);
|
||||||
|
|
||||||
emit OriginationFeeLiquidated(
|
emit OriginationFeeLiquidated(
|
||||||
|
|
|
@ -99,7 +99,7 @@ library UniversalERC20 {
|
||||||
* @param token underlying asset address
|
* @param token underlying asset address
|
||||||
* @param amount to move
|
* @param amount to move
|
||||||
**/
|
**/
|
||||||
function universalTransferFromSenderToThis(IERC20 token, uint256 amount)
|
function universalTransferFromSenderToThis(IERC20 token, uint256 amount, bool returnExcess)
|
||||||
internal
|
internal
|
||||||
{
|
{
|
||||||
if (amount == 0) {
|
if (amount == 0) {
|
||||||
|
@ -107,7 +107,7 @@ library UniversalERC20 {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isETH(token)) {
|
if (isETH(token)) {
|
||||||
if (msg.value > amount) {
|
if (msg.value > amount && returnExcess) {
|
||||||
// Return remainder if exist
|
// Return remainder if exist
|
||||||
(bool result, ) = msg.sender.call{
|
(bool result, ) = msg.sender.call{
|
||||||
value: msg.value.sub(amount),
|
value: msg.value.sub(amount),
|
||||||
|
|
Loading…
Reference in New Issue
Block a user