mirror of
https://github.com/Instadapp/aave-protocol-v2.git
synced 2024-07-29 21:47:30 +00:00
initial implementation of the credit delegation + basic tests
This commit is contained in:
parent
23f99d30f0
commit
3173bee782
|
@ -28,6 +28,12 @@ interface ILendingPool {
|
|||
**/
|
||||
event Withdraw(address indexed reserve, address indexed user, uint256 amount);
|
||||
|
||||
event BorrowAllowanceDelegated(
|
||||
address indexed fromUser,
|
||||
address indexed toUser,
|
||||
address indexed asset,
|
||||
uint256 amount
|
||||
);
|
||||
/**
|
||||
* @dev emitted on borrow
|
||||
* @param reserve the address of the reserve
|
||||
|
@ -39,7 +45,8 @@ interface ILendingPool {
|
|||
**/
|
||||
event Borrow(
|
||||
address indexed reserve,
|
||||
address indexed user,
|
||||
address user,
|
||||
address indexed onBehalfOf,
|
||||
uint256 amount,
|
||||
uint256 borrowRateMode,
|
||||
uint256 borrowRate,
|
||||
|
@ -149,6 +156,18 @@ interface ILendingPool {
|
|||
**/
|
||||
function withdraw(address reserve, uint256 amount) external;
|
||||
|
||||
function delegateBorrowAllowance(
|
||||
address user,
|
||||
address asset,
|
||||
uint256 amount
|
||||
) external;
|
||||
|
||||
function getBorrowAllowance(
|
||||
address fromUser,
|
||||
address toUser,
|
||||
address asset
|
||||
) external view returns (uint256);
|
||||
|
||||
/**
|
||||
* @dev Allows users to borrow a specific amount of the reserve currency, provided that the borrower
|
||||
* already deposited enough collateral.
|
||||
|
@ -160,7 +179,8 @@ interface ILendingPool {
|
|||
address reserve,
|
||||
uint256 amount,
|
||||
uint256 interestRateMode,
|
||||
uint16 referralCode
|
||||
uint16 referralCode,
|
||||
address onBehalfOf
|
||||
) external;
|
||||
|
||||
/**
|
||||
|
|
|
@ -48,7 +48,7 @@ contract LendingPool is VersionedInitializable, ILendingPool {
|
|||
|
||||
mapping(address => ReserveLogic.ReserveData) internal _reserves;
|
||||
mapping(address => UserConfiguration.Map) internal _usersConfig;
|
||||
|
||||
mapping(address => mapping(address => mapping(address => uint256))) internal _borrowAllowance;
|
||||
address[] internal _reservesList;
|
||||
|
||||
/**
|
||||
|
@ -157,6 +157,23 @@ contract LendingPool is VersionedInitializable, ILendingPool {
|
|||
emit Withdraw(asset, msg.sender, amount);
|
||||
}
|
||||
|
||||
function getBorrowAllowance(
|
||||
address fromUser,
|
||||
address toUser,
|
||||
address asset
|
||||
) external override view returns (uint256) {
|
||||
return _borrowAllowance[fromUser][asset][toUser];
|
||||
}
|
||||
|
||||
function delegateBorrowAllowance(
|
||||
address user,
|
||||
address asset,
|
||||
uint256 amount
|
||||
) external override {
|
||||
_borrowAllowance[msg.sender][asset][user] = amount;
|
||||
emit BorrowAllowanceDelegated(msg.sender, user, asset, amount);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Allows users to borrow a specific amount of the reserve currency, provided that the borrower
|
||||
* already deposited enough collateral.
|
||||
|
@ -169,12 +186,19 @@ contract LendingPool is VersionedInitializable, ILendingPool {
|
|||
address asset,
|
||||
uint256 amount,
|
||||
uint256 interestRateMode,
|
||||
uint16 referralCode
|
||||
uint16 referralCode,
|
||||
address onBehalfOf
|
||||
) external override {
|
||||
if (onBehalfOf != msg.sender) {
|
||||
_borrowAllowance[onBehalfOf][asset][msg.sender] = _borrowAllowance[onBehalfOf][asset][msg
|
||||
.sender]
|
||||
.sub(amount, Errors.BORROW_ALLOWANCE_ARE_NOT_ENOUGH);
|
||||
}
|
||||
_executeBorrow(
|
||||
ExecuteBorrowParams(
|
||||
asset,
|
||||
msg.sender,
|
||||
onBehalfOf,
|
||||
amount,
|
||||
interestRateMode,
|
||||
_reserves[asset].aTokenAddress,
|
||||
|
@ -450,21 +474,20 @@ contract LendingPool is VersionedInitializable, ILendingPool {
|
|||
vars.amountPlusPremium = amount.add(vars.premium);
|
||||
|
||||
if (debtMode == ReserveLogic.InterestRateMode.NONE) {
|
||||
|
||||
IERC20(asset).transferFrom(receiverAddress, vars.aTokenAddress, vars.amountPlusPremium);
|
||||
|
||||
|
||||
reserve.updateCumulativeIndexesAndTimestamp();
|
||||
reserve.cumulateToLiquidityIndex(IERC20(vars.aTokenAddress).totalSupply(), vars.premium);
|
||||
reserve.updateInterestRates(asset, vars.aTokenAddress, vars.premium, 0);
|
||||
|
||||
emit FlashLoan(receiverAddress, asset, amount, vars.premium, referralCode);
|
||||
|
||||
emit FlashLoan(receiverAddress, asset, amount, vars.premium, referralCode);
|
||||
} else {
|
||||
// If the transfer didn't succeed, the receiver either didn't return the funds, or didn't approve the transfer.
|
||||
_executeBorrow(
|
||||
ExecuteBorrowParams(
|
||||
asset,
|
||||
msg.sender,
|
||||
msg.sender,
|
||||
vars.amountPlusPremium.sub(vars.availableBalance),
|
||||
mode,
|
||||
vars.aTokenAddress,
|
||||
|
@ -694,6 +717,7 @@ contract LendingPool is VersionedInitializable, ILendingPool {
|
|||
struct ExecuteBorrowParams {
|
||||
address asset;
|
||||
address user;
|
||||
address onBehalfOf;
|
||||
uint256 amount;
|
||||
uint256 interestRateMode;
|
||||
address aTokenAddress;
|
||||
|
@ -707,7 +731,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();
|
||||
|
||||
|
@ -717,6 +741,7 @@ contract LendingPool is VersionedInitializable, ILendingPool {
|
|||
|
||||
ValidationLogic.validateBorrow(
|
||||
reserve,
|
||||
vars.onBehalfOf,
|
||||
vars.asset,
|
||||
vars.amount,
|
||||
amountInETH,
|
||||
|
@ -728,13 +753,11 @@ contract LendingPool is VersionedInitializable, ILendingPool {
|
|||
oracle
|
||||
);
|
||||
|
||||
|
||||
uint256 reserveIndex = reserve.index;
|
||||
if (!userConfig.isBorrowing(reserveIndex)) {
|
||||
userConfig.setBorrowing(reserveIndex, true);
|
||||
}
|
||||
|
||||
|
||||
reserve.updateCumulativeIndexesAndTimestamp();
|
||||
|
||||
//caching the current stable borrow rate
|
||||
|
@ -746,24 +769,29 @@ 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(vars.asset, vars.aTokenAddress, 0, vars.releaseUnderlying ? vars.amount : 0);
|
||||
|
||||
if(vars.releaseUnderlying){
|
||||
IAToken(vars.aTokenAddress).transferUnderlyingTo(msg.sender, vars.amount);
|
||||
reserve.updateInterestRates(
|
||||
vars.asset,
|
||||
vars.aTokenAddress,
|
||||
0,
|
||||
vars.releaseUnderlying ? vars.amount : 0
|
||||
);
|
||||
|
||||
if (vars.releaseUnderlying) {
|
||||
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
|
||||
|
|
|
@ -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 = '52'; // User borrows on behalf, but allowance are too small
|
||||
|
||||
// require error messages - aToken
|
||||
string public constant CALLER_MUST_BE_LENDING_POOL = '28'; // 'The caller of this function must be a lending pool'
|
||||
|
@ -70,7 +71,7 @@ library Errors {
|
|||
string public constant NO_ERRORS = '42'; // 'No errors'
|
||||
|
||||
//require error messages - Math libraries
|
||||
string public constant MULTIPLICATION_OVERFLOW = '44';
|
||||
string public constant ADDITION_OVERFLOW = '45';
|
||||
string public constant MULTIPLICATION_OVERFLOW = '44';
|
||||
string public constant ADDITION_OVERFLOW = '45';
|
||||
string public constant DIVISION_BY_ZERO = '46';
|
||||
}
|
||||
|
|
|
@ -100,6 +100,7 @@ library ValidationLogic {
|
|||
/**
|
||||
* @dev validates a borrow.
|
||||
* @param reserve the reserve state from which the user is borrowing
|
||||
* @param userAddress the address of the user
|
||||
* @param reserveAddress the address of the reserve
|
||||
* @param amount the amount to be borrowed
|
||||
* @param amountInETH the amount to be borrowed, in ETH
|
||||
|
@ -113,6 +114,7 @@ library ValidationLogic {
|
|||
|
||||
function validateBorrow(
|
||||
ReserveLogic.ReserveData storage reserve,
|
||||
address userAddress,
|
||||
address reserveAddress,
|
||||
uint256 amount,
|
||||
uint256 amountInETH,
|
||||
|
@ -151,7 +153,7 @@ library ValidationLogic {
|
|||
vars.currentLiquidationThreshold,
|
||||
vars.healthFactor
|
||||
) = GenericLogic.calculateUserAccountData(
|
||||
msg.sender,
|
||||
userAddress,
|
||||
reservesData,
|
||||
userConfig,
|
||||
reserves,
|
||||
|
@ -192,7 +194,7 @@ library ValidationLogic {
|
|||
require(
|
||||
!userConfig.isUsingAsCollateral(reserve.index) ||
|
||||
reserve.configuration.getLtv() == 0 ||
|
||||
amount > IERC20(reserve.aTokenAddress).balanceOf(msg.sender),
|
||||
amount > IERC20(reserve.aTokenAddress).balanceOf(userAddress),
|
||||
Errors.CALLATERAL_SAME_AS_BORROWING_CURRENCY
|
||||
);
|
||||
|
||||
|
@ -321,10 +323,10 @@ library ValidationLogic {
|
|||
}
|
||||
|
||||
/**
|
||||
* @dev validates a flashloan action
|
||||
* @param mode the flashloan mode (0 = classic flashloan, 1 = open a stable rate loan, 2 = open a variable rate loan)
|
||||
* @param premium the premium paid on the flashloan
|
||||
**/
|
||||
* @dev validates a flashloan action
|
||||
* @param mode the flashloan mode (0 = classic flashloan, 1 = open a stable rate loan, 2 = open a variable rate loan)
|
||||
* @param premium the premium paid on the flashloan
|
||||
**/
|
||||
function validateFlashloan(uint256 mode, uint256 premium) internal pure {
|
||||
require(premium > 0, Errors.REQUESTED_AMOUNT_TOO_SMALL);
|
||||
require(mode <= uint256(ReserveLogic.InterestRateMode.VARIABLE), Errors.INVALID_FLASHLOAN_MODE);
|
||||
|
|
|
@ -111,7 +111,7 @@
|
|||
},
|
||||
"DefaultReserveInterestRateStrategy": {
|
||||
"buidlerevm": {
|
||||
"address": "0x626FdE749F9d499d3777320CAf29484B624ab84a",
|
||||
"address": "0x2530ce07D254eA185E8e0bCC37a39e2FbA3bE548",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"localhost": {
|
||||
|
@ -422,7 +422,7 @@
|
|||
},
|
||||
"StableDebtToken": {
|
||||
"buidlerevm": {
|
||||
"address": "0xB660Fdd109a95718cB9d20E3A89EE6cE342aDcB6",
|
||||
"address": "0x0Cf45557d25a4e4c0F1aC65EF6c48ae67c61a0E6",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"localhost": {
|
||||
|
@ -432,7 +432,7 @@
|
|||
},
|
||||
"VariableDebtToken": {
|
||||
"buidlerevm": {
|
||||
"address": "0x830bceA96E56DBC1F8578f75fBaC0AF16B32A07d",
|
||||
"address": "0x7fAeC7791277Ff512c41CA903c177B2Ed952dDAc",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"localhost": {
|
||||
|
@ -446,7 +446,7 @@
|
|||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
},
|
||||
"buidlerevm": {
|
||||
"address": "0xA0AB1cB92A4AF81f84dCd258155B5c25D247b54E",
|
||||
"address": "0x33958cC3535Fc328369EAC2B2Bebd120D67C7fa1",
|
||||
"deployer": "0xc783df8a850f42e7F7e57013759C285caa701eB6"
|
||||
}
|
||||
},
|
||||
|
|
|
@ -103,7 +103,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);
|
||||
});
|
||||
|
@ -116,7 +122,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),
|
||||
|
|
|
@ -278,11 +278,34 @@ export const withdraw = async (
|
|||
}
|
||||
};
|
||||
|
||||
export const delegateBorrowAllowance = async (
|
||||
reserveSymbol: string,
|
||||
amount: string,
|
||||
user: SignerWithAddress,
|
||||
receiver: tEthereumAddress,
|
||||
testEnv: TestEnv
|
||||
) => {
|
||||
const {pool} = testEnv;
|
||||
|
||||
const reserve = await getReserveAddressFromSymbol(reserveSymbol);
|
||||
const amountToDelegate = await convertToCurrencyDecimals(reserve, amount);
|
||||
|
||||
await pool
|
||||
.connect(user.signer)
|
||||
.delegateBorrowAllowance(receiver, reserve, amountToDelegate.toString());
|
||||
expect(
|
||||
(
|
||||
await pool['getBorrowAllowance(address,address,address)'](user.address, receiver, reserve)
|
||||
).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,
|
||||
|
@ -294,15 +317,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);
|
||||
|
@ -317,7 +343,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(),
|
||||
|
@ -364,7 +390,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;
|
||||
}
|
||||
|
@ -845,10 +871,15 @@ const getTxCostAndTimestamp = async (tx: ContractReceipt) => {
|
|||
return {txCost, txTimestamp};
|
||||
};
|
||||
|
||||
const getContractsData = async (reserve: string, user: string, testEnv: TestEnv) => {
|
||||
const getContractsData = async (
|
||||
reserve: string,
|
||||
user: string,
|
||||
testEnv: TestEnv,
|
||||
sender?: string
|
||||
) => {
|
||||
const {pool} = testEnv;
|
||||
const reserveData = await getReserveData(pool, reserve);
|
||||
const userData = await getUserData(pool, reserve, user);
|
||||
const userData = await getUserData(pool, reserve, user, sender || user);
|
||||
const timestamp = await timeLatest();
|
||||
|
||||
return {
|
||||
|
|
|
@ -12,6 +12,7 @@ import {
|
|||
redirectInterestStream,
|
||||
redirectInterestStreamOf,
|
||||
allowInterestRedirectionTo,
|
||||
delegateBorrowAllowance,
|
||||
} from './actions';
|
||||
import {RateMode} from '../../helpers/types';
|
||||
|
||||
|
@ -102,6 +103,18 @@ 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, user, toUser, testEnv);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'withdraw':
|
||||
{
|
||||
const {amount} = action.args;
|
||||
|
@ -115,13 +128,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;
|
||||
|
||||
|
|
|
@ -955,6 +955,85 @@
|
|||
"expected": "success"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "User 0 deposits 1000 DAI, user 0 delegates borrowing of 1 WETH to user 4, user 4 borrows 1 WETH on behalf of user 0",
|
||||
"actions": [
|
||||
{
|
||||
"name": "mint",
|
||||
"args": {
|
||||
"reserve": "DAI",
|
||||
"amount": "1000",
|
||||
"user": "0"
|
||||
},
|
||||
"expected": "success"
|
||||
},
|
||||
{
|
||||
"name": "approve",
|
||||
"args": {
|
||||
"reserve": "DAI",
|
||||
"user": "0"
|
||||
},
|
||||
"expected": "success"
|
||||
},
|
||||
{
|
||||
"name": "deposit",
|
||||
"args": {
|
||||
"reserve": "DAI",
|
||||
"amount": "1000",
|
||||
"user": "0"
|
||||
},
|
||||
"expected": "success"
|
||||
},
|
||||
{
|
||||
"name": "delegateBorrowAllowance",
|
||||
"args": {
|
||||
"reserve": "WETH",
|
||||
"amount": "1",
|
||||
"user": "0",
|
||||
"toUser": "4"
|
||||
},
|
||||
"expected": "success"
|
||||
},
|
||||
{
|
||||
"name": "borrow",
|
||||
"args": {
|
||||
"reserve": "WETH",
|
||||
"amount": "1",
|
||||
"user": "4",
|
||||
"onBehalfOf": "0",
|
||||
"borrowRateMode": "variable"
|
||||
},
|
||||
"expected": "success"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"description": "User 0 delegates borrowing of 1 WETH to user 4, user 4 borrows 2 WETH on behalf of user 0, revert expected",
|
||||
"actions": [
|
||||
{
|
||||
"name": "delegateBorrowAllowance",
|
||||
"args": {
|
||||
"reserve": "WETH",
|
||||
"amount": "1",
|
||||
"user": "0",
|
||||
"toUser": "4"
|
||||
},
|
||||
"expected": "success"
|
||||
},
|
||||
{
|
||||
"name": "borrow",
|
||||
"args": {
|
||||
"reserve": "WETH",
|
||||
"amount": "2",
|
||||
"user": "4",
|
||||
"onBehalfOf": "0",
|
||||
"borrowRateMode": "variable"
|
||||
},
|
||||
"expected": "revert",
|
||||
"revertMessage": "52"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -61,7 +61,8 @@ export const getReserveData = async (
|
|||
export const getUserData = async (
|
||||
pool: LendingPool,
|
||||
reserve: string,
|
||||
user: string
|
||||
user: tEthereumAddress,
|
||||
sender?: tEthereumAddress
|
||||
): Promise<UserReserveData> => {
|
||||
const [userData, aTokenData] = await Promise.all([
|
||||
pool.getUserReserveData(reserve, user),
|
||||
|
@ -77,7 +78,7 @@ export const getUserData = async (
|
|||
] = aTokenData;
|
||||
|
||||
const token = await getMintableErc20(reserve);
|
||||
const walletBalance = new BigNumber((await token.balanceOf(user)).toString());
|
||||
const walletBalance = new BigNumber((await token.balanceOf(sender || user)).toString());
|
||||
|
||||
return {
|
||||
principalATokenBalance: new BigNumber(principalATokenBalance),
|
||||
|
|
|
@ -59,7 +59,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);
|
||||
|
||||
|
@ -252,7 +252,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
|
||||
|
||||
|
|
|
@ -56,7 +56,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);
|
||||
|
||||
|
@ -222,7 +222,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(
|
||||
|
|
Loading…
Reference in New Issue
Block a user