Skip to content

Commit 6771c4c

Browse files
committed
Optimize storage for borrow
1 parent d98bb99 commit 6771c4c

File tree

5 files changed

+57
-38
lines changed

5 files changed

+57
-38
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 / 1e14 >= minHealthFactor, HealthFactorTooLow());
164171

165172
// check ltv for token
166173
_checkTokenLTV(borrowToken);
@@ -171,7 +178,7 @@ contract LiquidityPoolAave is LiquidityPool {
171178
uint256 withdrawn = AAVE_POOL.withdraw(address(ASSETS), amount, to);
172179
// health factor after withdraw
173180
(,,,,,uint256 currentHealthFactor) = AAVE_POOL.getUserAccountData(address(this));
174-
require(currentHealthFactor >= minHealthFactor, HealthFactorTooLow());
181+
require(currentHealthFactor / 1e14 >= minHealthFactor, HealthFactorTooLow());
175182
emit WithdrawnFromAave(to, withdrawn);
176183
return withdrawn;
177184
}

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 & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,9 @@ describe("LiquidityPoolAave", function () {
6565
const UNI_DEC = 10n ** (await uni.decimals());
6666

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

895-
await expect(liquidityPool.connect(admin).setHealthFactor(4000n * 10n ** 18n / 100n))
895+
await expect(liquidityPool.connect(admin).setHealthFactor(4000n * 10000n / 100n))
896896
.to.emit(liquidityPool, "HealthFactorSet");
897897

898898
const amountToBorrow = 3n * UNI_DEC;
@@ -1414,7 +1414,7 @@ describe("LiquidityPoolAave", function () {
14141414
it("Should allow admin to set minimal health factor", async function () {
14151415
const {liquidityPool, admin} = await loadFixture(deployAll);
14161416
const oldHealthFactor = await liquidityPool.minHealthFactor();
1417-
const healthFactor = 300n * 10n ** 18n / 100n;
1417+
const healthFactor = 300n * 10000n / 100n;
14181418
await expect(liquidityPool.connect(admin).setHealthFactor(healthFactor))
14191419
.to.emit(liquidityPool, "HealthFactorSet").withArgs(oldHealthFactor, healthFactor);
14201420
expect(await liquidityPool.minHealthFactor())
@@ -1423,7 +1423,7 @@ describe("LiquidityPoolAave", function () {
14231423

14241424
it("Should NOT allow others to set minimal health factor", async function () {
14251425
const {liquidityPool, user} = await loadFixture(deployAll);
1426-
const healthFactor = 500n * 10n ** 18n / 100n;
1426+
const healthFactor = 500n * 10000n / 100n;
14271427
await expect(liquidityPool.connect(user).setHealthFactor(healthFactor))
14281428
.to.be.revertedWithCustomError(liquidityPool, "AccessControlUnauthorizedAccount");
14291429
});

0 commit comments

Comments
 (0)