Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🔒️ do creditor actions on a flashActionByCreditor via callback #133

Merged
merged 4 commits into from
Mar 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/accounts-v2
Submodule accounts-v2 updated 98 files
+27 −5 src/Factory.sol
+81 −41 src/Registry.sol
+32 −0 src/abstracts/Creditor.sol
+59 −37 src/accounts/AccountV1.sol
+3 −3 src/actions/MultiCall.sol
+3 −3 src/asset-modules/ERC20-Primaries/ERC20PrimaryAM.sol
+9 −7 src/asset-modules/Stargate-Finance/StakedStargateAM.sol
+3 −3 src/asset-modules/Stargate-Finance/StargateAM.sol
+15 −19 src/asset-modules/UniswapV3/UniswapV3AM.sol
+7 −34 src/asset-modules/abstracts/AbstractAM.sol
+5 −18 src/asset-modules/abstracts/AbstractDerivedAM.sol
+2 −15 src/asset-modules/abstracts/AbstractPrimaryAM.sol
+29 −33 src/asset-modules/abstracts/AbstractStakingAM.sol
+2 −1 src/asset-modules/interfaces/IRegistry.sol
+2 −27 src/interfaces/IAssetModule.sol
+6 −0 src/interfaces/ICreditor.sol
+2 −0 src/interfaces/IERC721.sol
+17 −8 src/interfaces/IRegistry.sol
+4 −2 src/libraries/Errors.sol
+33 −3 test/fork/Fork.t.sol
+8 −5 test/fork/asset-modules/stargate/ETHPool.fork.t.sol
+23 −32 test/fork/asset-modules/stargate/USDbCPool.fork.t.sol
+48 −0 test/fuzz/Creditor/FlashActionCallback.fuzz.t.sol
+32 −0 test/fuzz/Creditor/_Creditor.fuzz.t.sol
+7 −7 test/fuzz/Factory/CreateAccount.fuzz.t.sol
+9 −1 test/fuzz/Factory/SafeTransferAccount.fuzz.sol
+213 −95 test/fuzz/Factory/TransferFrom.fuzz.sol
+27 −8 test/fuzz/Registry/AddAsset.fuzz.t.sol
+51 −0 test/fuzz/Registry/BatchGetAssetTypes.fuzz.t.sol
+5 −26 test/fuzz/Registry/BatchProcessDeposit.fuzz.t.sol
+9 −9 test/fuzz/Registry/BatchProcessWithdrawal.fuzz.t.sol
+2 −2 test/fuzz/Registry/GetRiskFactors.fuzz.t.sol
+1 −1 test/fuzz/Registry/GetUsdValueExposureToUnderlyingAssetAfterDeposit.fuzz.t.sol
+1 −1 test/fuzz/Registry/GetUsdValueExposureToUnderlyingAssetAfterWithdrawal.fuzz.t.sol
+2 −2 test/fuzz/Registry/GetValuesInUsd.fuzz.t.sol
+1 −1 test/fuzz/Registry/GetValuesInUsdRecursive.fuzz.t.sol
+2 −2 test/fuzz/Registry/SetRiskParametersOfPrimaryAsset.fuzz.t.sol
+254 −7 test/fuzz/accounts/AccountV1/AuctionBid.fuzz.t.sol
+22 −31 test/fuzz/accounts/AccountV1/Deposit.fuzz.t.sol
+10 −10 test/fuzz/accounts/AccountV1/FlashAction.fuzz.t.sol
+151 −100 test/fuzz/accounts/AccountV1/FlashActionByCreditor.fuzz.t.sol
+12 −12 test/fuzz/accounts/AccountV1/Skim.fuzz.t.sol
+0 −54 test/fuzz/accounts/AccountV1/UpdateActionTimestampByCreditor.fuzz.t.sol
+3 −3 test/fuzz/accounts/AccountV1/Withdraw.fuzz.t.sol
+1 −1 test/fuzz/accounts/AccountV1/_AccountV1.fuzz.t.sol
+1 −1 test/fuzz/actions/MultiCall/ExecuteAction.fuzz.t.sol
+2 −0 test/fuzz/asset-modules/AbstractAM/Constructor.fuzz.t.sol
+0 −46 test/fuzz/asset-modules/AbstractAM/ProcessAsset.fuzz.t.sol
+2 −0 test/fuzz/asset-modules/AbstractDerivedAM/Constructor.fuzz.t.sol
+2 −2 test/fuzz/asset-modules/AbstractDerivedAM/GetRiskFactors.fuzz.t.sol
+1 −2 test/fuzz/asset-modules/AbstractDerivedAM/ProcessDirectDeposit.fuzz.t.sol
+1 −5 test/fuzz/asset-modules/AbstractDerivedAM/ProcessDirectWithdrawal.fuzz.t.sol
+1 −1 test/fuzz/asset-modules/AbstractDerivedAM/_AbstractDerivedAM.fuzz.t.sol
+2 −0 test/fuzz/asset-modules/AbstractPrimaryAM/Constructor.fuzz.t.sol
+1 −2 test/fuzz/asset-modules/AbstractPrimaryAM/ProcessDirectDeposit.fuzz.t.sol
+2 −8 test/fuzz/asset-modules/AbstractPrimaryAM/ProcessDirectWithdrawal.fuzz.t.sol
+6 −10 test/fuzz/asset-modules/AbstractStakingAM/Burn.fuzz.t.sol
+5 −10 test/fuzz/asset-modules/AbstractStakingAM/ClaimReward.fuzz.t.sol
+36 −0 test/fuzz/asset-modules/AbstractStakingAM/Constructor.fuzz.t.sol
+13 −22 test/fuzz/asset-modules/AbstractStakingAM/DecreaseLiquidity.fuzz.t.sol
+20 −57 test/fuzz/asset-modules/AbstractStakingAM/GetRewardBalances.fuzz.t.sol
+4 −7 test/fuzz/asset-modules/AbstractStakingAM/IncreaseLiquidity.fuzz.t.sol
+5 −10 test/fuzz/asset-modules/AbstractStakingAM/Mint.fuzz.t.sol
+1 −1 test/fuzz/asset-modules/AbstractStakingAM/RewardOf.fuzz.t.sol
+9 −15 test/fuzz/asset-modules/AbstractStakingAM/_AbstractStakingAM.fuzz.t.sol
+2 −1 test/fuzz/asset-modules/ERC20PrimaryAM/AddAsset.fuzz.t.sol
+1 −1 test/fuzz/asset-modules/ERC20PrimaryAM/Constructor.fuzz.t.sol
+2 −1 test/fuzz/asset-modules/FloorERC1155AM/AddAsset.fuzz.t.sol
+1 −1 test/fuzz/asset-modules/FloorERC1155AM/Constructor.fuzz.t.sol
+1 −2 test/fuzz/asset-modules/FloorERC1155AM/ProcessDirectDeposit.fuzz.t.sol
+2 −1 test/fuzz/asset-modules/FloorERC721AM/AddAsset.fuzz.t.sol
+1 −1 test/fuzz/asset-modules/FloorERC721AM/Constructor.fuzz.t.sol
+1 −2 test/fuzz/asset-modules/FloorERC721AM/ProcessDirectDeposit.fuzz.t.sol
+1 −1 test/fuzz/asset-modules/StakedStargateAM/AddAsset.fuzz.t.sol
+2 −2 test/fuzz/asset-modules/StakedStargateAM/Constructor.fuzz.t.sol
+4 −4 test/fuzz/asset-modules/StakedStargateAM/StakeAndClaim.fuzz.t.sol
+4 −4 test/fuzz/asset-modules/StakedStargateAM/WithdrawAndClaim.fuzz.t.sol
+1 −1 test/fuzz/asset-modules/StandardERC4626AM/Constructor.fuzz.t.sol
+1 −1 test/fuzz/asset-modules/StargateAM/Constructor.fuzz.t.sol
+1 −1 test/fuzz/asset-modules/UniswapV2AM/Constructor.fuzz.t.sol
+1 −1 test/fuzz/asset-modules/UniswapV3AM/Constructor.fuzz.t.sol
+1 −1 test/fuzz/asset-modules/UniswapV3AM/GetPrincipalAmounts.fuzz.t.sol
+8 −8 test/fuzz/asset-modules/UniswapV3AM/GetSqrtPriceX96.fuzz.t.sol
+10 −15 test/fuzz/asset-modules/UniswapV3AM/GetUnderlyingAssetsAmounts.fuzz.t.sol
+2 −2 test/fuzz/asset-modules/UniswapV3AM/GetValue.fuzz.t.sol
+6 −6 test/fuzz/asset-modules/UniswapV3AM/_UniswapV3AM.fuzz.t.sol
+2 −4 test/fuzz/asset-modules/UniswapV3AM/processDirectDeposit.fuzz.t.sol
+6 −24 test/fuzz/asset-modules/UniswapV3AM/processDirectWithdrawal.t.sol
+1 −1 test/invariant/handlers/FactoryHandler.sol
+9 −8 test/utils/Extensions.sol
+10 −18 test/utils/mocks/accounts/AccountV2.sol
+3 −11 test/utils/mocks/asset-modules/AssetModuleMock.sol
+4 −9 test/utils/mocks/asset-modules/FloorERC1155AM.sol
+4 −9 test/utils/mocks/asset-modules/FloorERC721AM.sol
+6 −2 test/utils/mocks/asset-modules/StakingAMMock.sol
+3 −3 test/utils/mocks/asset-modules/StandardERC4626AM.sol
+3 −3 test/utils/mocks/asset-modules/UniswapV2AM.sol
+34 −7 test/utils/mocks/creditors/CreditorMock.sol
58 changes: 35 additions & 23 deletions src/LendingPool.sol
Original file line number Diff line number Diff line change
Expand Up @@ -540,18 +540,47 @@ contract LendingPool is LendingPoolGuardian, Creditor, DebtToken, ILendingPool {
address accountOwner = IFactory(ACCOUNT_FACTORY).ownerOfAccount(account);
if (accountOwner == address(0)) revert LendingPoolErrors.IsNotAnAccount();

uint256 amountBorrowedWithFee = amountBorrowed + amountBorrowed.mulDivUp(originationFee, ONE_4);

// Check allowances to take debt.
if (accountOwner != msg.sender) {
// Since calling accountManagementAction() gives the sender full control over all assets in the Account,
// Calling flashActionByCreditor() gives the sender full control over all assets in the Account,
// Only Beneficiaries with maximum allowance can call the flashAction function.
if (creditAllowance[account][accountOwner][msg.sender] != type(uint256).max) {
revert LendingPoolErrors.Unauthorized();
}
}

// Mint debt tokens to the Account, debt must be minted before the actions in the Account are performed.
// Prepare callback of the Account.
// The borrowing of funds during a flashAction has to be executed via a callback of the Account.
// As such the Account cannot be reentered in between the time that funds are borrowed and the final health check is done.
callbackAccount = account;
bytes memory callbackData = abi.encode(amountBorrowed, actionTarget, msg.sender, referrer);

// The Action Target will use the borrowed funds (optionally with additional assets withdrawn from the Account)
// to execute one or more actions (swap, deposit, mint...).
// Next the action Target will deposit any of the remaining funds or any of the recipient token
// resulting from the actions back into the Account.
// As last step, after all assets are deposited back into the Account a final health check is done:
// The Collateral Value of all assets in the Account must be bigger than the total liabilities against the Account (including the debt taken during this function).
// flashActionByCreditor also checks that the Account indeed has opened a margin account for this Lending Pool.
{
uint256 accountVersion = IAccount(account).flashActionByCreditor(callbackData, actionTarget, actionData);
if (!isValidVersion[accountVersion]) revert LendingPoolErrors.InvalidVersion();
}
}

/**
* @notice Callback of the Account during a flashAction.
* @param account The contract address of the Arcadia Account.
* @param callbackData The data for the borrow during a flashAction.
* @dev During the callback, the Account cannot be reentered and the actionTimestamp is updated.
*/
function _flashActionCallback(address account, bytes calldata callbackData) internal override {
(uint256 amountBorrowed, address actionTarget, address sender, bytes3 referrer) =
abi.decode(callbackData, (uint256, address, address, bytes3));

uint256 amountBorrowedWithFee = amountBorrowed + amountBorrowed.mulDivUp(originationFee, ONE_4);

// Mint debt tokens to the Account.
_deposit(amountBorrowedWithFee, account);

// Add origination fee to the treasury.
Expand All @@ -562,29 +591,12 @@ contract LendingPool is LendingPoolGuardian, Creditor, DebtToken, ILendingPool {
}
}

// Need to update the actionTimestamp before transferring tokens,
// or ERC777s could reenter to frontrun Account transfers.
IAccount(account).updateActionTimestampByCreditor();

// Send Borrowed funds to the actionTarget.
// Transfer fails if there is insufficient liquidity in the pool.
asset.safeTransfer(actionTarget, amountBorrowed);

// The Action Target will use the borrowed funds (optionally with additional assets withdrawn from the Account)
// to execute one or more actions (swap, deposit, mint...).
// Next the action Target will deposit any of the remaining funds or any of the recipient token
// resulting from the actions back into the Account.
// As last step, after all assets are deposited back into the Account a final health check is done:
// The Collateral Value of all assets in the Account is bigger than the total liabilities against the Account (including the debt taken during this function).
// flashActionByCreditor also checks that the Account indeed has opened a margin account for this Lending Pool.
{
uint256 accountVersion = IAccount(account).flashActionByCreditor(actionTarget, actionData);
if (!isValidVersion[accountVersion]) revert LendingPoolErrors.InvalidVersion();
}

unchecked {
emit Borrow(
account, msg.sender, actionTarget, amountBorrowed, amountBorrowedWithFee - amountBorrowed, referrer
);
emit Borrow(account, sender, actionTarget, amountBorrowed, amountBorrowedWithFee - amountBorrowed, referrer);
}
}

Expand Down
9 changes: 3 additions & 6 deletions src/interfaces/IAccount.sol
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,6 @@ interface IAccount {
*/
function getUsedMargin() external view returns (uint256);

/**
* @notice Updates the actionTimestamp
*/
function updateActionTimestampByCreditor() external;

/**
* @notice Checks if the Account is still healthy for an updated open position.
* @param openPosition The new open position.
Expand All @@ -47,7 +42,9 @@ interface IAccount {
* The second bytes object contains the encoded input for the actionTarget.
* @return accountVersion The current Account version.
*/
function flashActionByCreditor(address actionTarget, bytes calldata actionData) external returns (uint256);
function flashActionByCreditor(bytes calldata callbackData, address actionTarget, bytes calldata actionData)
external
returns (uint256);

/**
* @notice Checks if an Account is liquidatable and continues the liquidation flow.
Expand Down
1 change: 1 addition & 0 deletions test/fuzz/LendingPool/AuctionRepay.fuzz.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ contract AuctionRepay_LendingPool_Fuzz_Test is LendingPool_Fuzz_Test {
vm.assume(sender != address(0));
vm.assume(sender != users.liquidityProvider);
vm.assume(sender != users.accountOwner);
vm.assume(sender != address(proxyAccount));

depositTokenInAccount(proxyAccount, mockERC20.stable1, amountLoaned);

Expand Down
5 changes: 2 additions & 3 deletions test/fuzz/LendingPool/FlashAction.fuzz.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,7 @@ contract FlashAction_LendingPool_Fuzz_Test is LendingPool_Fuzz_Test {
function testFuzz_Revert_flashAction_InsufficientLiquidity(
uint128 amountLoaned,
uint112 collateralValue,
uint128 liquidity,
bytes calldata actionData
uint128 liquidity
) public {
// Given: collateralValue is smaller than maxExposure.
collateralValue = uint112(bound(collateralValue, 0, type(uint112).max - 1));
Expand All @@ -110,7 +109,7 @@ contract FlashAction_LendingPool_Fuzz_Test is LendingPool_Fuzz_Test {

vm.startPrank(users.accountOwner);
vm.expectRevert("TRANSFER_FAILED");
pool.flashAction(amountLoaned, address(proxyAccount), address(actionHandler), actionData, emptyBytes3);
pool.flashAction(amountLoaned, address(proxyAccount), address(actionHandler), callData, emptyBytes3);
vm.stopPrank();
}

Expand Down
114 changes: 114 additions & 0 deletions test/fuzz/LendingPool/FlashActionCallback.fuzz.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
/**
* Created by Pragma Labs
* SPDX-License-Identifier: BUSL-1.1
*/
pragma solidity 0.8.22;

import { LendingPool_Fuzz_Test } from "./_LendingPool.fuzz.t.sol";

import { FixedPointMathLib } from "../../../lib/solmate/src/utils/FixedPointMathLib.sol";

import { ActionData } from "../../../lib/accounts-v2/src/interfaces/IActionBase.sol";
import { ActionMultiCall } from "../../../lib/accounts-v2/src/actions/MultiCall.sol";
import { IPermit2 } from "../../../lib/accounts-v2/src/interfaces/IPermit2.sol";

/**
* @notice Fuzz tests for the function "flashActionCallback" of contract "LendingPool".
*/
contract FlashActionCallback_LendingPool_Fuzz_Test is LendingPool_Fuzz_Test {
using FixedPointMathLib for uint256;

/* ///////////////////////////////////////////////////////////////
TEST CONTRACTS
/////////////////////////////////////////////////////////////// */

ActionMultiCall internal actionHandler;
bytes internal callData;

/* ///////////////////////////////////////////////////////////////
SETUP
/////////////////////////////////////////////////////////////// */

function setUp() public override {
LendingPool_Fuzz_Test.setUp();
}

/*//////////////////////////////////////////////////////////////
TESTS
//////////////////////////////////////////////////////////////*/
function testFuzz_Revert_flashActionCallback_Unauthorised(
address account,
address sender,
bytes calldata callbackData
) public {
vm.assume(account != sender);

pool.setCallbackAccount(account);

vm.prank(sender);
vm.expectRevert(Unauthorized.selector);
pool.flashActionCallback(callbackData);
}

function testFuzz_Revert_flashActionCallback_InsufficientLiquidity(
uint128 amountLoaned,
uint128 liquidity,
address account,
address actionTarget,
address sender,
bytes3 referrer
) public {
vm.assume(liquidity < amountLoaned);
vm.assume(liquidity > 0);

vm.prank(address(srTranche));
pool.depositInLendingPool(liquidity, users.liquidityProvider);

pool.setCallbackAccount(account);
bytes memory callbackData = abi.encode(amountLoaned, actionTarget, sender, referrer);

vm.prank(account);
vm.expectRevert("TRANSFER_FAILED");
pool.flashActionCallback(callbackData);
}

function testFuzz_Success_flashActionCallback(
uint128 amountLoaned,
uint128 liquidity,
address account,
address actionTarget,
address sender,
bytes3 referrer,
uint8 originationFee
) public {
vm.assume(liquidity >= amountLoaned);
uint256 fee = uint256(amountLoaned).mulDivUp(originationFee, 10_000);
vm.assume(liquidity <= type(uint128).max - fee);
vm.assume(amountLoaned > 0);

vm.prank(users.creatorAddress);
pool.setOriginationFee(originationFee);

vm.prank(users.liquidityProvider);
mockERC20.stable1.approve(address(pool), type(uint256).max);

vm.prank(address(srTranche));
pool.depositInLendingPool(liquidity, users.liquidityProvider);

pool.setCallbackAccount(account);
bytes memory callbackData = abi.encode(amountLoaned, actionTarget, sender, referrer);

vm.startPrank(account);
vm.expectEmit(true, true, true, true);
emit Borrow(account, sender, actionTarget, amountLoaned, fee, referrer);
pool.flashActionCallback(callbackData);
vm.stopPrank();

assertEq(pool.getCallbackAccount(), address(0));
assertEq(mockERC20.stable1.balanceOf(address(pool)), liquidity - amountLoaned);
assertEq(mockERC20.stable1.balanceOf(actionTarget), amountLoaned);
assertEq(debt.balanceOf(account), uint256(amountLoaned) + fee);
assertEq(pool.liquidityOf(treasury), fee);
assertEq(pool.totalLiquidity(), liquidity + fee);
}
}
4 changes: 2 additions & 2 deletions test/fuzz/LendingPool/LiquidityOf.fuzz.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ contract LiquidityOf_LendingPool_Fuzz_Test is LendingPool_Fuzz_Test {
vm.stopPrank();

// Given: collateralValue is smaller than maxExposure.
realisedDebt = uint112(bound(realisedDebt, 0, type(uint112).max - 1));
realisedDebt = uint112(bound(realisedDebt, 1, type(uint112).max - 1));
vm.assume(deltaTimestamp <= 5 * 365 * 24 * 60 * 60); // 5 year
vm.assume(interestRate <= 1e3 * 10 ** 18); // 1000%
vm.assume(interestRate > 0);
Expand Down Expand Up @@ -153,7 +153,7 @@ contract LiquidityOf_LendingPool_Fuzz_Test is LendingPool_Fuzz_Test {
pool.setInterestWeightTranche(0, totalInterestWeight);

// Given: collateralValue is smaller than maxExposure.
realisedDebt = uint112(bound(realisedDebt, 0, type(uint112).max - 1));
realisedDebt = uint112(bound(realisedDebt, 1, type(uint112).max - 1));
vm.assume(deltaTimestamp <= 5 * 365 * 24 * 60 * 60); // 5 year
vm.assume(interestRate <= 1e3 * 10 ** 18); // 1000%
vm.assume(interestRate > 0);
Expand Down
12 changes: 6 additions & 6 deletions test/scenario/LeveragedActions.scenario.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,7 @@ contract LeveragedActions_Scenario_Test is Scenario_Lending_Test {
});

withdrawData.assets[0] = address(mockERC20.stable1);
withdrawData.assetTypes[0] = 0;
withdrawData.assetTypes[0] = 1;
withdrawData.assetIds[0] = 0;
withdrawData.assetAmounts[0] = stableCollateral;

Expand All @@ -220,7 +220,7 @@ contract LeveragedActions_Scenario_Test is Scenario_Lending_Test {
});

depositData.assets[0] = address(mockERC20.token1);
depositData.assetTypes[0] = 0;
depositData.assetTypes[0] = 1;
withdrawData.assetIds[0] = 0;

ActionData memory transferFromOwner;
Expand Down Expand Up @@ -304,7 +304,7 @@ contract LeveragedActions_Scenario_Test is Scenario_Lending_Test {
});

withdrawData.assets[0] = address(mockERC20.stable1);
withdrawData.assetTypes[0] = 0;
withdrawData.assetTypes[0] = 1;
withdrawData.assetIds[0] = 0;
withdrawData.assetAmounts[0] = stableCollateral;

Expand All @@ -316,7 +316,7 @@ contract LeveragedActions_Scenario_Test is Scenario_Lending_Test {
});

depositData.assets[0] = address(mockERC20.token1);
depositData.assetTypes[0] = 0;
depositData.assetTypes[0] = 1;
withdrawData.assetIds[0] = 0;

ActionData memory transferFromOwner;
Expand Down Expand Up @@ -429,7 +429,7 @@ contract LeveragedActions_Scenario_Test is Scenario_Lending_Test {
});

withdrawData.assets[0] = address(mockERC20.stable1);
withdrawData.assetTypes[0] = 0;
withdrawData.assetTypes[0] = 1;
withdrawData.assetIds[0] = 0;
withdrawData.assetAmounts[0] = stableCollateral;

Expand All @@ -441,7 +441,7 @@ contract LeveragedActions_Scenario_Test is Scenario_Lending_Test {
});

depositData.assets[0] = address(mockERC20.token1);
depositData.assetTypes[0] = 0;
depositData.assetTypes[0] = 1;
withdrawData.assetIds[0] = 0;

ActionData memory transferFromOwner;
Expand Down
8 changes: 8 additions & 0 deletions test/utils/Extensions.sol
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,14 @@ contract LendingPoolExtension is LendingPool {
LendingPool(riskManager_, asset_, treasury_, account_factory, liquidator_)
{ }

function getCallbackAccount() public view returns (address callbackAccount_) {
callbackAccount_ = callbackAccount;
}

function setCallbackAccount(address callbackAccount_) public {
callbackAccount = callbackAccount_;
}

function getMaxTotalPenalty() public pure returns (uint256 maxTotalPenalty) {
maxTotalPenalty = MAX_TOTAL_PENALTY;
}
Expand Down
Loading