Platform: Code4rena
Start Date: 24/06/2021
Pot Size: $80,000 USDC
Total HM: 18
Participants: 12
Period: 7 days
Judge: cemozer
Total Solo HM: 11
Id: 16
League: ETH
Rank: 11/12
Findings: 3
Award: $881.38
π Selected for report: 1
π Solo Findings: 0
a_delamo
Use latestRoundData instead of latestAnswer for chainlink Oracles in order to be able to run more validations like
( roundId, rawPrice, , updateTime, answeredInRound ) = AggregatorV3Interface(source.source).latestRoundData(); require(rawPrice > 0, "Chainlink price <= 0"); require(updateTime != 0, "Incomplete round"); require(answeredInRound >= roundId, "Stale price");
Provide direct links to all referenced code in GitHub. Add screenshots, logs, or any other relevant proof that illustrates the concept.
#0 - raymogg
2021-07-05T06:10:19Z
Duplicate of #145
#1 - loudoguno
2021-08-24T16:06:41Z
changed risk from 1 to 2 as per judges sheet
181.1748 USDC - $181.17
a_delamo
The method executeTrade
on Trader.sol
is calling matchOrders
method of the TracerPerpetualSwaps contract. executeTrade
is validating that the call was successful, but is missing to validate the return result == true. As a result, we will be adding invalid trade.
(bool success, ) = makeOrder.market.call( abi.encodePacked( ITracerPerpetualSwaps(makeOrder.market).matchOrders.selector, abi.encode(makeOrder, takeOrder, fillAmount) ) ); // ignore orders that cannot be executed //FIXME: We should also check if return == false if (!success) continue; // update order state filled[makerOrderId] = makeOrderFilled + fillAmount; filled[takerOrderId] = takeOrderFilled + fillAmount; averageExecutionPrice[makerOrderId] = newMakeAverage; averageExecutionPrice[takerOrderId] = newTakeAverage;
.... // validate orders can match, and outcome state is valid if ( !Perpetuals.canMatch(order1, filled1, order2, filled2) || !Balances.marginIsValid( newPos1, balances[order1.maker].lastUpdatedGasPrice * LIQUIDATION_GAS_COST, pricingContract.fairPrice(), trueMaxLeverage() ) || !Balances.marginIsValid( newPos2, balances[order2.maker].lastUpdatedGasPrice * LIQUIDATION_GAS_COST, pricingContract.fairPrice(), trueMaxLeverage() ) ) { // emit failed to match event and return false if (order1.side == Perpetuals.Side.Long) { emit FailedOrders( order1.maker, order2.maker, order1Id, order2Id ); } else { emit FailedOrders( order2.maker, order1.maker, order2Id, order1Id ); } return false; } ....
#0 - loudoguno
2021-08-24T16:55:10Z
adding duplicate label (of #71 ) and closing as per judges sheet
π Selected for report: a_delamo
333.3333 USDC - $333.33
a_delamo
For every new TracerPerpetualSwaps contract, we need to deploy a new Liquidation, Insurance, and Pricing contract. All these deployments are really gas-intensive, so it would be recommended to use EIP-1167: Minimal Proxy Contract to reduce the gas cost of the deployments.
function _deployTracer( bytes calldata _data, address tracerOwner, address oracle, address fastGasOracle, uint256 maxLiquidationSlippage ) internal returns (address) { // Create and link tracer to factory address market = IPerpsDeployer(perpsDeployer).deploy(_data); ITracerPerpetualSwaps tracer = ITracerPerpetualSwaps(market); validTracers[market] = true; tracersByIndex[tracerCounter] = market; tracerCounter++; // Instantiate Insurance contract for tracer address insurance = IInsuranceDeployer(insuranceDeployer).deploy(market); address pricing = IPricingDeployer(pricingDeployer).deploy(market, insurance, oracle); address liquidation = ILiquidationDeployer(liquidationDeployer).deploy( pricing, market, insurance, fastGasOracle, maxLiquidationSlippage ); // Perform admin operations on the tracer to finalise linking tracer.setInsuranceContract(insurance); tracer.setPricingContract(pricing); tracer.setLiquidationContract(liquidation); // Ownership either to the deployer or the DAO tracer.transferOwnership(tracerOwner); ILiquidation(liquidation).transferOwnership(tracerOwner); emit TracerDeployed(tracer.marketId(), address(tracer)); return market; }
More info: https://blog.openzeppelin.com/deep-dive-into-the-minimal-proxy-contract/ https://eips.ethereum.org/EIPS/eip-1167