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

Gas Optimizations #34

Open
code423n4 opened this issue Feb 21, 2022 · 1 comment
Open

Gas Optimizations #34

code423n4 opened this issue Feb 21, 2022 · 1 comment
Labels
bug Something isn't working duplicate This issue or pull request already exists G (Gas Optimization)

Comments

@code423n4
Copy link
Contributor

Gas Optimizations

Loop optimizations

Loops can be optimized in several ways. Let's take for example the loop in the _liquidateMaker function in ClearingHouse.

for (uint i = 0; i < amms.length; i++) {
    (,, uint dToken,,,,) = amms[i].makers(maker);
    // @todo put checks on slippage
    (int256 _realizedPnl, uint _quote) = amms[i].removeLiquidity(maker, dToken, 0, 0);
    realizedPnl += _realizedPnl;
    quoteAsset += _quote;
}

We can do multiple things here:

  1. Variables in solidity are already initialized to their default value, and initializing them to the same value actually costs more gas. So for example in the loop above, the code can be optimized using uint i; instead of uint i = 0;.
  2. Use ++i instead of i++ to save some gas spent in every iteration.
  3. Save the array length in a local variable before the loop instead of accessing it in every iteration.
  4. Save amms[i] in a local variable instead of accessing the i element of the array twice in every iteration.
    So after all these changes, the code will look something like this:
uint length = amms.length;
IAMM amm_i;
for (uint i; i < length; ++i) {
    amm_i = amms[i];
    (,, uint dToken,,,,) = amm_i.makers(maker);
    // @todo put checks on slippage
    (int256 _realizedPnl, uint _quote) = amm_i.removeLiquidity(maker, dToken, 0, 0);
    realizedPnl += _realizedPnl;
    quoteAsset += _quote;
}

There are more loops in the code that can be optimized the same way, for example in the ClearingHouse, MarginAccount and the HubbleViewer contracts.

save return value of a function instead of calling it multiple times

in the _calcTwap function in the AMM contract there are multiple calls to the _blockTimestamp(), and it can be called once to save gas.

avoid accessing a mapping multiple times

in the _calcTwap function in the AMM contract, instead of accessing the reserveSnapshots[snapshotIndex] twice in the loop it can be accessed only once.
old code:

currentSnapshot = reserveSnapshots[snapshotIndex];
currentPrice = reserveSnapshots[snapshotIndex].lastPrice;

new code:

currentSnapshot = reserveSnapshots[snapshotIndex];
currentPrice = currentSnapshot.lastPrice;

this can be done in some other places in the code, like the _increasePosition function for example, when the positions mapping is accessed twice.
old code:

positions[trader].size += baseAssetQuantity; // -ve baseAssetQuantity will increase short position
positions[trader].openNotional += quoteAsset;

new code:

Position storage pos = positions[trader];
pos.size += baseAssetQuantity; // -ve baseAssetQuantity will increase short position
pos.openNotional += quoteAsset;

another place it can be done is in removeMargin in the MarginAccount when accessing margin[idx][trader] twice.

@code423n4 code423n4 added bug Something isn't working G (Gas Optimization) labels Feb 21, 2022
code423n4 added a commit that referenced this issue Feb 21, 2022
@atvanguard
Copy link
Collaborator

Good report, also duplicates.

@atvanguard atvanguard added the duplicate This issue or pull request already exists label Feb 26, 2022
@CloudEllie CloudEllie reopened this Mar 30, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working duplicate This issue or pull request already exists G (Gas Optimization)
Projects
None yet
Development

No branches or pull requests

3 participants