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

Fix: Internal audit fixes #981

Open
wants to merge 5 commits into
base: fix/osqth-estimate
Choose a base branch
from
Open
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 packages/zen-bull-netting/foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ no_match_contract = "Fuzzing"
gas_reports = ["ZenBullNetting"]

[profile.fuzz]
runs = 2500
runs = 5000
max_local_rejects = 1024
max_global_rejects = 65536
seed = '0x3e8'
Expand Down
90 changes: 36 additions & 54 deletions packages/zen-bull-netting/src/NettingLib.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,7 @@ import { IController } from "./interface/IController.sol";

library NettingLib {
event TransferWethFromMarketMakers(
address indexed trader,
uint256 quantity,
uint256 wethAmount,
uint256 remainingOsqthBalance,
uint256 clearingPrice
address indexed trader, uint256 wethAmount, uint256 clearingPrice
);
event TransferOsqthToMarketMakers(
address indexed trader, uint256 bidId, uint256 quantity, uint256 remainingOsqthBalance
Expand Down Expand Up @@ -46,27 +42,21 @@ library NettingLib {
uint256 _quantity,
uint256 _oSqthToMint,
uint256 _clearingPrice
) external returns (bool, uint256) {
) external returns (uint256) {
uint256 wethAmount;
uint256 remainingOsqthToMint;
if (_quantity >= _oSqthToMint) {
wethAmount = (_oSqthToMint * _clearingPrice) / 1e18;
IERC20(_weth).transferFrom(_trader, address(this), wethAmount);

emit TransferWethFromMarketMakers(
_trader, _oSqthToMint, wethAmount, remainingOsqthToMint, _clearingPrice
);
return (true, remainingOsqthToMint);
_oSqthToMint = 0;
} else {
wethAmount = (_quantity * _clearingPrice) / 1e18;
remainingOsqthToMint = _oSqthToMint - _quantity;
IERC20(_weth).transferFrom(_trader, address(this), wethAmount);

emit TransferWethFromMarketMakers(
_trader, _quantity, wethAmount, remainingOsqthToMint, _clearingPrice
);
return (false, remainingOsqthToMint);
_oSqthToMint = _oSqthToMint - _quantity;
}

IERC20(_weth).transferFrom(_trader, address(this), wethAmount);

emit TransferWethFromMarketMakers(_trader, wethAmount, _clearingPrice);

return _oSqthToMint;
}

/**
Expand All @@ -75,32 +65,28 @@ library NettingLib {
* @param _oSqth oSQTH address
* @param _trader market maker address
* @param _bidId MM's bid ID
* @param _oSqthBalance remaining netting contracts's oSQTH balance
* @param _oSqthBalanceToPush remaining netting contracts's oSQTH balance
* @param _quantity oSQTH quantity in market maker order
*/
function transferOsqthToMarketMakers(
address _oSqth,
address _trader,
uint256 _bidId,
uint256 _oSqthBalance,
uint256 _oSqthBalanceToPush,
uint256 _quantity
) external returns (bool, uint256) {
uint256 remainingOsqthBalance;
if (_quantity < _oSqthBalance) {
IERC20(_oSqth).transfer(_trader, _quantity);

remainingOsqthBalance = _oSqthBalance - _quantity;

emit TransferOsqthToMarketMakers(_trader, _bidId, _quantity, remainingOsqthBalance);

return (false, remainingOsqthBalance);
) external returns (uint256) {
if (_quantity >= _oSqthBalanceToPush) {
_quantity = _oSqthBalanceToPush;
_oSqthBalanceToPush = 0;
} else {
IERC20(_oSqth).transfer(_trader, _oSqthBalance);
_oSqthBalanceToPush = _oSqthBalanceToPush - _quantity;
}

emit TransferOsqthToMarketMakers(_trader, _bidId, _oSqthBalance, remainingOsqthBalance);
IERC20(_oSqth).transfer(_trader, _quantity);

return (true, remainingOsqthBalance);
}
emit TransferOsqthToMarketMakers(_trader, _bidId, _quantity, _oSqthBalanceToPush);

return _oSqthBalanceToPush;
}

/**
Expand All @@ -117,20 +103,18 @@ library NettingLib {
uint256 _remainingOsqthToPull,
uint256 _quantity
) external returns (uint256) {
uint256 oSqthRemaining;
if (_quantity < _remainingOsqthToPull) {
IERC20(_oSqth).transferFrom(_trader, address(this), _quantity);

oSqthRemaining = _remainingOsqthToPull - _quantity;

emit TransferOsqthFromMarketMakers(_trader, _quantity, oSqthRemaining);
if (_quantity >= _remainingOsqthToPull) {
_quantity = _remainingOsqthToPull;
_remainingOsqthToPull = 0;
} else {
IERC20(_oSqth).transferFrom(_trader, address(this), _remainingOsqthToPull);

emit TransferOsqthFromMarketMakers(_trader, _remainingOsqthToPull, oSqthRemaining);
_remainingOsqthToPull = _remainingOsqthToPull - _quantity;
}

return oSqthRemaining;
IERC20(_oSqth).transferFrom(_trader, address(this), _quantity);

emit TransferOsqthFromMarketMakers(_trader, _quantity, _remainingOsqthToPull);

return _remainingOsqthToPull;
}

/**
Expand All @@ -151,16 +135,14 @@ library NettingLib {
uint256 _quantity,
uint256 _clearingPrice
) external returns (uint256) {
uint256 oSqthQuantity;

if (_quantity < _remainingOsqthToPull) {
oSqthQuantity = _quantity;
if (_quantity >= _remainingOsqthToPull) {
_quantity = _remainingOsqthToPull;
_remainingOsqthToPull = 0;
} else {
oSqthQuantity = _remainingOsqthToPull;
_remainingOsqthToPull = _remainingOsqthToPull - _quantity;
}

uint256 wethAmount = (oSqthQuantity * _clearingPrice) / 1e18;
_remainingOsqthToPull -= oSqthQuantity;
uint256 wethAmount = (_quantity * _clearingPrice) / 1e18;
IERC20(_weth).transfer(_trader, wethAmount);

emit TransferWethToMarketMaker(
Expand Down
46 changes: 18 additions & 28 deletions packages/zen-bull-netting/src/ZenBullNetting.sol
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,8 @@ contract ZenBullNetting is Ownable, EIP712, FlashSwap {
Order[] orders;
/// @dev price from the auction to sell sqth
uint256 clearingPrice;
/// @dev min ETH to get from flashswapping USDC debt
uint256 minEthFromUsdc;
/// @dev amount to deposit into crab in ZenBull flash deposit
uint256 flashDepositEthToCrab;
/// @dev min ETH to get from oSQTH in ZenBull flash deposit
Expand All @@ -180,7 +182,7 @@ contract ZenBullNetting is Ownable, EIP712, FlashSwap {
uint24 wethUsdcPoolFee;
}

/// @dev struct to store proportional amounts of erc20s (received or to send)
/// @dev struct to store accounting vars
struct MemoryVar {
uint256 currentZenBullBalance;
uint256 remainingEth;
Expand Down Expand Up @@ -231,19 +233,15 @@ contract ZenBullNetting is Ownable, EIP712, FlashSwap {
);
event SetBot(address bot);
event DepositAuction(
uint256 wethDeposited,
uint256 crabAmount,
uint256 clearingPrice,
uint256 oSqthAmount,
uint256 depositsIndex
uint256 wethDeposited, uint256 crabAmount, uint256 clearingPrice, uint256 oSqthAmount
);
event WithdrawAuction(
uint256 zenBullWithdrawn, uint256 clearingPrice, uint256 oSqthAmount, uint256 withdrawsIndex
);
event CancelNonce(address trader, uint256 nonce);
/// @dev shared events with the NettingLib for client side to detect them
event TransferWethFromMarketMakers(
address indexed trader, uint256 quantity, uint256 wethAmount, uint256 clearingPrice
address indexed trader, uint256 wethAmount, uint256 clearingPrice
);
event TransferOsqthToMarketMakers(
address indexed trader, uint256 bidId, uint256 quantity, uint256 remainingOsqthBalance
Expand Down Expand Up @@ -406,7 +404,7 @@ contract ZenBullNetting is Ownable, EIP712, FlashSwap {
/**
* @notice withdraw ETH from queue
* @param _amount ETH amount to dequeue
* @param _force forceWithdraw if deposited more than a week ago
* @param _force force withdraw if deposited more than a week ago
*/
function dequeueEth(uint256 _amount, bool _force) external {
require(!isAuctionLive || _force, "ZBN04");
Expand Down Expand Up @@ -546,7 +544,7 @@ contract ZenBullNetting is Ownable, EIP712, FlashSwap {
}
depositsIndex = i;

// process withdraws and send usdc
// process withdraws and send ETH
i = withdrawsIndex;
while (zenBullQuantity > 0) {
Receipt memory withdraw = withdraws[i];
Expand Down Expand Up @@ -597,23 +595,25 @@ contract ZenBullNetting is Ownable, EIP712, FlashSwap {
oracle, ethSqueethPool, oSqth, weth, zenBull, ethIntoCrab, auctionTwapPeriod
);

emit DepositAuction(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

L583 posessive apostrophe typo -> " * @dev takes in orders from MMs to buy oSQTH"

_params.depositsToProcess, _params.crabAmount, _params.clearingPrice, oSqthToMint
);

// get WETH from MM
for (uint256 i = 0; i < _params.orders.length; i++) {
for (uint256 i = 0; i < _params.orders.length && oSqthToMint > 0; i++) {
require(_params.orders[i].isBuying, "ZBN21");
require(_params.orders[i].price >= _params.clearingPrice, "ZBN22");

_checkOrder(_params.orders[i]);
_useNonce(_params.orders[i].trader, _params.orders[i].nonce);

bool shouldBreak;
(shouldBreak, oSqthToMint) = NettingLib.transferWethFromMarketMakers(
oSqthToMint = NettingLib.transferWethFromMarketMakers(
weth,
_params.orders[i].trader,
_params.orders[i].quantity,
oSqthToMint,
_params.clearingPrice
);
if (shouldBreak) break;
}
require(oSqthToMint == 0, "ZBN23");

Expand All @@ -634,7 +634,7 @@ contract ZenBullNetting is Ownable, EIP712, FlashSwap {
weth,
_params.wethUsdcPoolFee,
usdcToBorrow,
wethToLend - (_params.depositsToProcess + wethFromAuction - ethIntoCrab),
_params.minEthFromUsdc,
1,
abi.encodePacked(wethToLend)
);
Expand All @@ -660,16 +660,14 @@ contract ZenBullNetting is Ownable, EIP712, FlashSwap {
// send oSqth to market makers
memVar.oSqthBalance = IERC20(oSqth).balanceOf(address(this));
{
for (uint256 i = 0; i < _params.orders.length; i++) {
bool shouldBreak;
(shouldBreak, memVar.oSqthBalance) = NettingLib.transferOsqthToMarketMakers(
for (uint256 i = 0; i < _params.orders.length && memVar.oSqthBalance > 0; i++) {
memVar.oSqthBalance = NettingLib.transferOsqthToMarketMakers(
oSqth,
_params.orders[i].trader,
_params.orders[i].bidId,
memVar.oSqthBalance,
_params.orders[i].quantity
);
if (shouldBreak) break;
}
}

Expand Down Expand Up @@ -740,14 +738,6 @@ contract ZenBullNetting is Ownable, EIP712, FlashSwap {
}
depositsIndex = k;
isAuctionLive = false;

emit DepositAuction(
_params.depositsToProcess,
_params.crabAmount,
_params.clearingPrice,
memVar.oSqthBalance,
k
);
}

/**
Expand Down Expand Up @@ -824,7 +814,7 @@ contract ZenBullNetting is Ownable, EIP712, FlashSwap {
remainingWithdraws -= withdraw.amount;
zenBullBalance[withdraw.sender] -= withdraw.amount;

// send proportional usdc
// send proportional ETH
ethAmount = withdraw.amount * ethToWithdrawers / _params.withdrawsToProcess;

delete withdraws[j];
Expand All @@ -837,7 +827,7 @@ contract ZenBullNetting is Ownable, EIP712, FlashSwap {
withdraws[j].amount -= remainingWithdraws;
zenBullBalance[withdraw.sender] -= remainingWithdraws;

// send proportional usdc
// send proportional ETH
ethAmount = remainingWithdraws * ethToWithdrawers / _params.withdrawsToProcess;

payable(withdraw.sender).sendValue(ethAmount);
Expand Down
11 changes: 11 additions & 0 deletions packages/zen-bull-netting/test/ZenBullNettingBaseSetup.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ contract ZenBullNettingBaseSetup is Test {
address public constant ORACLE = 0x65D66c76447ccB45dAf1e8044e918fA786A483A1;
address public constant CRAB = 0x3B960E47784150F5a63777201ee2B15253D713e8;
address public constant FLASH_ZEN = 0x11A56a3A7A6Eb768A9125798B1eABE9EBD9EcE02;
address public constant QUOTER = 0xb27308f9F90D607463bb33eA1BeBb41C27CE5AB6;

address public ethSqueethPool = 0x82c427AdFDf2d245Ec51D8046b41c4ee87F0d29C;
address public ethUsdcPool = 0x8ad599c3A0ff1De082011EFDDc58f1908eb6e6D8;
Expand Down Expand Up @@ -113,6 +114,16 @@ contract ZenBullNettingBaseSetup is Test {
);
}

function _calcCrabSharesToMint(
uint256 _ethAmount,
uint256 _crabCollateral,
uint256 _crabTotalSupply
) internal pure returns (uint256) {
uint256 depositorShare = div(_ethAmount, (_crabCollateral + _ethAmount));

return (div(mul(_crabTotalSupply, depositorShare), (uint256(1e18) - depositorShare)));
}

function mul(uint256 x, uint256 y) internal pure returns (uint256) {
// add(mul(x, y), WAD / 2) / WAD;
return ((x * y) + (1e18 / 2)) / 1e18;
Expand Down
Loading