Rubicon contest - 0xkatana's results

An order book protocol for Ethereum, built on L2s.

General Information

Platform: Code4rena

Start Date: 23/05/2022

Pot Size: $50,000 USDC

Total HM: 44

Participants: 99

Period: 5 days

Judge: hickuphh3

Total Solo HM: 11

Id: 129

League: ETH

Rubicon

Findings Distribution

Researcher Performance

Rank: 85/99

Findings: 1

Award: $50.15

🌟 Selected for report: 0

🚀 Solo Findings: 0

[G-01] Use prefix not postfix in loops

Using a prefix increment (++i) instead of a postfix increment (i++) saves gas for each loop cycle and so can have a big gas impact when the loop executes on a large number of elements.

There are many examples of this in for loops https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/rubiconPools/BathToken.sol#L635 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/rubiconPools/BathToken.sol#L733 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/rubiconPools/BathPair.sol#L206 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/rubiconPools/BathPair.sol#L311 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/rubiconPools/BathPair.sol#L427 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/rubiconPools/BathPair.sol#L480 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/rubiconPools/BathPair.sol#L582 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/RubiconRouter.sol#L85 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/RubiconRouter.sol#L169 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/RubiconRouter.sol#L227 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/RubiconMarket.sol#L436 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/RubiconMarket.sol#L1165 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/RubiconMarket.sol#L1197

Use prefix not postfix to increment in a loop

[G-02] Redundant zero initialization

Solidity does not recognize null as a value, so uint variables are initialized to zero. Setting a uint variable to zero is redundant and can waste gas.

There were many places where an int is initialized to zero https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/rubiconPools/BathToken.sol#L635 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/rubiconPools/BathPair.sol#L311 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/rubiconPools/BathPair.sol#L427 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/rubiconPools/BathPair.sol#L480 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/rubiconPools/BathPair.sol#L582 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/RubiconRouter.sol#L82 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/RubiconRouter.sol#L83 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/RubiconRouter.sol#L85 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/RubiconRouter.sol#L168 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/RubiconRouter.sol#L169 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/RubiconRouter.sol#L226 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/RubiconRouter.sol#L227 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/RubiconMarket.sol#L990

Remove the redundant zero initialization uint256 i; instead of uint256 i = 0;

[G-03] Split up require statements instead of &&

Combining require statement conditions with && logic uses unnecessary gas. It is better to split up each part of the logical statement into a separate require statements

One example is

require(_bathAssetAddress != address(0) && _bathQuoteAddress != address(0), "tokenToBathToken error");

This can be improved to

require(_bathAssetAddress != address(0)); require(_bathQuoteAddress != address(0));

Several places had require statements with many logical "and"s. Instead, split into two to save gas https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/rubiconPools/BathToken.sol#L741 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/rubiconPools/BathPair.sol#L122 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/rubiconPools/BathPair.sol#L333 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/rubiconPools/BathPair.sol#L334 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/rubiconPools/BathPair.sol#L347 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/rubiconPools/BathPair.sol#L420 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/rubiconPools/BathPair.sol#L421 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/rubiconPools/BathPair.sol#L472 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/rubiconPools/BathPair.sol#L473 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/rubiconPools/BathPair.sol#L474 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/rubiconPools/BathPair.sol#L507 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/RubiconMarket.sol#L716 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/RubiconMarket.sol#L717 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/RubiconMarket.sol#L1178

Use separate require statements instead of concatenating with &&

[G-04] Cache array length before loop

Caching the array length outside a loop saves reading it on each iteration, as long as the array's length is not changed during the loop. This saves gas.

This was found in many places https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/rubiconPools/BathToken.sol#L635 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/rubiconPools/BathPair.sol#L311 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/rubiconPools/BathPair.sol#L582 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/RubiconRouter.sol#L169 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/RubiconRouter.sol#L227

Cache the array length before the for loop

[G-05] Use != 0 instead of > 0

Using > 0 uses slightly more gas than using != 0. Use != 0 when comparing uint variables to zero, which cannot hold values below zero

Locations where this was found include https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/peripheral_contracts/BathBuddy.sol#L102 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/rubiconPools/BathToken.sol#L634 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/rubiconPools/BathPair.sol#L232 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/rubiconPools/BathPair.sol#L252 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/rubiconPools/BathPair.sol#L333 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/rubiconPools/BathPair.sol#L334 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/rubiconPools/BathPair.sol#L515 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/rubiconPools/BathPair.sol#L523 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/rubiconPools/BathPair.sol#L597 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/rubiconPools/BathPair.sol#L611 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/rubiconPools/BathHouse.sol#L111 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/rubiconPools/BathHouse.sol#L281 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/RubiconRouter.sol#L354 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/proxy/UpgradeableProxy.sol#L30 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/proxy/Address.sol#L36 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/proxy/Address.sol#L240 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/RubiconMarket.sol#L233 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/RubiconMarket.sol#L400 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/RubiconMarket.sol#L402 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/RubiconMarket.sol#L837 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/RubiconMarket.sol#L876 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/RubiconMarket.sol#L918 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/RubiconMarket.sol#L942 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/RubiconMarket.sol#L985 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/RubiconMarket.sol#L1002 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/RubiconMarket.sol#L1063 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/RubiconMarket.sol#L1099 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/RubiconMarket.sol#L1100 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/RubiconMarket.sol#L1175 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/RubiconMarket.sol#L1217

Replace > 0 with != 0 to save gas

[G-06] Use type(uint256).max

The value 2**256 - 1 is used for some variables but using type(uint256).max uses less gas than this constant value. Source https://forum.openzeppelin.com/t/using-the-maximum-integer-in-solidity/3000/13

There are five places where this change can save gas https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/rubiconPools/BathToken.sol#L214 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/rubiconPools/BathToken.sol#L256 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/rubiconPools/BathToken.sol#L421 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/rubiconPools/BathToken.sol#L451 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/RubiconRouter.sol#L157

Use type(uint256).max

[G-07] For loop incrementing can be unsafe

For loops that use i++ do not need to use safemath for this operation because the loop would run out of gas long before this point. Making this addition operation unsafe using unchecked saves gas.

Sample code to make the for loop increment unsafe

for (uint i = 0; i < length; i = unchecked_inc(i)) { // do something that doesn't change the value of i } function unchecked_inc(uint i) returns (uint) { unchecked { return i + 1; } }

Idea borrowed from https://gist.github.com/hrkrshnn/ee8fabd532058307229d65dcd5836ddc#the-increment-in-for-loop-post-condition-can-be-made-unchecked

There are many for loops and that can use this change https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/rubiconPools/BathToken.sol#L635 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/rubiconPools/BathPair.sol#L311 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/rubiconPools/BathPair.sol#L427 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/rubiconPools/BathPair.sol#L480 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/rubiconPools/BathPair.sol#L582 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/RubiconRouter.sol#L85 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/RubiconRouter.sol#L169 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/RubiconRouter.sol#L227

Make the increment in for loops unsafe to save gas

[G-08] Use iszero assembly for zero checks

Comparing a value to zero can be done using the iszero EVM opcode. This can save gas

Source from t11s https://twitter.com/transmissions11/status/1474465495243898885

There are many places where a value is compared to zero https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/peripheral_contracts/SafeMathE.sol#L17 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/rubiconPools/BathToken.sol#L315 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/rubiconPools/BathToken.sol#L317 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/rubiconPools/BathToken.sol#L399 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/rubiconPools/BathToken.sol#L457 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/rubiconPools/BathToken.sol#L480 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/rubiconPools/BathToken.sol#L494 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/rubiconPools/BathToken.sol#L569 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/RubiconRouter.sol#L86 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/RubiconRouter.sol#L171 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/RubiconRouter.sol#L229 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/RubiconRouter.sol#L236 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/RubiconRouter.sol#L464 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/RubiconMarket.sol#L54 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/RubiconMarket.sol#L287 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/RubiconMarket.sol#L288 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/RubiconMarket.sol#L341 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/RubiconMarket.sol#L1009 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/RubiconMarket.sol#L1093 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/RubiconMarket.sol#L1137 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/RubiconMarket.sol#L1178

Use the assembly iszero evm opcode to compare values to zero

[G-09] Save gas with unchecked

Use unchecked math when there is no overflow risk to save gas. Before index is decreased in remove it is checked for zero condition. This means index will not underflow and can be unchecked.

These subtractions do not need to be checked for underflows because they are in if statements or while loops that confirm the underflow will not happen https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/RubiconMarket.sol#L852 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/RubiconMarket.sol#L891 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/RubiconMarket.sol#L917 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/RubiconMarket.sol#L941

Add unchecked around math that can't overflow for gas savings. In Solidity before 0.8.0, use the normal math operators instead of safe math functions.

[G-10] Add payable to functions that won't receive ETH

Identifying a function as payable saves gas. Functions that have a modifier like onlyOwner or auth cannot be called by normal users and will not mistakenly receive ETH. These functions can be payable to save gas.

There are many functions that have the auth modifier in the contracts. Some examples are https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/RubiconMarket.sol#L22 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/RubiconMarket.sol#L479 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/RubiconMarket.sol#L733 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/RubiconMarket.sol#L747 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/RubiconMarket.sol#L762 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/RubiconMarket.sol#L1231 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/RubiconMarket.sol#L1239 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/RubiconMarket.sol#L1249 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/RubiconMarket.sol#L1256

Add payable to these functions for gas savings

[G-11] Use internal function in place of modifier

An internal function can save gas vs. a modifier. A modifier inlines the code of the original function but an internal function does not.

Source https://blog.polymath.network/solidity-tips-and-tricks-to-save-gas-and-reduce-bytecode-size-c44580b218e6#dde7

Many modifiers can use this change https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/rubiconPools/BathToken.sol#L226 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/rubiconPools/BathToken.sol#L234 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/rubiconPools/BathPair.sol#L142 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/rubiconPools/BathPair.sol#L147 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/rubiconPools/BathHouse.sol#L87 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/proxy/TransparentUpgradeableProxy.sol#L66 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/RubiconMarket.sol#L27 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/RubiconMarket.sol#L209 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/RubiconMarket.sol#L215 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/RubiconMarket.sol#L221 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/RubiconMarket.sol#L225 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/RubiconMarket.sol#L452 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/RubiconMarket.sol#L458 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/RubiconMarket.sol#L465 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/RubiconMarket.sol#L494 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/RubiconMarket.sol#L570

Use internal functions in place of modifiers to save gas.

[G-12] Use newer solidity version

A solidity version before 0.8.X is used. The latest release of solidity includes changes that can provide gas savings. The improvements include: The advantages of versions 0.8.* over <0.8.0 are:

  • Safemath by default from 0.8.0 (can be more gas efficient than some library based safemath).
  • Low level inliner from 0.8.2, leads to cheaper runtime gas. Especially relevant when the contract has small functions. For example, OpenZeppelin libraries typically have a lot of small helper functions and if they are not inlined, they cost an additional 20 to 40 gas because of 2 extra jump instructions and additional stack operations needed for function calls.
  • Optimizer improvements in packed structs: Before 0.8.3, storing packed structs, in some cases used an additional storage read operation. After EIP-2929, if the slot was already cold, this means unnecessary stack operations and extra deploy time costs. However, if the slot was already warm, this means additional cost of 100 gas alongside the same unnecessary stack operations and extra deploy time costs.
  • Custom errors from 0.8.4, leads to cheaper deploy time cost and run time cost. Note: the run time cost is only relevant when the revert condition is met. In short, replace revert strings by custom errors.
  • Solidity version 0.8.13 can save more gas with Yul IR pipeline

Source https://gist.github.com/hrkrshnn/ee8fabd532058307229d65dcd5836ddc#upgrade-to-at-least-084

Use solidity release 0.8.13 with Yul IR pipeline and other improvements for gas savings

[G-13] Use simple comparison in trinary logic

The comparison operators >= and <= use more gas than >, <, or ==. Replacing the >= and ≤ operators with a comparison operator that has an opcode in the EVM saves gas

The existing code is https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/RubiconMarket.sol#L62 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/RubiconMarket.sol#L70

return x >= y ? x : y;

A simple comparison can be used for gas savings by reversing the logic

return x < y ? y : x;

Other places with this https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/RubiconMarket.sol#L58 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/RubiconMarket.sol#L66

Replace the comparison operator and reverse the logic to save gas using the suggestions above

[G-14] Use simple comparison in if statement

The comparison operators >= and <= use more gas than >, <, or ==. Replacing the >= and ≤ operators with a comparison operator that has an opcode in the EVM saves gas

The existing code is https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/RubiconMarket.sol#L849

if (pay_amt >= offers[offerId].buy_amt) { //If amount to sell is higher or equal than current offer amount to buy fill_amt = add(fill_amt, offers[offerId].pay_amt); //Add amount bought to acumulator pay_amt = sub(pay_amt, offers[offerId].buy_amt); //Decrease amount to sell take(bytes32(offerId), uint128(offers[offerId].pay_amt)); //We take the whole offer } else { // if lower uint256 baux = rmul( pay_amt * 10**9, rdiv(offers[offerId].pay_amt, offers[offerId].buy_amt) ) / 10**9; fill_amt = add(fill_amt, baux); //Add amount bought to acumulator take(bytes32(offerId), uint128(baux)); //We take the portion of the offer that we need pay_amt = 0; //All amount is sold }

A simple comparison can be used for gas savings by reversing the logic

if (pay_amt < offers[offerId].buy_amt) { // if lower uint256 baux = rmul( pay_amt * 10**9, rdiv(offers[offerId].pay_amt, offers[offerId].buy_amt) ) / 10**9; fill_amt = add(fill_amt, baux); //Add amount bought to acumulator take(bytes32(offerId), uint128(baux)); //We take the portion of the offer that we need pay_amt = 0; //All amount is sold } else { //If amount to sell is higher or equal than current offer amount to buy fill_amt = add(fill_amt, offers[offerId].pay_amt); //Add amount bought to acumulator pay_amt = sub(pay_amt, offers[offerId].buy_amt); //Decrease amount to sell take(bytes32(offerId), uint128(offers[offerId].pay_amt)); //We take the whole offer }

Other places with this https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/RubiconMarket.sol#L888

Replace the comparison operator and reverse the logic to save gas using the suggestions above

[G-15] Bitshift for divide by 2

When multiply or dividing by a power of two, it is cheaper to bitshift than to use standard math operations.

There is a divide by 2 operation on these lines https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/RubiconMarket.sol#L77 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/RubiconMarket.sol#L81 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/RubiconMarket.sol#L85 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/RubiconMarket.sol#L89

Bitshift right by one bit instead of dividing by 2 to save gas

[G-16] Non-public variables save gas

Many constant variables are public, but changing the visibility of these variables to private or internal can save gas.

https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/peripheral_contracts/TokenWithFaucet.sol#L16 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/peripheral_contracts/SafeMathE.sol#L23 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/peripheral_contracts/SafeMathE.sol#L24 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/rubiconPools/BathToken.sol#L70 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/RubiconMarket.sol#L73 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/RubiconMarket.sol#L74

Declare some public variables as private or internal to save gas

[G-17] Use calldata instead of memory for function arguments

Using calldata instead of memory for function arguments saves gas sometimes. This can happen when a function is called externally and the memory array values are kept in calldata and copied to memory during ABI decoding (using the opcode calldataload and mstore). If the array is used in a for loop, arr[i] accesses the value in memory using a mload. If calldata is used instead, then instead of going via memory, the value is directly read from calldata using calldataload. That is, there are no intermediate memory operations that carries this value.

Many cases of function arguments using memory instead of calldata can use this improvement to save gas https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/rubiconPools/BathPair.sol#L413-L417 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/rubiconPools/BathPair.sol#L464-L469 https://github.com/code-423n4/2022-05-rubicon/blob/main/contracts/rubiconPools/BathPair.sol#L578

Source https://gist.github.com/hrkrshnn/ee8fabd532058307229d65dcd5836ddc#use-calldata-instead-of-memory-for-function-parameters

Change function arguments from memory to calldata

[G-18] Write contracts in vyper

The contracts are all written entirely in solidity. Writing contracts with vyper instead of solidity can save gas.

Source https://twitter.com/eiber_david/status/1515737811881807876 doggo demonstrates https://twitter.com/fubuloubu/status/1528179581974417414?t=-hcq_26JFDaHdAQZ-wYxCA&s=19

Write some or all of the contracts in vyper to save gas

AuditHub

A portfolio for auditors, a security profile for protocols, a hub for web3 security.

Built bymalatrax © 2024

Auditors

Browse

Contests

Browse

Get in touch

ContactTwitter