Skip to content

Commit 495b17a

Browse files
committed
Merge branch 'feat-optimize-borrow' into update-test-conf
2 parents 2d34795 + 6771c4c commit 495b17a

File tree

5 files changed

+57
-39
lines changed

5 files changed

+57
-39
lines changed

contracts/LiquidityPool.sol

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ pragma solidity 0.8.28;
44
import {IERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
55
import {BitMaps} from "@openzeppelin/contracts/utils/structs/BitMaps.sol";
66
import {AccessControl} from "@openzeppelin/contracts/access/AccessControl.sol";
7-
import {Pausable} from "@openzeppelin/contracts/utils/Pausable.sol";
87
import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
98
import {EIP712} from "@openzeppelin/contracts/utils/cryptography/EIP712.sol";
109
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
@@ -21,7 +20,7 @@ import {IBorrower} from "./interfaces/IBorrower.sol";
2120
/// Borrowing can be paused by the WITHDRAW_PROFIT_ROLE before withdrawing the profit.
2221
/// The contract is pausable by the PAUSER_ROLE.
2322
/// @author Tanya Bushenyova <[email protected]>
24-
contract LiquidityPool is ILiquidityPool, AccessControl, EIP712, Pausable {
23+
contract LiquidityPool is ILiquidityPool, AccessControl, EIP712 {
2524
using SafeERC20 for IERC20;
2625
using ECDSA for bytes32;
2726
using BitMaps for BitMaps.BitMap;
@@ -40,11 +39,12 @@ contract LiquidityPool is ILiquidityPool, AccessControl, EIP712, Pausable {
4039

4140
IERC20 immutable public ASSETS;
4241

43-
bool public borrowPaused;
44-
address public mpcAddress;
42+
BitMaps.BitMap private _usedNonces;
4543
uint256 public totalDeposited;
4644

47-
BitMaps.BitMap private _usedNonces;
45+
bool public paused;
46+
bool public borrowPaused;
47+
address public mpcAddress;
4848

4949
bytes32 public constant LIQUIDITY_ADMIN_ROLE = "LIQUIDITY_ADMIN_ROLE";
5050
bytes32 public constant WITHDRAW_PROFIT_ROLE = "WITHDRAW_PROFIT_ROLE";
@@ -62,13 +62,27 @@ contract LiquidityPool is ILiquidityPool, AccessControl, EIP712, Pausable {
6262
error InvalidBorrowToken();
6363
error NotImplemented();
6464
error NoProfit();
65+
error EnforcedPause();
66+
error ExpectedPause();
6567

6668
event Deposit(address from, uint256 amount);
6769
event Withdraw(address caller, address to, uint256 amount);
6870
event ProfitWithdrawn(address token, address to, uint256 amount);
6971
event BorrowPaused();
7072
event BorrowUnpaused();
7173
event MPCAddressSet(address oldMPCAddress, address newMPCAddress);
74+
event Paused(address account);
75+
event Unpaused(address account);
76+
77+
modifier whenNotPaused() {
78+
require(!paused, EnforcedPause());
79+
_;
80+
}
81+
82+
modifier whenPaused() {
83+
require(paused, ExpectedPause());
84+
_;
85+
}
7286

7387
constructor(
7488
address liquidityToken,
@@ -181,15 +195,13 @@ contract LiquidityPool is ILiquidityPool, AccessControl, EIP712, Pausable {
181195
}
182196

183197
function pause() external override onlyRole(PAUSER_ROLE) whenNotPaused() {
184-
_pause();
198+
paused = true;
199+
emit Paused(msg.sender);
185200
}
186201

187202
function unpause() external override onlyRole(PAUSER_ROLE) whenPaused() {
188-
_unpause();
189-
}
190-
191-
function paused() public view override(Pausable, ILiquidityPool) returns (bool) {
192-
return super.paused();
203+
paused = false;
204+
emit Unpaused(msg.sender);
193205
}
194206

195207
// Internal functions

contracts/LiquidityPoolAave.sol

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,15 @@ import {LiquidityPool} from "./LiquidityPool.sol";
2323
contract LiquidityPoolAave is LiquidityPool {
2424
using SafeERC20 for IERC20;
2525

26-
uint256 private constant MULTIPLIER = 1e18;
26+
uint256 private constant MULTIPLIER = 10000;
2727

2828
IAavePoolAddressesProvider immutable public AAVE_POOL_PROVIDER;
2929
IAavePool immutable public AAVE_POOL;
3030
IERC20 immutable public ATOKEN;
3131
uint8 immutable public ASSETS_DECIMALS;
3232

33-
uint256 public minHealthFactor;
34-
uint256 public defaultLTV;
33+
uint32 public minHealthFactor;
34+
uint32 public defaultLTV;
3535

3636
mapping(address token => uint256 ltv) public borrowTokenLTV;
3737

@@ -55,8 +55,8 @@ contract LiquidityPoolAave is LiquidityPool {
5555
address aavePoolProvider,
5656
address admin,
5757
address mpcAddress_,
58-
uint256 minHealthFactor_,
59-
uint256 defaultLTV_
58+
uint32 minHealthFactor_,
59+
uint32 defaultLTV_
6060
) LiquidityPool(liquidityToken, admin, mpcAddress_) {
6161
ASSETS_DECIMALS = IERC20Metadata(liquidityToken).decimals();
6262
require(aavePoolProvider != address(0), ZeroAddress());
@@ -68,9 +68,8 @@ contract LiquidityPoolAave is LiquidityPool {
6868
IAavePoolDataProvider poolDataProvider = IAavePoolDataProvider(provider.getPoolDataProvider());
6969
(,,,,,bool usageAsCollateralEnabled,,,,) = poolDataProvider.getReserveConfigurationData(liquidityToken);
7070
require(usageAsCollateralEnabled, CollateralNotSupported());
71-
minHealthFactor = minHealthFactor_;
72-
defaultLTV = defaultLTV_;
73-
mpcAddress = mpcAddress_;
71+
_setHealthFactor(minHealthFactor_);
72+
_setDefaultLTV(defaultLTV_);
7473
}
7574

7675
function repay(address[] calldata borrowTokens) external override {
@@ -86,7 +85,7 @@ contract LiquidityPoolAave is LiquidityPool {
8685

8786
function setBorrowTokenLTVs(
8887
address[] calldata tokens,
89-
uint256[] calldata ltvs
88+
uint32[] calldata ltvs
9089
) external onlyRole(DEFAULT_ADMIN_ROLE) {
9190
require(tokens.length == ltvs.length, InvalidLength());
9291
for (uint256 i = 0; i < tokens.length; ++i) {
@@ -98,20 +97,28 @@ contract LiquidityPoolAave is LiquidityPool {
9897
}
9998
}
10099

101-
function setDefaultLTV(uint256 defaultLTV_) external onlyRole(DEFAULT_ADMIN_ROLE) {
102-
uint256 oldDefaultLTV = defaultLTV;
100+
function setDefaultLTV(uint32 defaultLTV_) external onlyRole(DEFAULT_ADMIN_ROLE) {
101+
_setDefaultLTV(defaultLTV_);
102+
}
103+
104+
function setHealthFactor(uint32 minHealthFactor_) external onlyRole(DEFAULT_ADMIN_ROLE) {
105+
_setHealthFactor(minHealthFactor_);
106+
}
107+
108+
// Internal functions
109+
110+
function _setDefaultLTV(uint32 defaultLTV_) internal {
111+
uint32 oldDefaultLTV = defaultLTV;
103112
defaultLTV = defaultLTV_;
104113
emit DefaultLTVSet(oldDefaultLTV, defaultLTV_);
105114
}
106115

107-
function setHealthFactor(uint256 minHealthFactor_) external onlyRole(DEFAULT_ADMIN_ROLE) {
108-
uint256 oldHealthFactor = minHealthFactor;
116+
function _setHealthFactor(uint32 minHealthFactor_) internal {
117+
uint32 oldHealthFactor = minHealthFactor;
109118
minHealthFactor = minHealthFactor_;
110119
emit HealthFactorSet(oldHealthFactor, minHealthFactor_);
111120
}
112121

113-
// Internal functions
114-
115122
function _checkTokenLTV(address borrowToken) private view {
116123
uint256 ltv = borrowTokenLTV[borrowToken];
117124
if (ltv == 0) ltv = defaultLTV;
@@ -160,7 +167,7 @@ contract LiquidityPoolAave is LiquidityPool {
160167

161168
// - Check health factor for user after borrow (can be read from aave, getUserAccountData)
162169
(,,,,,uint256 currentHealthFactor) = AAVE_POOL.getUserAccountData(address(this));
163-
require(currentHealthFactor >= minHealthFactor, HealthFactorTooLow());
170+
require(currentHealthFactor / (1e18 / MULTIPLIER) >= minHealthFactor, HealthFactorTooLow());
164171

165172
// check ltv for token
166173
_checkTokenLTV(borrowToken);
@@ -172,7 +179,7 @@ contract LiquidityPoolAave is LiquidityPool {
172179
AAVE_POOL.withdraw(address(ASSETS), amount, to);
173180
// health factor after withdraw
174181
(,,,,,uint256 currentHealthFactor) = AAVE_POOL.getUserAccountData(address(this));
175-
require(currentHealthFactor >= minHealthFactor, HealthFactorTooLow());
182+
require(currentHealthFactor / (1e18 / MULTIPLIER) >= minHealthFactor, HealthFactorTooLow());
176183
emit WithdrawnFromAave(to, amount);
177184
}
178185

hardhat.config.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ task("grant-role", "Grant some role on some AccessControl")
3232

3333
task("set-default-ltv", "Update Liquidity Pool config")
3434
.addOptionalParam("pool", "Liquidity Pool proxy address or id", "LiquidityPoolAaveUSDC", types.string)
35-
.addOptionalParam("ltv", "New default LTV value", 20n * 10n**16n, types.bigint)
35+
.addOptionalParam("ltv", "New default LTV value, where 10000 is 100%", 2000n, types.bigint)
3636
.setAction(async ({pool, ltv}: {pool: string, ltv: bigint}, hre) => {
3737
const {resolveXAddress} = await loadTestHelpers();
3838
const [admin] = await hre.ethers.getSigners();
@@ -46,7 +46,7 @@ task("set-default-ltv", "Update Liquidity Pool config")
4646

4747
task("set-token-ltvs", "Update Liquidity Pool config")
4848
.addParam("tokens", "Comma separated list of tokens to update LTV for")
49-
.addParam("ltvs", "Comma separated list of new LTV values")
49+
.addParam("ltvs", "Comma separated list of new LTV values where 10000 is 100%")
5050
.addOptionalParam("pool", "Liquidity Pool proxy address or id", "LiquidityPoolAaveUSDC", types.string)
5151
.setAction(async (args: {tokens: string, ltvs: string, pool: string}, hre) => {
5252
const {resolveXAddress} = await loadTestHelpers();
@@ -65,7 +65,7 @@ task("set-token-ltvs", "Update Liquidity Pool config")
6565

6666
task("set-min-health-factor", "Update Liquidity Pool config")
6767
.addOptionalParam("pool", "Liquidity Pool proxy address or id", "LiquidityPoolAaveUSDC", types.string)
68-
.addOptionalParam("healthfactor", "New min health factor value", 500n * 10n**16n, types.bigint)
68+
.addOptionalParam("healthfactor", "New min health factor value, where 10000 is 1", 50000n, types.bigint)
6969
.setAction(async ({pool, healthfactor}: {pool: string, healthfactor: bigint}, hre) => {
7070
const {resolveXAddress} = await loadTestHelpers();
7171
const [admin] = await hre.ethers.getSigners();

scripts/deploy.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,8 @@ export async function main() {
9797
let mainPool: LiquidityPool;
9898
let aavePool: LiquidityPoolAave;
9999
if (config.AavePool) {
100-
const minHealthFactor = BigInt(config.AavePool.minHealthFactor) * 10n ** 18n / 100n;
101-
const defaultLTV = BigInt(config.AavePool.defaultLTV) * 10n ** 18n / 100n;
100+
const minHealthFactor = BigInt(config.AavePool.minHealthFactor) * 10000n / 100n;
101+
const defaultLTV = BigInt(config.AavePool.defaultLTV) * 10000n / 100n;
102102
console.log("Deploying AAVE Liquidity Pool");
103103
aavePool = (await verifier.deployX(
104104
"LiquidityPoolAave",

test/LiquidityPoolAave.ts

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,9 @@ describe("LiquidityPoolAave", function () {
6767
const UNI_DEC = 10n ** (await uni.decimals());
6868

6969
// Initialize health factor as 5 (500%)
70-
const healthFactor = 500n * 10n ** 18n / 100n;
70+
const healthFactor = 500n * 10000n / 100n;
7171
// Initialize token LTV as 5%
72-
const defaultLtv = 5n * 10n ** 18n / 100n;
72+
const defaultLtv = 5n * 10000n / 100n;
7373
const liquidityPool = (
7474
await deploy("LiquidityPoolAave", deployer, {},
7575
usdc.target, AAVE_POOL_PROVIDER, admin.address, mpc_signer.address, healthFactor, defaultLtv
@@ -894,7 +894,7 @@ describe("LiquidityPoolAave", function () {
894894
await expect(liquidityPool.connect(liquidityAdmin).deposit(amountCollateral))
895895
.to.emit(liquidityPool, "SuppliedToAave");
896896

897-
await expect(liquidityPool.connect(admin).setHealthFactor(5000n * 10n ** 18n / 100n))
897+
await expect(liquidityPool.connect(admin).setHealthFactor(5000n * 10000n / 100n))
898898
.to.emit(liquidityPool, "HealthFactorSet");
899899

900900
const amountToBorrow = 3n * UNI_DEC;
@@ -1422,7 +1422,7 @@ describe("LiquidityPoolAave", function () {
14221422
it("Should allow admin to set minimal health factor", async function () {
14231423
const {liquidityPool, admin} = await loadFixture(deployAll);
14241424
const oldHealthFactor = await liquidityPool.minHealthFactor();
1425-
const healthFactor = 300n * 10n ** 18n / 100n;
1425+
const healthFactor = 300n * 10000n / 100n;
14261426
await expect(liquidityPool.connect(admin).setHealthFactor(healthFactor))
14271427
.to.emit(liquidityPool, "HealthFactorSet").withArgs(oldHealthFactor, healthFactor);
14281428
expect(await liquidityPool.minHealthFactor())
@@ -1431,7 +1431,7 @@ describe("LiquidityPoolAave", function () {
14311431

14321432
it("Should NOT allow others to set minimal health factor", async function () {
14331433
const {liquidityPool, user} = await loadFixture(deployAll);
1434-
const healthFactor = 500n * 10n ** 18n / 100n;
1434+
const healthFactor = 500n * 10000n / 100n;
14351435
await expect(liquidityPool.connect(user).setHealthFactor(healthFactor))
14361436
.to.be.revertedWithCustomError(liquidityPool, "AccessControlUnauthorizedAccount");
14371437
});
@@ -1503,7 +1503,6 @@ describe("LiquidityPoolAave", function () {
15031503

15041504
expect(await usdc.balanceOf(user.address)).to.be.eq(amount);
15051505
expect(await liquidityPool.totalDeposited()).to.be.eq(0);
1506-
expect(await aToken.balanceOf(liquidityPool.target)).to.greaterThan(0);
15071506
});
15081507

15091508
it("Should NOT allow others to withdraw collateral", async function () {

0 commit comments

Comments
 (0)