diff --git a/contracts/interfaces/ILendingPool.sol b/contracts/interfaces/ILendingPool.sol index f44a458a..49869817 100644 --- a/contracts/interfaces/ILendingPool.sol +++ b/contracts/interfaces/ILendingPool.sol @@ -32,11 +32,11 @@ 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 + address[] assets, + uint256[] interestRateModes, + uint256[] amounts ); /** * @dev emitted on borrow @@ -189,17 +189,17 @@ 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 + * @dev Sets allowance to borrow on a certain type of debt assets for a certain user address + * @param assets The underlying asset of each 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 + * @param interestRateModes Types of debt: 1 for stable, 2 for variable + * @param amounts Allowance amounts to borrow **/ function delegateBorrowAllowance( - address asset, + address[] calldata assets, address user, - uint256 interestRateMode, - uint256 amount + uint256[] calldata interestRateModes, + uint256[] calldata amounts ) external; function getBorrowAllowance( diff --git a/contracts/lendingpool/LendingPool.sol b/contracts/lendingpool/LendingPool.sol index 3f490365..f77aac9d 100644 --- a/contracts/lendingpool/LendingPool.sol +++ b/contracts/lendingpool/LendingPool.sol @@ -179,23 +179,32 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage } /** - * @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 + * @dev Sets allowance to borrow on a certain type of debt assets for a certain user address + * @param assets The underlying asset of each 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 + * @param interestRateModes Types of debt: 1 for stable, 2 for variable + * @param amounts Allowance amounts to borrow **/ function delegateBorrowAllowance( - address asset, + address[] calldata assets, address user, - uint256 interestRateMode, - uint256 amount + uint256[] calldata interestRateModes, + uint256[] calldata amounts ) external override { _whenNotPaused(); - address debtToken = _reserves[asset].getDebtTokenAddress(interestRateMode); - _borrowAllowance[debtToken][msg.sender][user] = amount; - emit BorrowAllowanceDelegated(asset, msg.sender, user, interestRateMode, amount); + uint256 countAssets = assets.length; + require( + countAssets == interestRateModes.length && countAssets == amounts.length, + Errors.INCONSISTENT_PARAMS_LENGTH + ); + + for (uint256 i = 0; i < countAssets; i++) { + address debtToken = _reserves[assets[i]].getDebtTokenAddress(interestRateModes[i]); + _borrowAllowance[debtToken][msg.sender][user] = amounts[i]; + } + + emit BorrowAllowanceDelegated(msg.sender, user, assets, interestRateModes, amounts); } /** @@ -913,7 +922,6 @@ contract LendingPool is VersionedInitializable, ILendingPool, LendingPoolStorage * @dev adds a reserve to the array of the _reserves address **/ function _addReserveToList(address asset) internal { - uint256 reservesCount = _reservesCount; require(reservesCount < MAX_NUMBER_RESERVES, Errors.NO_MORE_RESERVES_ALLOWED); diff --git a/contracts/libraries/helpers/Errors.sol b/contracts/libraries/helpers/Errors.sol index 9ed7b07e..2bd24743 100644 --- a/contracts/libraries/helpers/Errors.sol +++ b/contracts/libraries/helpers/Errors.sol @@ -97,6 +97,9 @@ library Errors { string public constant INVALID_DECIMALS = '73'; string public constant INVALID_RESERVE_FACTOR = '74'; + // Credit delegation + string public constant INCONSISTENT_PARAMS_LENGTH = '75'; + enum CollateralManagerErrors { NO_ERROR, diff --git a/test/helpers/actions.ts b/test/helpers/actions.ts index 85d3eb00..60feac6a 100644 --- a/test/helpers/actions.ts +++ b/test/helpers/actions.ts @@ -279,9 +279,9 @@ export const withdraw = async ( }; export const delegateBorrowAllowance = async ( - reserveSymbol: string, - amount: string, - interestRateMode: string, + reserveSymbols: string[], + amounts: string[], + interestRateModes: string[], user: SignerWithAddress, receiver: tEthereumAddress, expectedResult: string, @@ -290,20 +290,27 @@ export const delegateBorrowAllowance = async ( ) => { const {pool} = testEnv; - const reserve = await getReserveAddressFromSymbol(reserveSymbol); - const amountToDelegate = await convertToCurrencyDecimals(reserve, amount); + const reserves : tEthereumAddress[] = [] + const amountsToDelegate: tEthereumAddress[] = [] + for (const reserveSymbol of reserveSymbols) { + const newLength = reserves.push(await getReserveAddressFromSymbol(reserveSymbol)) + amountsToDelegate.push(await (await convertToCurrencyDecimals(reserves[newLength-1], amounts[newLength-1])).toString()) + } const delegateAllowancePromise = pool .connect(user.signer) - .delegateBorrowAllowance(reserve, receiver, interestRateMode, amountToDelegate.toString()); + .delegateBorrowAllowance(reserves, receiver, interestRateModes, amountsToDelegate); 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'); + for (const [i, reserve] of reserves.entries()) { + expect( + (await pool.getBorrowAllowance(user.address, receiver, reserve, interestRateModes[i])).toString() + ).to.be.equal(amountsToDelegate[i], 'borrowAllowance are set incorrectly'); + } + } }; diff --git a/test/helpers/scenario-engine.ts b/test/helpers/scenario-engine.ts index bb4f82f8..fe2e302a 100644 --- a/test/helpers/scenario-engine.ts +++ b/test/helpers/scenario-engine.ts @@ -121,9 +121,9 @@ const executeAction = async (action: Action, users: SignerWithAddress[], testEnv } await delegateBorrowAllowance( - reserve, - amount, - rateMode, + [reserve], + [amount], + [rateMode], user, toUser, expected, diff --git a/test/pausable-functions.spec.ts b/test/pausable-functions.spec.ts index 48c50ee2..a15ceb61 100644 --- a/test/pausable-functions.spec.ts +++ b/test/pausable-functions.spec.ts @@ -132,7 +132,7 @@ makeSuite('Pausable Pool', (testEnv: TestEnv) => { // Try to execute liquidation await expect( - pool.connect(user.signer).delegateBorrowAllowance(dai.address, toUser.address, '1', '1') + pool.connect(user.signer).delegateBorrowAllowance([dai.address], toUser.address, ['1'], ['1']) ).revertedWith(IS_PAUSED); // Unpause the pool