Skip to content

Commit 2d34795

Browse files
committed
Add withdrawProfit zero address check. Simplify withdraw()
1 parent 505e5a7 commit 2d34795

File tree

7 files changed

+35
-20
lines changed

7 files changed

+35
-20
lines changed

.env.example

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,5 +26,5 @@ ETHERSCAN_ARBITRUM_SEPOLIA=
2626
FORK_PROVIDER=https://eth-mainnet.public.blastapi.io
2727
USDC_OWNER_ADDRESS=0x7713974908Be4BEd47172370115e8b1219F4A5f0
2828
RPL_OWNER_ADDRESS=0xdC7b28976d6eb13082a5Be7C66f9dCFE0115738f
29-
UNI_OWNER_ADDRESS=0x46f34C24A7bA7a2Ac6DD76c3F09B32D41C144d08
29+
UNI_OWNER_ADDRESS=0x090D4613473dEE047c3f2706764f49E0821D256e
3030
PRIME_OWNER_ADDRESS=0x1D0065D367DA1919cD597d25F91a97B6039428C5

contracts/LiquidityPool.sol

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -142,19 +142,19 @@ contract LiquidityPool is ILiquidityPool, AccessControl, EIP712, Pausable {
142142

143143
// Admin functions
144144

145+
/// @notice Can withdraw a maximum of totalDeposited. If anything is left, it meant to be withdrawn through
146+
/// a withdrawProfit().
145147
function withdraw(address to, uint256 amount)
146148
external
147149
override
148150
onlyRole(LIQUIDITY_ADMIN_ROLE)
149151
whenNotPaused()
150-
returns (uint256)
151152
{
152-
uint256 withdrawn = _withdrawLogic(to, amount);
153153
uint256 deposited = totalDeposited;
154-
require(deposited >= withdrawn, InsufficientLiquidity());
155-
totalDeposited = deposited - withdrawn;
156-
emit Withdraw(msg.sender, to, withdrawn);
157-
return withdrawn;
154+
require(deposited >= amount, InsufficientLiquidity());
155+
totalDeposited = deposited - amount;
156+
_withdrawLogic(to, amount);
157+
emit Withdraw(msg.sender, to, amount);
158158
}
159159

160160
function withdrawProfit(
@@ -240,6 +240,7 @@ contract LiquidityPool is ILiquidityPool, AccessControl, EIP712, Pausable {
240240
address[] calldata tokens,
241241
address to
242242
) internal {
243+
require(to != address(0), ZeroAddress());
243244
bool success;
244245
for (uint256 i = 0; i < tokens.length; i++) {
245246
IERC20 token = IERC20(tokens[i]);
@@ -261,9 +262,9 @@ contract LiquidityPool is ILiquidityPool, AccessControl, EIP712, Pausable {
261262
require(borrowToken == address(ASSETS), InvalidBorrowToken());
262263
}
263264

264-
function _withdrawLogic(address to, uint256 amount) internal virtual returns (uint256) {
265+
function _withdrawLogic(address to, uint256 amount) internal virtual {
266+
require(ASSETS.balanceOf(address(this)) >= amount, InsufficientLiquidity());
265267
ASSETS.safeTransfer(to, amount);
266-
return amount;
267268
}
268269

269270
function _withdrawProfitLogic(IERC20 token) internal virtual returns (uint256) {

contracts/LiquidityPoolAave.sol

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -166,14 +166,14 @@ contract LiquidityPoolAave is LiquidityPool {
166166
_checkTokenLTV(borrowToken);
167167
}
168168

169-
function _withdrawLogic(address to, uint256 amount) internal override returns (uint256) {
169+
function _withdrawLogic(address to, uint256 amount) internal override {
170+
require(ATOKEN.balanceOf(address(this)) >= amount, InsufficientLiquidity());
170171
// get USDC from AAVE
171-
uint256 withdrawn = AAVE_POOL.withdraw(address(ASSETS), amount, to);
172+
AAVE_POOL.withdraw(address(ASSETS), amount, to);
172173
// health factor after withdraw
173174
(,,,,,uint256 currentHealthFactor) = AAVE_POOL.getUserAccountData(address(this));
174175
require(currentHealthFactor >= minHealthFactor, HealthFactorTooLow());
175-
emit WithdrawnFromAave(to, withdrawn);
176-
return withdrawn;
176+
emit WithdrawnFromAave(to, amount);
177177
}
178178

179179
function _withdrawProfitLogic(IERC20 token) internal override returns (uint256) {

contracts/interfaces/ILiquidityPool.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ interface ILiquidityPool {
1414

1515
function depositWithPull(uint256 amount) external;
1616

17-
function withdraw(address to, uint256 amount) external returns (uint256 withdrawn);
17+
function withdraw(address to, uint256 amount) external;
1818

1919
function borrow(
2020
address borrowToken,

contracts/testing/TestLiquidityPool.sol

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,8 @@ contract TestLiquidityPool is ILiquidityPool, AccessControl {
2121
emit Deposit();
2222
}
2323

24-
function withdraw(address to, uint256 amount) external override onlyRole(LIQUIDITY_ADMIN_ROLE) returns (uint256) {
24+
function withdraw(address to, uint256 amount) external override onlyRole(LIQUIDITY_ADMIN_ROLE) {
2525
SafeERC20.safeTransfer(ASSETS, to, amount);
26-
return amount;
2726
}
2827

2928
function depositWithPull(uint256) external pure override {

test/LiquidityPool.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import {
2-
loadFixture, time
2+
loadFixture, time, setBalance
33
} from "@nomicfoundation/hardhat-toolbox/network-helpers";
44
import {expect} from "chai";
55
import hre from "hardhat";
@@ -39,6 +39,7 @@ describe("LiquidityPool", function () {
3939
if (!UNI_OWNER_ADDRESS) throw new Error("Env variables not configured (UNI_OWNER_ADDRESS missing)");
4040
const uni = await hre.ethers.getContractAt("ERC20", UNI_ADDRESS);
4141
const uniOwner = await hre.ethers.getImpersonatedSigner(UNI_OWNER_ADDRESS);
42+
await setBalance(UNI_OWNER_ADDRESS, 10n ** 18n);
4243

4344
const USDC_DEC = 10n ** (await usdc.decimals());
4445
const RPL_DEC = 10n ** (await rpl.decimals());
@@ -657,6 +658,12 @@ describe("LiquidityPool", function () {
657658
.to.be.revertedWithCustomError(liquidityPoolBase, "EnforcedPause");
658659
});
659660

661+
it("Should NOT withdraw profit to zero address", async function () {
662+
const {liquidityPoolBase, user, usdc, withdrawProfit, pauser} = await loadFixture(deployAll);
663+
await expect(liquidityPoolBase.connect(withdrawProfit).withdrawProfit([usdc.target], ZERO_ADDRESS))
664+
.to.be.revertedWithCustomError(liquidityPoolBase, "ZeroAddress()");
665+
});
666+
660667
it("Should revert during withdrawing profit if no profit", async function () {
661668
const {liquidityPoolBase, usdc, withdrawProfit, user} = await loadFixture(deployAll);
662669
await expect(liquidityPoolBase.connect(withdrawProfit).withdrawProfit([usdc.target], user.address))

test/LiquidityPoolAave.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import {
2-
loadFixture, time
2+
loadFixture, time, setBalance
33
} from "@nomicfoundation/hardhat-toolbox/network-helpers";
44
import {expect} from "chai";
55
import hre from "hardhat";
66
import {
77
deploy, signBorrow
88
} from "./helpers";
9+
import {ZERO_ADDRESS} from "../scripts/common";
910
import {encodeBytes32String, AbiCoder} from "ethers";
1011
import {
1112
MockTarget, MockBorrowSwap, LiquidityPoolAave
@@ -51,6 +52,7 @@ describe("LiquidityPoolAave", function () {
5152
const uniOwner = await hre.ethers.getImpersonatedSigner(UNI_OWNER_ADDRESS);
5253
const uniData = await aavePool.getReserveData(UNI_ADDRESS);
5354
const uniDebtToken = await hre.ethers.getContractAt("ERC20", uniData[10]);
55+
await setBalance(UNI_OWNER_ADDRESS, 10n ** 18n);
5456

5557
// PRIME token used as not supported by aave
5658
const NON_SUPPORTED_TOKEN_ADDRESS = "0xb23d80f5FefcDDaa212212F028021B41DEd428CF";
@@ -627,7 +629,7 @@ describe("LiquidityPoolAave", function () {
627629
const usdcDebtBefore = await usdcDebtToken.balanceOf(liquidityPool.target);
628630
expect(usdcDebtBefore).to.be.greaterThan(amountToBorrow);
629631

630-
await usdc.connect(uniOwner).transfer(liquidityPool.target, amountToBorrow);
632+
await usdc.connect(usdcOwner).transfer(liquidityPool.target, amountToBorrow);
631633

632634
await expect(liquidityPool.connect(user).repay([usdc.target]))
633635
.to.emit(liquidityPool, "Repaid");
@@ -892,7 +894,7 @@ describe("LiquidityPoolAave", function () {
892894
await expect(liquidityPool.connect(liquidityAdmin).deposit(amountCollateral))
893895
.to.emit(liquidityPool, "SuppliedToAave");
894896

895-
await expect(liquidityPool.connect(admin).setHealthFactor(4000n * 10n ** 18n / 100n))
897+
await expect(liquidityPool.connect(admin).setHealthFactor(5000n * 10n ** 18n / 100n))
896898
.to.emit(liquidityPool, "HealthFactorSet");
897899

898900
const amountToBorrow = 3n * UNI_DEC;
@@ -1274,6 +1276,12 @@ describe("LiquidityPoolAave", function () {
12741276
.to.be.revertedWithCustomError(liquidityPool, "EnforcedPause");
12751277
});
12761278

1279+
it("Should NOT withdraw profit to zero address", async function () {
1280+
const {liquidityPool, user, uni, withdrawProfit, pauser} = await loadFixture(deployAll);
1281+
await expect(liquidityPool.connect(withdrawProfit).withdrawProfit([uni.target], ZERO_ADDRESS))
1282+
.to.be.revertedWithCustomError(liquidityPool, "ZeroAddress()");
1283+
});
1284+
12771285
it("Should revert during withdrawing profit if no profit", async function () {
12781286
const {liquidityPool, uni, withdrawProfit, user} = await loadFixture(deployAll);
12791287
await expect(liquidityPool.connect(withdrawProfit).withdrawProfit([uni.target], user.address))

0 commit comments

Comments
 (0)