diff --git a/contracts/interfaces/ILendingPool.sol b/contracts/interfaces/ILendingPool.sol index b14f5cb8..55010304 100644 --- a/contracts/interfaces/ILendingPool.sol +++ b/contracts/interfaces/ILendingPool.sol @@ -29,6 +29,13 @@ interface ILendingPool { **/ event Withdraw(address indexed reserve, address indexed user, uint256 amount); + event BorrowAllowanceDelegated( + address indexed asset, + address indexed fromUser, + address indexed toUser, + uint256 interestRateMode, + uint256 amount + ); /** * @dev emitted on borrow * @param reserve the address of the reserve @@ -40,7 +47,8 @@ interface ILendingPool { **/ event Borrow( address indexed reserve, - address indexed user, + address user, + address indexed onBehalfOf, uint256 amount, uint256 borrowRateMode, uint256 borrowRate, @@ -151,6 +159,27 @@ interface ILendingPool { **/ function withdraw(address reserve, uint256 amount) external; + /** + * @dev Sets allowance to borrow on a certain type of debt asset for a certain user address + * @param asset The underlying asset of the debt token + * @param user The user to give allowance to + * @param interestRateMode Type of debt: 1 for stable, 2 for variable + * @param amount Allowance amount to borrow + **/ + function delegateBorrowAllowance( + address asset, + address user, + uint256 interestRateMode, + uint256 amount + ) external; + + function getBorrowAllowance( + address fromUser, + address toUser, + address asset, + uint256 interestRateMode + ) external view returns (uint256); + /** * @dev Allows users to borrow a specific amount of the reserve currency, provided that the borrower * already deposited enough collateral. @@ -162,7 +191,8 @@ interface ILendingPool { address reserve, uint256 amount, uint256 interestRateMode, - uint16 referralCode + uint16 referralCode, + address onBehalfOf ) external; /** diff --git a/contracts/lendingpool/LendingPool.sol b/contracts/lendingpool/LendingPool.sol index 814230ef..6c3eef51 100644 --- a/contracts/lendingpool/LendingPool.sol +++ b/contracts/lendingpool/LendingPool.sol @@ -48,6 +48,8 @@ contract LendingPool is VersionedInitializable, ILendingPool { mapping(address => ReserveLogic.ReserveData) internal _reserves; mapping(address => UserConfiguration.Map) internal _usersConfig; + // debt token address => user who gives allowance => user who receives allowance => amount + mapping(address => mapping(address => mapping(address => uint256))) internal _borrowAllowance; address[] internal _reservesList; @@ -159,6 +161,35 @@ contract LendingPool is VersionedInitializable, ILendingPool { emit Withdraw(asset, msg.sender, amount); } + function getBorrowAllowance( + address fromUser, + address toUser, + address asset, + uint256 interestRateMode + ) external override view returns (uint256) { + return + _borrowAllowance[_reserves[asset].getDebtTokenAddress(interestRateMode)][fromUser][toUser]; + } + + /** + * @dev Sets allowance to borrow on a certain type of debt asset for a certain user address + * @param asset The underlying asset of the debt token + * @param user The user to give allowance to + * @param interestRateMode Type of debt: 1 for stable, 2 for variable + * @param amount Allowance amount to borrow + **/ + function delegateBorrowAllowance( + address asset, + address user, + uint256 interestRateMode, + uint256 amount + ) external override { + address debtToken = _reserves[asset].getDebtTokenAddress(interestRateMode); + + _borrowAllowance[debtToken][msg.sender][user] = amount; + emit BorrowAllowanceDelegated(asset, msg.sender, user, interestRateMode, amount); + } + /** * @dev Allows users to borrow a specific amount of the reserve currency, provided that the borrower * already deposited enough collateral. @@ -166,20 +197,34 @@ contract LendingPool is VersionedInitializable, ILendingPool { * @param amount the amount to be borrowed * @param interestRateMode the interest rate mode at which the user wants to borrow. Can be 0 (STABLE) or 1 (VARIABLE) * @param referralCode a referral code for integrators + * @param onBehalfOf address of the user who will receive the debt **/ function borrow( address asset, uint256 amount, uint256 interestRateMode, - uint16 referralCode + uint16 referralCode, + address onBehalfOf ) external override { + ReserveLogic.ReserveData storage reserve = _reserves[asset]; + + if (onBehalfOf != msg.sender) { + address debtToken = reserve.getDebtTokenAddress(interestRateMode); + + _borrowAllowance[debtToken][onBehalfOf][msg + .sender] = _borrowAllowance[debtToken][onBehalfOf][msg.sender].sub( + amount, + Errors.BORROW_ALLOWANCE_ARE_NOT_ENOUGH + ); + } _executeBorrow( ExecuteBorrowParams( asset, msg.sender, + onBehalfOf, amount, interestRateMode, - _reserves[asset].aTokenAddress, + reserve.aTokenAddress, referralCode, true ) @@ -523,6 +568,7 @@ contract LendingPool is VersionedInitializable, ILendingPool { ExecuteBorrowParams( asset, msg.sender, + msg.sender, vars.amountPlusPremium.sub(vars.availableBalance), mode, vars.aTokenAddress, @@ -752,6 +798,7 @@ contract LendingPool is VersionedInitializable, ILendingPool { struct ExecuteBorrowParams { address asset; address user; + address onBehalfOf; uint256 amount; uint256 interestRateMode; address aTokenAddress; @@ -765,7 +812,7 @@ contract LendingPool is VersionedInitializable, ILendingPool { **/ function _executeBorrow(ExecuteBorrowParams memory vars) internal { ReserveLogic.ReserveData storage reserve = _reserves[vars.asset]; - UserConfiguration.Map storage userConfig = _usersConfig[msg.sender]; + UserConfiguration.Map storage userConfig = _usersConfig[vars.onBehalfOf]; address oracle = _addressesProvider.getPriceOracle(); @@ -775,7 +822,7 @@ contract LendingPool is VersionedInitializable, ILendingPool { ValidationLogic.validateBorrow( reserve, - vars.asset, + vars.onBehalfOf, vars.amount, amountInETH, vars.interestRateMode, @@ -802,12 +849,12 @@ contract LendingPool is VersionedInitializable, ILendingPool { currentStableRate = reserve.currentStableBorrowRate; IStableDebtToken(reserve.stableDebtTokenAddress).mint( - vars.user, + vars.onBehalfOf, vars.amount, currentStableRate ); } else { - IVariableDebtToken(reserve.variableDebtTokenAddress).mint(vars.user, vars.amount); + IVariableDebtToken(reserve.variableDebtTokenAddress).mint(vars.onBehalfOf, vars.amount); } reserve.updateInterestRates( @@ -818,12 +865,13 @@ contract LendingPool is VersionedInitializable, ILendingPool { ); if (vars.releaseUnderlying) { - IAToken(vars.aTokenAddress).transferUnderlyingTo(msg.sender, vars.amount); + IAToken(vars.aTokenAddress).transferUnderlyingTo(vars.user, vars.amount); } emit Borrow( vars.asset, - msg.sender, + vars.user, + vars.onBehalfOf, vars.amount, vars.interestRateMode, ReserveLogic.InterestRateMode(vars.interestRateMode) == ReserveLogic.InterestRateMode.STABLE diff --git a/contracts/lendingpool/LendingPoolLiquidationManager.sol b/contracts/lendingpool/LendingPoolLiquidationManager.sol index 3f393107..bc204c2c 100644 --- a/contracts/lendingpool/LendingPoolLiquidationManager.sol +++ b/contracts/lendingpool/LendingPoolLiquidationManager.sol @@ -43,6 +43,7 @@ contract LendingPoolLiquidationManager is VersionedInitializable { mapping(address => ReserveLogic.ReserveData) internal reserves; mapping(address => UserConfiguration.Map) internal usersConfig; + mapping(address => mapping(address => mapping(address => uint256))) internal _borrowAllowance; address[] internal reservesList; diff --git a/contracts/libraries/helpers/Errors.sol b/contracts/libraries/helpers/Errors.sol index ee9feac9..3ee9d945 100644 --- a/contracts/libraries/helpers/Errors.sol +++ b/contracts/libraries/helpers/Errors.sol @@ -38,6 +38,7 @@ library Errors { string public constant INCONSISTENT_PROTOCOL_ACTUAL_BALANCE = '26'; // 'The actual balance of the protocol is inconsistent' string public constant CALLER_NOT_LENDING_POOL_CONFIGURATOR = '27'; // 'The actual balance of the protocol is inconsistent' string public constant INVALID_FLASHLOAN_MODE = '43'; //Invalid flashloan mode selected + string public constant BORROW_ALLOWANCE_ARE_NOT_ENOUGH = '54'; // User borrows on behalf, but allowance are too small string public constant REENTRANCY_NOT_ALLOWED = '52'; string public constant FAILED_REPAY_WITH_COLLATERAL = '53'; diff --git a/contracts/libraries/logic/ReserveLogic.sol b/contracts/libraries/logic/ReserveLogic.sol index 84e7626c..bccc5113 100644 --- a/contracts/libraries/logic/ReserveLogic.sol +++ b/contracts/libraries/logic/ReserveLogic.sol @@ -120,6 +120,28 @@ library ReserveLogic { return cumulated; } + /** + * @dev returns an address of the debt token used for particular interest rate mode on asset. + * @param reserve the reserve object + * @param interestRateMode - STABLE or VARIABLE from ReserveLogic.InterestRateMode enum + * @return an address of the corresponding debt token from reserve configuration + **/ + function getDebtTokenAddress(ReserveLogic.ReserveData storage reserve, uint256 interestRateMode) + internal + view + returns (address) + { + require( + ReserveLogic.InterestRateMode.STABLE == ReserveLogic.InterestRateMode(interestRateMode) || + ReserveLogic.InterestRateMode.VARIABLE == ReserveLogic.InterestRateMode(interestRateMode), + Errors.INVALID_INTEREST_RATE_MODE_SELECTED + ); + return + ReserveLogic.InterestRateMode.STABLE == ReserveLogic.InterestRateMode(interestRateMode) + ? reserve.stableDebtTokenAddress + : reserve.variableDebtTokenAddress; + } + /** * @dev Updates the liquidity cumulative index Ci and variable borrow cumulative index Bvc. Refer to the whitepaper for * a formal specification. diff --git a/contracts/libraries/logic/ValidationLogic.sol b/contracts/libraries/logic/ValidationLogic.sol index a5f3f331..b88c065b 100644 --- a/contracts/libraries/logic/ValidationLogic.sol +++ b/contracts/libraries/logic/ValidationLogic.sol @@ -100,7 +100,7 @@ library ValidationLogic { /** * @dev validates a borrow. * @param reserve the reserve state from which the user is borrowing - * @param reserveAddress the address of the reserve + * @param userAddress the address of the user * @param amount the amount to be borrowed * @param amountInETH the amount to be borrowed, in ETH * @param interestRateMode the interest rate mode at which the user is borrowing @@ -113,7 +113,7 @@ library ValidationLogic { function validateBorrow( ReserveLogic.ReserveData storage reserve, - address reserveAddress, + address userAddress, uint256 amount, uint256 amountInETH, uint256 interestRateMode, @@ -151,7 +151,7 @@ library ValidationLogic { vars.currentLiquidationThreshold, vars.healthFactor ) = GenericLogic.calculateUserAccountData( - msg.sender, + userAddress, reservesData, userConfig, reserves, @@ -192,7 +192,7 @@ library ValidationLogic { require( !userConfig.isUsingAsCollateral(reserve.id) || reserve.configuration.getLtv() == 0 || - amount > IERC20(reserve.aTokenAddress).balanceOf(msg.sender), + amount > IERC20(reserve.aTokenAddress).balanceOf(userAddress), Errors.CALLATERAL_SAME_AS_BORROWING_CURRENCY ); diff --git a/test/atoken-transfer.spec.ts b/test/atoken-transfer.spec.ts index 73c299ad..a5c13989 100644 --- a/test/atoken-transfer.spec.ts +++ b/test/atoken-transfer.spec.ts @@ -60,7 +60,13 @@ makeSuite('AToken: Transfer', (testEnv: TestEnv) => { await expect( pool .connect(users[1].signer) - .borrow(weth.address, ethers.utils.parseEther('0.1'), RateMode.Stable, AAVE_REFERRAL), + .borrow( + weth.address, + ethers.utils.parseEther('0.1'), + RateMode.Stable, + AAVE_REFERRAL, + users[1].address + ), COLLATERAL_BALANCE_IS_0 ).to.be.revertedWith(COLLATERAL_BALANCE_IS_0); }); @@ -73,7 +79,13 @@ makeSuite('AToken: Transfer', (testEnv: TestEnv) => { await pool .connect(users[1].signer) - .borrow(weth.address, ethers.utils.parseEther('0.1'), RateMode.Stable, AAVE_REFERRAL); + .borrow( + weth.address, + ethers.utils.parseEther('0.1'), + RateMode.Stable, + AAVE_REFERRAL, + users[1].address + ); await expect( aDai.connect(users[1].signer).transfer(users[0].address, aDAItoTransfer), diff --git a/test/flash-liquidation-with-collateral.spec.ts b/test/flash-liquidation-with-collateral.spec.ts index c48b5e99..0dcc7f1e 100644 --- a/test/flash-liquidation-with-collateral.spec.ts +++ b/test/flash-liquidation-with-collateral.spec.ts @@ -47,9 +47,9 @@ makeSuite('LendingPool. repayWithCollateral() with liquidator', (testEnv: TestEn const usdcPrice = await oracle.getAssetPrice(usdc.address); - await pool.connect(user.signer).borrow(usdc.address, amountToBorrow, 2, 0); + await pool.connect(user.signer).borrow(usdc.address, amountToBorrow, 2, 0, user.address); - await pool.connect(user.signer).borrow(usdc.address, amountToBorrow, 1, 0); + await pool.connect(user.signer).borrow(usdc.address, amountToBorrow, 1, 0, user.address); const {userData: wethUserDataBefore} = await getContractsData( weth.address, @@ -203,7 +203,7 @@ makeSuite('LendingPool. repayWithCollateral() with liquidator', (testEnv: TestEn .toFixed(0) ); - await pool.connect(user.signer).borrow(usdc.address, amountUSDCToBorrow, 2, 0); + await pool.connect(user.signer).borrow(usdc.address, amountUSDCToBorrow, 2, 0, user.address); }); it('User 5 liquidates half the USDC loan of User 3 by swapping his WETH collateral', async () => { @@ -464,7 +464,7 @@ makeSuite('LendingPool. repayWithCollateral() with liquidator', (testEnv: TestEn .toFixed(0) ); - await pool.connect(user.signer).borrow(dai.address, amountDAIToBorrow, 2, 0); + await pool.connect(user.signer).borrow(dai.address, amountDAIToBorrow, 2, 0, user.address); }); it('It is not possible to do reentrancy on repayWithCollateral()', async () => { @@ -736,7 +736,7 @@ makeSuite('LendingPool. repayWithCollateral() with liquidator', (testEnv: TestEn await pool.connect(user.signer).deposit(weth.address, amountToDepositWeth, user.address, '0'); await pool.connect(user.signer).deposit(dai.address, amountToDepositDAI, user.address, '0'); - await pool.connect(user.signer).borrow(usdc.address, amountToBorrowVariable, 2, 0); + await pool.connect(user.signer).borrow(usdc.address, amountToBorrowVariable, 2, 0, user.address); const amountToRepay = amountToBorrowVariable; @@ -844,7 +844,7 @@ makeSuite('LendingPool. repayWithCollateral() with liquidator', (testEnv: TestEn await dai.connect(user.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); await pool.connect(user.signer).deposit(dai.address, amountDAIToDeposit, user.address, '0'); - await pool.connect(user.signer).borrow(usdc.address, amountToBorrow, 2, 0); + await pool.connect(user.signer).borrow(usdc.address, amountToBorrow, 2, 0, user.address); }); it('Liquidator tries to liquidates User 5 USDC loan by swapping his WETH collateral, should revert due WETH collateral disabled', async () => { diff --git a/test/helpers/actions.ts b/test/helpers/actions.ts index 1e8dd6db..3f9fea4b 100644 --- a/test/helpers/actions.ts +++ b/test/helpers/actions.ts @@ -283,11 +283,41 @@ export const withdraw = async ( } }; +export const delegateBorrowAllowance = async ( + reserveSymbol: string, + amount: string, + interestRateMode: string, + user: SignerWithAddress, + receiver: tEthereumAddress, + expectedResult: string, + testEnv: TestEnv, + revertMessage?: string +) => { + const {pool} = testEnv; + + const reserve = await getReserveAddressFromSymbol(reserveSymbol); + const amountToDelegate = await convertToCurrencyDecimals(reserve, amount); + + const delegateAllowancePromise = pool + .connect(user.signer) + .delegateBorrowAllowance(reserve, receiver, interestRateMode, amountToDelegate.toString()); + if (expectedResult === 'revert') { + await expect(delegateAllowancePromise, revertMessage).to.be.reverted; + return; + } else { + await delegateAllowancePromise; + expect( + (await pool.getBorrowAllowance(user.address, receiver, reserve, interestRateMode)).toString() + ).to.be.equal(amountToDelegate.toString(), 'borrowAllowance are set incorrectly'); + } +}; + export const borrow = async ( reserveSymbol: string, amount: string, interestRateMode: string, user: SignerWithAddress, + onBehalfOf: tEthereumAddress, timeTravel: string, expectedResult: string, testEnv: TestEnv, @@ -299,15 +329,18 @@ export const borrow = async ( const {reserveData: reserveDataBefore, userData: userDataBefore} = await getContractsData( reserve, - user.address, - testEnv + onBehalfOf, + testEnv, + user.address ); const amountToBorrow = await convertToCurrencyDecimals(reserve, amount); if (expectedResult === 'success') { const txResult = await waitForTx( - await pool.connect(user.signer).borrow(reserve, amountToBorrow, interestRateMode, '0') + await pool + .connect(user.signer) + .borrow(reserve, amountToBorrow, interestRateMode, '0', onBehalfOf) ); const {txCost, txTimestamp} = await getTxCostAndTimestamp(txResult); @@ -322,7 +355,7 @@ export const borrow = async ( reserveData: reserveDataAfter, userData: userDataAfter, timestamp, - } = await getContractsData(reserve, user.address, testEnv); + } = await getContractsData(reserve, onBehalfOf, testEnv, user.address); const expectedReserveData = calcExpectedReserveDataAfterBorrow( amountToBorrow.toString(), @@ -369,7 +402,7 @@ export const borrow = async ( // }); } else if (expectedResult === 'revert') { await expect( - pool.connect(user.signer).borrow(reserve, amountToBorrow, interestRateMode, '0'), + pool.connect(user.signer).borrow(reserve, amountToBorrow, interestRateMode, '0', onBehalfOf), revertMessage ).to.be.reverted; } diff --git a/test/helpers/scenario-engine.ts b/test/helpers/scenario-engine.ts index 8618de3d..6a03a4d1 100644 --- a/test/helpers/scenario-engine.ts +++ b/test/helpers/scenario-engine.ts @@ -8,7 +8,8 @@ import { repay, setUseAsCollateral, swapBorrowRateMode, - rebalanceStableBorrowRate + rebalanceStableBorrowRate, + delegateBorrowAllowance, } from './actions'; import {RateMode} from '../../helpers/types'; @@ -59,7 +60,7 @@ const executeAction = async (action: Action, users: SignerWithAddress[], testEnv if (borrowRateMode) { if (borrowRateMode === 'none') { - RateMode.None; + rateMode = RateMode.None; } else if (borrowRateMode === 'stable') { rateMode = RateMode.Stable; } else if (borrowRateMode === 'variable') { @@ -111,6 +112,27 @@ const executeAction = async (action: Action, users: SignerWithAddress[], testEnv } break; + case 'delegateBorrowAllowance': + { + const {amount, toUser: toUserIndex} = action.args; + const toUser = users[parseInt(toUserIndex, 10)].address; + if (!amount || amount === '') { + throw `Invalid amount to deposit into the ${reserve} reserve`; + } + + await delegateBorrowAllowance( + reserve, + amount, + rateMode, + user, + toUser, + expected, + testEnv, + revertMessage + ); + } + break; + case 'withdraw': { const {amount} = action.args; @@ -124,13 +146,27 @@ const executeAction = async (action: Action, users: SignerWithAddress[], testEnv break; case 'borrow': { - const {amount, timeTravel} = action.args; + const {amount, timeTravel, onBehalfOf: onBehalfOfIndex} = action.args; + + const onBehalfOf = onBehalfOfIndex + ? users[parseInt(onBehalfOfIndex)].address + : user.address; if (!amount || amount === '') { throw `Invalid amount to borrow from the ${reserve} reserve`; } - await borrow(reserve, amount, rateMode, user, timeTravel, expected, testEnv, revertMessage); + await borrow( + reserve, + amount, + rateMode, + user, + onBehalfOf, + timeTravel, + expected, + testEnv, + revertMessage + ); } break; diff --git a/test/helpers/scenarios/credit-delegation.json b/test/helpers/scenarios/credit-delegation.json new file mode 100644 index 00000000..a67924ee --- /dev/null +++ b/test/helpers/scenarios/credit-delegation.json @@ -0,0 +1,148 @@ +{ + "title": "LendingPool: credit delegation", + "description": "Test cases for the credit delegation related functions.", + "stories": [ + { + "description": "User 0 deposits 1000 DAI, user 0 delegates borrowing of 1 WETH on variable to user 4, user 4 borrows 1 WETH variable on behalf of user 0", + "actions": [ + { + "name": "mint", + "args": { + "reserve": "WETH", + "amount": "1000", + "user": "0" + }, + "expected": "success" + }, + { + "name": "approve", + "args": { + "reserve": "WETH", + "user": "0" + }, + "expected": "success" + }, + { + "name": "deposit", + "args": { + "reserve": "WETH", + "amount": "1000", + "user": "0" + }, + "expected": "success" + }, + { + "name": "delegateBorrowAllowance", + "args": { + "reserve": "WETH", + "amount": "2", + "user": "0", + "borrowRateMode": "variable", + "toUser": "4" + }, + "expected": "success" + }, + { + "name": "borrow", + "args": { + "reserve": "WETH", + "amount": "1", + "user": "4", + "onBehalfOf": "0", + "borrowRateMode": "variable" + }, + "expected": "success" + } + ] + }, + { + "description": "User 4 trying to borrow 1 WETH stable on behalf of user 0, revert expected", + "actions": [ + { + "name": "borrow", + "args": { + "reserve": "WETH", + "amount": "1", + "user": "4", + "onBehalfOf": "0", + "borrowRateMode": "stable" + }, + "expected": "revert", + "revertMessage": "54" + } + ] + }, + { + "description": "User 0 delegates borrowing of 1 WETH to user 4, user 4 borrows 3 WETH variable on behalf of user 0, revert expected", + "actions": [ + { + "name": "delegateBorrowAllowance", + "args": { + "reserve": "WETH", + "amount": "1", + "user": "0", + "borrowRateMode": "variable", + "toUser": "4" + }, + "expected": "success" + }, + { + "name": "borrow", + "args": { + "reserve": "WETH", + "amount": "3", + "user": "4", + "onBehalfOf": "0", + "borrowRateMode": "variable" + }, + "expected": "revert", + "revertMessage": "54" + } + ] + }, + { + "description": "User 0 delegates borrowing of 1 WETH on stable to user 2, user 2 borrows 1 WETH stable on behalf of user 0", + "actions": [ + { + "name": "delegateBorrowAllowance", + "args": { + "reserve": "WETH", + "amount": "1", + "user": "0", + "borrowRateMode": "stable", + "toUser": "2" + }, + "expected": "success" + }, + { + "name": "borrow", + "args": { + "reserve": "WETH", + "amount": "1", + "user": "2", + "onBehalfOf": "0", + "borrowRateMode": "stable" + }, + "expected": "success" + } + ] + }, + { + "description": "User 0 delegates borrowing of 1 WETH to user 2 with wrong borrowRateMode, revert expected", + "actions": [ + { + "name": "delegateBorrowAllowance", + "args": { + "reserve": "WETH", + "amount": "1", + "user": "0", + "borrowRateMode": "random", + "toUser": "2" + }, + "expected": "revert", + "revertMessage": "8" + } + ] + } + ] +} diff --git a/test/liquidation-atoken.spec.ts b/test/liquidation-atoken.spec.ts index 342c2a63..15f3d12d 100644 --- a/test/liquidation-atoken.spec.ts +++ b/test/liquidation-atoken.spec.ts @@ -63,7 +63,7 @@ makeSuite('LendingPool liquidation - liquidator receiving aToken', (testEnv) => await pool .connect(borrower.signer) - .borrow(dai.address, amountDAIToBorrow, RateMode.Variable, '0'); + .borrow(dai.address, amountDAIToBorrow, RateMode.Variable, '0', borrower.address); const userGlobalDataAfter = await pool.getUserAccountData(borrower.address); @@ -261,7 +261,7 @@ makeSuite('LendingPool liquidation - liquidator receiving aToken', (testEnv) => await pool .connect(borrower.signer) - .borrow(usdc.address, amountUSDCToBorrow, RateMode.Stable, '0'); + .borrow(usdc.address, amountUSDCToBorrow, RateMode.Stable, '0', borrower.address); //drops HF below 1 diff --git a/test/liquidation-underlying.spec.ts b/test/liquidation-underlying.spec.ts index 3f2aecbc..e40ec406 100644 --- a/test/liquidation-underlying.spec.ts +++ b/test/liquidation-underlying.spec.ts @@ -68,7 +68,7 @@ makeSuite('LendingPool liquidation - liquidator receiving the underlying asset', await pool .connect(borrower.signer) - .borrow(dai.address, amountDAIToBorrow, RateMode.Stable, '0'); + .borrow(dai.address, amountDAIToBorrow, RateMode.Stable, '0', borrower.address); const userGlobalDataAfter = await pool.getUserAccountData(borrower.address); @@ -240,7 +240,7 @@ makeSuite('LendingPool liquidation - liquidator receiving the underlying asset', await pool .connect(borrower.signer) - .borrow(usdc.address, amountUSDCToBorrow, RateMode.Stable, '0'); + .borrow(usdc.address, amountUSDCToBorrow, RateMode.Stable, '0', borrower.address); //drops HF below 1 await oracle.setAssetPrice( diff --git a/test/repay-with-collateral.spec.ts b/test/repay-with-collateral.spec.ts index faefa403..9c169f10 100644 --- a/test/repay-with-collateral.spec.ts +++ b/test/repay-with-collateral.spec.ts @@ -65,7 +65,7 @@ makeSuite('LendingPool. repayWithCollateral()', (testEnv: TestEnv) => { await pool.connect(user.signer).deposit(weth.address, amountToDeposit, user.address, '0'); - await pool.connect(user.signer).borrow(dai.address, amountToBorrow, 2, 0); + await pool.connect(user.signer).borrow(dai.address, amountToBorrow, 2, 0, user.address); }); it('It is not possible to do reentrancy on repayWithCollateral()', async () => { @@ -187,7 +187,7 @@ makeSuite('LendingPool. repayWithCollateral()', (testEnv: TestEnv) => { await pool.connect(user.signer).deposit(weth.address, amountToDeposit, user.address, '0'); - await pool.connect(user.signer).borrow(usdc.address, amountToBorrow, 2, 0); + await pool.connect(user.signer).borrow(usdc.address, amountToBorrow, 2, 0, user.address); }); it('User 3 repays completely his USDC loan by swapping his WETH collateral', async () => { @@ -309,9 +309,9 @@ makeSuite('LendingPool. repayWithCollateral()', (testEnv: TestEnv) => { await pool.connect(user.signer).deposit(weth.address, amountToDeposit, user.address, '0'); - await pool.connect(user.signer).borrow(usdc.address, amountToBorrowVariable, 2, 0); + await pool.connect(user.signer).borrow(usdc.address, amountToBorrowVariable, 2, 0, user.address); - await pool.connect(user.signer).borrow(usdc.address, amountToBorrowStable, 1, 0); + await pool.connect(user.signer).borrow(usdc.address, amountToBorrowStable, 1, 0, user.address); const amountToRepay = parseUnits('80', 6); @@ -450,7 +450,7 @@ makeSuite('LendingPool. repayWithCollateral()', (testEnv: TestEnv) => { await pool.connect(user.signer).deposit(weth.address, amountToDepositWeth, user.address, '0'); await pool.connect(user.signer).deposit(dai.address, amountToDepositDAI, user.address, '0'); - await pool.connect(user.signer).borrow(dai.address, amountToBorrowVariable, 2, 0); + await pool.connect(user.signer).borrow(dai.address, amountToBorrowVariable, 2, 0, user.address); const amountToRepay = parseEther('80'); @@ -542,7 +542,7 @@ makeSuite('LendingPool. repayWithCollateral()', (testEnv: TestEnv) => { await dai.connect(user.signer).approve(pool.address, APPROVAL_AMOUNT_LENDING_POOL); await pool.connect(user.signer).deposit(dai.address, amountDAIToDeposit, user.address, '0'); - await pool.connect(user.signer).borrow(usdc.address, amountToBorrow, 2, 0); + await pool.connect(user.signer).borrow(usdc.address, amountToBorrow, 2, 0, user.address); }); it('User 5 tries to repay his USDC loan by swapping his WETH collateral, should not revert even with WETH collateral disabled', async () => {