Platform: Code4rena
Start Date: 17/02/2022
Pot Size: $75,000 USDC
Total HM: 20
Participants: 39
Period: 7 days
Judges: moose-code, JasoonS
Total Solo HM: 13
Id: 89
League: ETH
Rank: 20/39
Findings: 2
Award: $439.99
π Selected for report: 0
π Solo Findings: 0
π Selected for report: defsec
Also found by: 0v3rf10w, 0x0x0x, 0x1f8b, 0xwags, CertoraInc, Dravee, IllIllI, Meta0xNull, Nikolay, Omik, WatchPug, bobi, cccz, csanuragjain, danb, gzeon, hubble, hyh, itsmeSTYJ, jayjonah8, kenta, kirk-baird, leastwood, pauliax, peritoflores, rfa, robee, sorrynotsorry, ye0lde
212.4973 USDC - $212.50
https://github.com/code-423n4/2022-02-hubble/blob/ed1d885d5dbc2eae24e43c3ecbf291a0f5a52765/contracts/ClearingHouse.sol#L344-L354 https://github.com/code-423n4/2022-02-hubble/blob/8c157f519bc32e552f8cc832ecc75dc381faa91e/contracts/legos/Governable.sol#L15-L21
When fees/margin or governance are involved it's important to emit events for off-chain monitors/tools to be able to react if necessary.
Automated tools especially need all relevant ancillary data to be emitted in order to efficiently react to it. An automated bot trading with the hubble exchange will not be able to see changes to fee/margin changes in real time, and may submit orders which cause it to miscalculate P&L, causing it to lose capital. This is especially true because the contracts do not use timelocks for changes. See these examples where similar findings have been flagged as medium/high-severity issues.
function setParams( int _maintenanceMargin, int _minAllowableMargin, uint _tradeFee, uint _liquidationPenality ) external onlyGovernance { tradeFee = _tradeFee; liquidationPenalty = _liquidationPenality; maintenanceMargin = _maintenanceMargin; minAllowableMargin = _minAllowableMargin; }
function setGovernace(address _governance) external onlyGovernance { _setGovernace(_governance); } function _setGovernace(address _governance) internal { governance = _governance; }
The onlyGovernance
modifier does not emit events
address public governance; modifier onlyGovernance() { require(msg.sender == governance, "ONLY_GOVERNANCE"); _; }
The provided deployment script only uses a signer rather than a contract as the governance address. Furthermore, the live environment deployed on testnet has a deployed InsuranceFund
which uses the onlyGovernance
modifier...
function syncDeps(IRegistry _registry) public onlyGovernance { vusd = IERC20(_registry.vusd()); marginAccount = _registry.marginAccount(); }
...and the only transaction interacting with this function appears here and is called by an address, not a contract. There are no other transactions to the insurance fund to change the governance address, so it's clear that the testnet does not use an emitting governor either.
Code inspection Hardhat snowtrace.io
Emit events for these changes
#0 - atvanguard
2022-02-24T08:14:23Z
Severity is 0
.
#1 - moose-code
2022-03-15T13:54:00Z
Dup of #31
#2 - JeeberC4
2022-03-24T20:45:44Z
Since this issue was downgraded to a QA level, and the warden did not submit a separate QA report, we've renamed this one to "QA report" for consistency. The original title, for the record, was Missing events for critical governance and fee/margin rate changes
227.4932 USDC - $227.49
credit
should be copied
if (credit > 0) { uint toBurn = Math.min(vusd.balanceOf(address(this)), credit); credit -= toBurn;
external
rather than public
function getUnderlyingTwapPrice(uint256 _intervalInSeconds) public view returns (int256) {
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/AMM.sol#L387
function liquidateMaker(address maker) override public whenNotPaused {
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/ClearingHouse.sol#L148
function liquidateTaker(address trader) override public whenNotPaused {
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/ClearingHouse.sol#L153
function syncDeps(IRegistry _registry) public onlyGovernance {
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/InsuranceFund.sol#L116
function getNormalizedMargin(address trader) override public view returns(int256 weighted) {
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/MarginAccount.sol#L509
function syncDeps(address _registry, uint _liquidationIncentive) public onlyGovernance {
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/MarginAccount.sol#L599
require()
strings longer than 32 bytes cost extra gasrequire(baseAssetQuantity > 0, "VAMM._longbaseAssetQuantity is <= 0");
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/AMM.sol#L487
require(baseAssetQuantity < 0, "VAMM._shortbaseAssetQuantity is >= 0");
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/AMM.sol#L511
require(margin[VUSD_IDX][trader] >= 0, "Cannot remove margin when vusd balance is negative");
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/MarginAccount.sol#L174
require(notionalPosition == 0, "Liquidate positions before settling bad debt");
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/MarginAccount.sol#L354
require(repay <= maxRepay, "Need to repay more to seize that much");
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/MarginAccount.sol#L453
require(reserve >= withdrawals[start].amount, 'Cannot process withdrawals at this timeNot enough balance');
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/VUSD.sol#L55
require(isAboveMinAllowableMargin(trader), "CHBelow Minimum Allowable Margin");
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/ClearingHouse.sol#L84
require(isAboveMinAllowableMargin(maker), "CHBelow Minimum Allowable Margin");
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/ClearingHouse.sol#L101
require(hasRole(DEFAULT_ADMIN_ROLE, _msgSender()), "HubbleErc20.allowTransfers.noAuth");
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/tests/ERC20Mintable.sol#L32
require(hasRole(DEFAULT_ADMIN_ROLE, _msgSender()), "HubbleErc20.allowTransfers.noAuth");
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/tests/ERC20Mintable.sol#L60
require(prices[underlying] != 0, "underlying price has not been set as yet");
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/tests/TestOracle.sol#L20
require(twapPrices[underlying] != 0, "underlying twap price has not been set as yet");
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/tests/TestOracle.sol#L33
> 0
costs more gas than != 0
when used in on uints in a require()
statementrequire(amount > 0, "Add non-zero margin");
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/MarginAccount.sol#L150
require(_round > 0, "Not enough history");
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/Oracle.sol#L153
require()
statements that use &&
saves gasSee this issue for an example
require(idx > VUSD_IDX && idx < supportedCollateral.length, "collateral not seizable");
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/MarginAccount.sol
uint constant VUSD_IDX = 0;
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/MarginAccount.sol#L31
for (uint i = 0; i < idxs.length; i++) {
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/MarginAccount.sol#L331
for (uint i = 0; i < assets.length; i++) {
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/MarginAccount.sol#L521
for (uint i = 0; i < _collaterals.length; i++) {
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/MarginAccount.sol#L552
uint constant VUSD_IDX = 0;
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/MarginAccountHelper.sol#L13
for (uint i = 0; i < amms.length; i++) {
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/ClearingHouse.sol#L122
for (uint i = 0; i < amms.length; i++) {
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/ClearingHouse.sol#L130
for (uint i = 0; i < amms.length; i++) {
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/ClearingHouse.sol#L170
for (uint i = 0; i < amms.length; i++) { // liquidate all positions
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/ClearingHouse.sol#L194
for (uint i = 0; i < amms.length; i++) {
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/ClearingHouse.sol#L251
for (uint i = 0; i < amms.length; i++) {
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/ClearingHouse.sol#L263
for (uint i = 0; i < amms.length; i++) {
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/ClearingHouse.sol#L277
uint shares = 0;
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/InsuranceFund.sol#L52
uint constant VUSD_IDX = 0;
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/HubbleViewer.sol#L15
for (uint i = 0; i < len; i++) {
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/HubbleViewer.sol#L52
for (uint i = 0; i < traders.length; i++) {
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/HubbleViewer.sol#L65
for (uint i = 0; i < traders.length; i++) {
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/HubbleViewer.sol#L78
for (uint i = 0; i < l; i++) {
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/HubbleViewer.sol#L95
for (uint i = 0; i < l; i++) {
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/HubbleViewer.sol#L120
for (uint i = 0; i < l; i++) {
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/HubbleViewer.sol#L137
for (uint256 i = 0; i < recipients.length; i++)
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/tests/Disperse.sol#L9
uint256 total = 0;
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/tests/Disperse.sol#L17
for (uint256 i = 0; i < recipients.length; i++)
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/tests/Disperse.sol#L18
for (uint256 i = 0; i < recipients.length; i++)
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/tests/Disperse.sol#L21
for (uint256 i = 0; i < recipients.length; i++)
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/tests/Disperse.sol#L27
for (uint256 i = 0; i < recipients.length; i++)
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/tests/Disperse.sol#L32
for (uint i = 0; i < numTraders; i++) {
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/tests/Leaderboard.sol#L43
for (uint j = 0; j < l; j++) {
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/tests/Leaderboard.sol#L45
for (uint i = 0; i < targets.length; i++) {
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/tests/Executor.sol#L19
for (uint i = 0; i < traders.length; i++) {
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/tests/BatchLiquidator.sol#L25
for (uint i = 0; i < traders.length; i++) {
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/tests/BatchLiquidator.sol#L31
for (uint i = 0; i < traders.length; i++) {
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/tests/BatchLiquidator.sol#L37
<array>.length
should not be looked up in every loop of a for-loopEven memory arrays incur the overhead of bit tests and bit shifts to calculate the array length
for (uint i = 0; i < idxs.length; i++) {
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/MarginAccount.sol#L331
for (uint i = 1 /* skip vusd */; i < assets.length; i++) {
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/MarginAccount.sol#L373
for (uint i = 0; i < assets.length; i++) {
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/MarginAccount.sol#L521
for (uint i = 0; i < _collaterals.length; i++) {
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/MarginAccount.sol#L552
for (uint i = 0; i < amms.length; i++) {
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/ClearingHouse.sol#L122
for (uint i = 0; i < amms.length; i++) {
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/ClearingHouse.sol#L130
for (uint i = 0; i < amms.length; i++) {
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/ClearingHouse.sol#L170
for (uint i = 0; i < amms.length; i++) { // liquidate all positions
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/ClearingHouse.sol#L194
for (uint i = 0; i < amms.length; i++) {
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/ClearingHouse.sol#L251
for (uint i = 0; i < amms.length; i++) {
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/ClearingHouse.sol#L263
for (uint i = 0; i < amms.length; i++) {
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/ClearingHouse.sol#L277
for (uint i = 0; i < traders.length; i++) {
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/HubbleViewer.sol#L65
for (uint i = 0; i < traders.length; i++) {
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/HubbleViewer.sol#L78
for (uint i = 1; i < length; i++) {
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/HubbleViewer.sol#L367
for (uint256 i = 0; i < recipients.length; i++)
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/tests/Disperse.sol#L9
for (uint256 i = 0; i < recipients.length; i++)
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/tests/Disperse.sol#L18
for (uint256 i = 0; i < recipients.length; i++)
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/tests/Disperse.sol#L21
for (uint256 i = 0; i < recipients.length; i++)
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/tests/Disperse.sol#L27
for (uint256 i = 0; i < recipients.length; i++)
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/tests/Disperse.sol#L32
for (uint i = 0; i < targets.length; i++) {
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/tests/Executor.sol#L19
for (uint i = 0; i < traders.length; i++) {
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/tests/BatchLiquidator.sol#L25
for (uint i = 0; i < traders.length; i++) {
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/tests/BatchLiquidator.sol#L31
for (uint i = 0; i < traders.length; i++) {
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/tests/BatchLiquidator.sol#L37
++i
/i++
should be unchecked{++i}
/unchecked{++i}
when it is not possible for them to overflow, as is the case when used in for- and while-loopsfor (uint i = 0; i < idxs.length; i++) {
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/MarginAccount.sol#L331
for (uint i = 1 /* skip vusd */; i < assets.length; i++) {
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/MarginAccount.sol#L373
for (uint i = 0; i < assets.length; i++) {
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/MarginAccount.sol#L521
for (uint i = 0; i < _collaterals.length; i++) {
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/MarginAccount.sol#L552
for (uint i = 0; i < amms.length; i++) {
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/ClearingHouse.sol#L122
for (uint i = 0; i < amms.length; i++) {
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/ClearingHouse.sol#L130
for (uint i = 0; i < amms.length; i++) {
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/ClearingHouse.sol#L170
for (uint i = 0; i < amms.length; i++) { // liquidate all positions
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/ClearingHouse.sol#L194
for (uint i = 0; i < amms.length; i++) {
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/ClearingHouse.sol#L251
for (uint i = 0; i < amms.length; i++) {
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/ClearingHouse.sol#L263
for (uint i = 0; i < amms.length; i++) {
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/ClearingHouse.sol#L277
for (uint i = 0; i < len; i++) {
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/HubbleViewer.sol#L52
for (uint i = 0; i < traders.length; i++) {
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/HubbleViewer.sol#L65
for (uint i = 0; i < traders.length; i++) {
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/HubbleViewer.sol#L78
for (uint i = 0; i < l; i++) {
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/HubbleViewer.sol#L95
for (uint i = 0; i < l; i++) {
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/HubbleViewer.sol#L120
for (uint i = 0; i < l; i++) {
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/HubbleViewer.sol#L137
for (uint i = 1; i < length; i++) {
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/HubbleViewer.sol#L367
for (uint256 i = 0; i < recipients.length; i++)
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/tests/Disperse.sol#L9
for (uint256 i = 0; i < recipients.length; i++)
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/tests/Disperse.sol#L18
for (uint256 i = 0; i < recipients.length; i++)
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/tests/Disperse.sol#L21
for (uint256 i = 0; i < recipients.length; i++)
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/tests/Disperse.sol#L27
for (uint256 i = 0; i < recipients.length; i++)
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/tests/Disperse.sol#L32
for (uint i = 0; i < numTraders; i++) {
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/tests/Leaderboard.sol#L43
for (uint j = 0; j < l; j++) {
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/tests/Leaderboard.sol#L45
for (uint i = 0; i < targets.length; i++) {
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/tests/Executor.sol#L19
for (uint i = 0; i < traders.length; i++) {
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/tests/BatchLiquidator.sol#L25
for (uint i = 0; i < traders.length; i++) {
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/tests/BatchLiquidator.sol#L31
for (uint i = 0; i < traders.length; i++) {
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/tests/BatchLiquidator.sol#L37
++i
costs less gas than ++i
, especially when it's used in for-loops (--i
/i--
too)for (uint i = 0; i < idxs.length; i++) {
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/MarginAccount.sol#L331
for (uint i = 1 /* skip vusd */; i < assets.length; i++) {
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/MarginAccount.sol#L373
for (uint i = 0; i < assets.length; i++) {
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/MarginAccount.sol#L521
for (uint i = 0; i < _collaterals.length; i++) {
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/MarginAccount.sol#L552
for (uint i = 0; i < amms.length; i++) {
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/ClearingHouse.sol#L122
for (uint i = 0; i < amms.length; i++) {
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/ClearingHouse.sol#L130
for (uint i = 0; i < amms.length; i++) {
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/ClearingHouse.sol#L170
for (uint i = 0; i < amms.length; i++) { // liquidate all positions
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/ClearingHouse.sol#L194
for (uint i = 0; i < amms.length; i++) {
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/ClearingHouse.sol#L251
for (uint i = 0; i < amms.length; i++) {
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/ClearingHouse.sol#L263
for (uint i = 0; i < amms.length; i++) {
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/ClearingHouse.sol#L277
for (uint i = 0; i < len; i++) {
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/HubbleViewer.sol#L52
for (uint i = 0; i < traders.length; i++) {
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/HubbleViewer.sol#L65
for (uint i = 0; i < traders.length; i++) {
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/HubbleViewer.sol#L78
for (uint i = 0; i < l; i++) {
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/HubbleViewer.sol#L95
for (uint i = 0; i < l; i++) {
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/HubbleViewer.sol#L120
for (uint i = 0; i < l; i++) {
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/HubbleViewer.sol#L137
for (uint i = 1; i < length; i++) {
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/HubbleViewer.sol#L367
for (uint256 i = 0; i < recipients.length; i++)
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/tests/Disperse.sol#L9
for (uint256 i = 0; i < recipients.length; i++)
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/tests/Disperse.sol#L18
for (uint256 i = 0; i < recipients.length; i++)
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/tests/Disperse.sol#L21
for (uint256 i = 0; i < recipients.length; i++)
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/tests/Disperse.sol#L27
for (uint256 i = 0; i < recipients.length; i++)
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/tests/Disperse.sol#L32
for (uint i = 0; i < numTraders; i++) {
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/tests/Leaderboard.sol#L43
for (uint j = 0; j < l; j++) {
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/tests/Leaderboard.sol#L45
for (uint i = 0; i < targets.length; i++) {
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/tests/Executor.sol#L19
for (uint i = 0; i < traders.length; i++) {
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/tests/BatchLiquidator.sol#L25
for (uint i = 0; i < traders.length; i++) {
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/tests/BatchLiquidator.sol#L31
for (uint i = 0; i < traders.length; i++) {
https://github.com/code-423n4/2022-02-hubble/blob/main/contracts/tests/BatchLiquidator.sol#L37
#0 - atvanguard
2022-02-26T08:17:28Z
Good report
#1 - moose-code
2022-03-05T15:15:36Z
Really nice format.