Skip to content

Commit

Permalink
fix: sherlock
Browse files Browse the repository at this point in the history
  • Loading branch information
Gevarist authored Aug 23, 2023
1 parent 9133fc4 commit 76d67ab
Show file tree
Hide file tree
Showing 5 changed files with 90 additions and 21 deletions.
21 changes: 7 additions & 14 deletions contracts/ArrakisV2.sol
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import {Position} from "./libraries/Position.sol";
import {Pool} from "./libraries/Pool.sol";
import {Underlying as UnderlyingHelper} from "./libraries/Underlying.sol";
import {SafeCast} from "@openzeppelin/contracts/utils/math/SafeCast.sol";
import {hundredPercent} from "./constants/CArrakisV2.sol";

/// @title ArrakisV2 LP vault version 2
/// @notice Smart contract managing liquidity providing strategy for a given token pair
Expand Down Expand Up @@ -140,12 +139,13 @@ contract ArrakisV2 is IUniswapV3MintCallback, ArrakisV2Storage {
range.lowerTick,
range.upperTick
);
if (liquidity == 0) continue;

liquidity = SafeCast.toUint128(
FullMath.mulDiv(liquidity, mintAmount_, ts)
);

if (liquidity == 0) continue;

pool.mint(me, range.lowerTick, range.upperTick, liquidity, "");
}
}
Expand Down Expand Up @@ -183,12 +183,13 @@ contract ArrakisV2 is IUniswapV3MintCallback, ArrakisV2Storage {
range.lowerTick,
range.upperTick
);
if (liquidity == 0) continue;

liquidity = SafeCast.toUint128(
FullMath.mulDiv(liquidity, burnAmount_, ts)
);

if (liquidity == 0) continue;

Withdraw memory withdraw = _withdraw(
pool,
range.lowerTick,
Expand Down Expand Up @@ -430,21 +431,13 @@ contract ArrakisV2 is IUniswapV3MintCallback, ArrakisV2Storage {
liquidity_
);

(uint256 collect0, uint256 collect1) = pool_.collect(
address(this),
(uint256 collect0, uint256 collect1) = _collectFees(
pool_,
lowerTick_,
upperTick_,
type(uint128).max,
type(uint128).max
upperTick_
);

withdraw.fee0 = collect0 - withdraw.burn0;
withdraw.fee1 = collect1 - withdraw.burn1;
}

function _applyFees(uint256 fee0_, uint256 fee1_) internal {
uint16 mManagerFeeBPS = managerFeeBPS;
managerBalance0 += (fee0_ * mManagerFeeBPS) / hundredPercent;
managerBalance1 += (fee1_ * mManagerFeeBPS) / hundredPercent;
}
}
10 changes: 10 additions & 0 deletions contracts/ArrakisV2Resolver.sol
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,16 @@ contract ArrakisV2Resolver is IArrakisV2Resolver {
uint256 mintAmount
)
{
/// @dev to not exceed max amount sent by user.
uint256 numberOfRanges = vaultV2_.getRanges().length;

require(
numberOfRanges < amount0Max_ && numberOfRanges < amount1Max_,
"max amounts should be higher than the number of ranges"
);
amount0Max_ = amount0Max_ - numberOfRanges;
amount1Max_ = amount1Max_ - numberOfRanges;

uint256 totalSupply = vaultV2_.totalSupply();
UnderlyingPayload memory underlyingPayload = UnderlyingPayload({
ranges: vaultV2_.getRanges(),
Expand Down
76 changes: 71 additions & 5 deletions contracts/abstract/ArrakisV2Storage.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ pragma solidity 0.8.13;
import {
IUniswapV3Factory
} from "@uniswap/v3-core/contracts/interfaces/IUniswapV3Factory.sol";
import {
IUniswapV3Pool
} from "@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol";
import {
IERC20,
SafeERC20
Expand All @@ -21,6 +24,7 @@ import {
EnumerableSet
} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
import {Range, Rebalance, InitializePayload} from "../structs/SArrakisV2.sol";
import {hundredPercent} from "../constants/CArrakisV2.sol";

/// @title ArrakisV2Storage base contract containing all ArrakisV2 storage variables.
// solhint-disable-next-line max-states-count
Expand Down Expand Up @@ -131,11 +135,12 @@ abstract contract ArrakisV2Storage is
__ReentrancyGuard_init();

_addPools(params_.feeTiers, params_.token0, params_.token1);
_whitelistRouters(params_.routers);

token0 = IERC20(params_.token0);
token1 = IERC20(params_.token1);

_whitelistRouters(params_.routers);

_transferOwnership(params_.owner);

manager = params_.manager;
Expand Down Expand Up @@ -206,7 +211,8 @@ abstract contract ArrakisV2Storage is
/// @notice set manager
/// @param manager_ manager address.
/// @dev only callable by owner.
function setManager(address manager_) external onlyOwner {
function setManager(address manager_) external onlyOwner nonReentrant {
_collectFeesOnPools();
_withdrawManagerBalance();
manager = manager_;
emit LogSetManager(manager_);
Expand All @@ -215,8 +221,13 @@ abstract contract ArrakisV2Storage is
/// @notice set manager fee bps
/// @param managerFeeBPS_ manager fee in basis points.
/// @dev only callable by manager.
function setManagerFeeBPS(uint16 managerFeeBPS_) external onlyManager {
function setManagerFeeBPS(uint16 managerFeeBPS_)
external
onlyManager
nonReentrant
{
require(managerFeeBPS_ <= 10000, "MFO");
_collectFeesOnPools();
managerFeeBPS = managerFeeBPS_;
emit LogSetManagerFeeBPS(managerFeeBPS_);
}
Expand Down Expand Up @@ -277,12 +288,21 @@ abstract contract ArrakisV2Storage is
managerBalance0 = 0;
managerBalance1 = 0;

/// @dev token can blacklist manager and make this function fail,
/// so we use try catch to deal with blacklisting.

if (amount0 > 0) {
token0.safeTransfer(manager, amount0);
// solhint-disable-next-line no-empty-blocks
try token0.transfer(manager, amount0) {} catch {
amount0 = 0;
}
}

if (amount1 > 0) {
token1.safeTransfer(manager, amount1);
// solhint-disable-next-line no-empty-blocks
try token1.transfer(manager, amount1) {} catch {
amount1 = 0;
}
}

emit LogWithdrawManagerBalance(amount0, amount1);
Expand All @@ -308,6 +328,46 @@ abstract contract ArrakisV2Storage is
}
}

function _collectFeesOnPools() internal {
uint256 fees0;
uint256 fees1;
for (uint256 i; i < _ranges.length; i++) {
Range memory range = _ranges[i];
IUniswapV3Pool pool = IUniswapV3Pool(
factory.getPool(address(token0), address(token1), range.feeTier)
);

/// @dev to update the position and collect fees.
pool.burn(range.lowerTick, range.upperTick, 0);

(uint256 collect0, uint256 collect1) = _collectFees(
pool,
range.lowerTick,
range.upperTick
);

fees0 += collect0;
fees1 += collect1;
}

_applyFees(fees0, fees1);
emit LogCollectedFees(fees0, fees1);
}

function _collectFees(
IUniswapV3Pool pool_,
int24 lowerTick_,
int24 upperTick_
) internal returns (uint256 collect0, uint256 collect1) {
(collect0, collect1) = pool_.collect(
address(this),
lowerTick_,
upperTick_,
type(uint128).max,
type(uint128).max
);
}

function _whitelistRouters(address[] calldata routers_) internal {
for (uint256 i = 0; i < routers_.length; i++) {
require(
Expand All @@ -323,5 +383,11 @@ abstract contract ArrakisV2Storage is
emit LogWhitelistRouters(routers_);
}

function _applyFees(uint256 fee0_, uint256 fee1_) internal {
uint16 mManagerFeeBPS = managerFeeBPS;
managerBalance0 += (fee0_ * mManagerFeeBPS) / hundredPercent;
managerBalance1 += (fee1_ * mManagerFeeBPS) / hundredPercent;
}

// #endregion internal functions
}
2 changes: 1 addition & 1 deletion contracts/libraries/Underlying.sol
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,7 @@ library Underlying {
if (sqrtRatioAX96 > sqrtRatioBX96)
(sqrtRatioAX96, sqrtRatioBX96) = (sqrtRatioBX96, sqrtRatioAX96);

if (sqrtRatioX96 <= sqrtRatioAX96) {
if (sqrtRatioX96 < sqrtRatioAX96) {
amount0 = SafeCast.toUint256(
SqrtPriceMath.getAmount0Delta(
sqrtRatioAX96,
Expand Down
2 changes: 1 addition & 1 deletion hardhat.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ const config: HardhatUserConfig = {
{
version: "0.8.13",
settings: {
optimizer: { enabled: true, runs: 1299 },
optimizer: { enabled: true, runs: 833 },
},
},
],
Expand Down

0 comments on commit 76d67ab

Please sign in to comment.