Platform: Code4rena
Start Date: 26/09/2022
Pot Size: $50,000 USDC
Total HM: 13
Participants: 113
Period: 5 days
Judge: 0xean
Total Solo HM: 6
Id: 166
League: ETH
Rank: 21/113
Findings: 2
Award: $150.83
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: 0xNazgul
Also found by: 0x1f8b, 0x52, 0xDecorativePineapple, 0xSmartContract, 0xmatt, Aeros, Aymen0909, Bnke0x0, Chom, CodingNameKiki, Deivitto, DimitarDimitrov, IllIllI, JC, Jeiwan, Lambda, Matin, Migue, Mukund, Ocean_Sky, Olivierdem, RaymondFam, RockingMiles, Rolezn, Ruhum, Satyam_Sharma, Shinchan, Tomo, Trabajo_de_mates, V_B, Waze, __141345__, a12jmx, ajtra, asutorufos, aysha, brgltd, bulej93, carrotsmuggler, catchup, cccz, chrisdior4, cryptonue, cryptphi, d3e4, defsec, delfin454000, durianSausage, erictee, fatherOfBlocks, gogo, kaden, karanctf, ladboy233, lukris02, mahdikarimi, martin, mics, natzuu, oyc_109, p_crypt0, pedr02b2, rbserver, reassor, rotcivegaf, rvierdiiev, sikorico, slowmoses, sorrynotsorry, tnevler, trustindistrust
126.7868 USDC - $126.79
Total Low Severity Findings: 5 Total Non-Critical Severity Findings: 6
Severity: Low
owner = _owner;
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraFactory.sol#L80
farmingAddress = _farmingAddress;
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraFactory.sol#L87
vaultAddress = _vaultAddress;
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraFactory.sol#L94
function deploy( address dataStorage, address _factory, address token0, address token1
Consider adding zero-address checks in the mentioned codebase.
Severity: Low
Users can potentially call functions that create and make it potentially malicicous XXX WORK ON DESCRIPTION XXX
function createPool(address tokenA, address tokenB) external override returns (address pool) {
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraFactory.sol#L59
function getOrCreatePosition(
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraPool.sol#L403
function createNewTimepoint(
Consider adding a mapping of who can call these create functions to avoid malicious use
Severity: Low
Algebra contracts are using low level calls with solidity version before 0.8.14 which can result in optimizer bug. https://medium.com/certora/overly-optimistic-optimizer-certora-bug-disclosure-2101e3f7994d
For example a low level call in AlgebraPool.sol:
pragma solidity =0.7.6; … function getOrCreatePosition( address owner, int24 bottomTick, int24 topTick[] ) private view returns (Position storage) { bytes32 key; assembly { key := or(shl(24, or(shl(24, owner), and(bottomTick, 0xFFFFFF))), and(topTick, 0xFFFFFF)) } return positions[key]; }
POC can be found in the above medium reference url.
Consider upgrading to at least solidity v0.8.15.
Severity: Low
The critical procedures should be two step process.
function setOwner(address _owner) external override onlyOwner {
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraFactory.sol#L77
function setFarmingAddress(address _farmingAddress) external override onlyOwner {
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraFactory.sol#L84
function setVaultAddress(address _vaultAddress) external override onlyOwner {
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraFactory.sol#L91
function setBaseFeeConfiguration(
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraFactory.sol#L98
function setFactory(address _factory) external override onlyOwner {
function setCommunityFee(uint8 communityFee0, uint8 communityFee1) external override lock onlyFactoryOwner {
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraPool.sol#L952
function setIncentive(address virtualPoolAddress) external override {
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraPool.sol#L959
function setLiquidityCooldown(uint32 newLiquidityCooldown) external override onlyFactoryOwner {
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraPool.sol#L967
Lack of two-step procedure for critical operations leaves them error-prone. Consider adding two step procedure on the critical functions.
Severity: Low
The Algebra contracts are heavily math-based contracts, it is recommended to use SafeMath to avoid potential overflows/underflows.
Apply safemath or move to solidity 0.8.x
Severity: Non-Critical
If the variable needs to be different based on which class it comes from, a view/pure function should be used instead.
bytes32 internal constant POOL_INIT_CODE_HASH = 0x6ec6c9c8091d160c0aa74b2b14ba9c1717e95093bd3ac085cee99a49aab294a4;
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraFactory.sol#L116
Severity: Non-Critical
Some parameters of constructors are not checked for invalid values.
address _poolDeployer
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraFactory.sol#L50
address _vaultAddress
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraFactory.sol#L50
address _pool
address deployer
Validate the parameters.
Severity: Non-Critical
The current form of relative path import is not recommended for use because it can unpredictably pollute the namespace. Instead, the Solidity docs recommend specifying imported symbols explicitly. https://docs.soliditylang.org/en/v0.8.15/layout-of-source-files.html#importing-other-source-files
import './interfaces/IAlgebraFactory.sol'; import './interfaces/IAlgebraPoolDeployer.sol'; import './interfaces/IDataStorageOperator.sol'; import './libraries/AdaptiveFee.sol'; import './DataStorageOperator.sol';
import './interfaces/IAlgebraPool.sol'; import './interfaces/IDataStorageOperator.sol'; import './interfaces/IAlgebraVirtualPool.sol'; import './base/PoolState.sol'; import './base/PoolImmutables.sol';
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraPool.sol#L4-L9
import './libraries/TokenDeltaMath.sol'; import './libraries/PriceMovementMath.sol'; import './libraries/TickManager.sol'; import './libraries/TickTable.sol'; import './libraries/LowGasSafeMath.sol'; import './libraries/SafeCast.sol'; import './libraries/FullMath.sol'; import './libraries/Constants.sol'; import './libraries/TransferHelper.sol'; import './libraries/TickMath.sol'; import './libraries/LiquidityMath.sol'; import './interfaces/IAlgebraPoolDeployer.sol'; import './interfaces/IAlgebraFactory.sol'; import './interfaces/IERC20Minimal.sol'; import './interfaces/callback/IAlgebraMintCallback.sol'; import './interfaces/callback/IAlgebraSwapCallback.sol'; import './interfaces/callback/IAlgebraFlashCallback.sol';
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraPool.sol#L11-L30
import './interfaces/IAlgebraPoolDeployer.sol'; import './AlgebraPool.sol'; import './interfaces/IAlgebraFactory.sol'; import './interfaces/IDataStorageOperator.sol'; import './libraries/DataStorage.sol'; import './libraries/Sqrt.sol'; import './libraries/AdaptiveFee.sol'; import './libraries/Constants.sol';
import '../interfaces/pool/IAlgebraPoolImmutables.sol'; import '../interfaces/IAlgebraPoolDeployer.sol'; import '../libraries/Constants.sol';
import '../interfaces/pool/IAlgebraPoolState.sol'; import '../libraries/TickManager.sol';
import './Constants.sol';
import './FullMath.sol';
import './FullMath.sol'; import './TokenDeltaMath.sol';
import './LowGasSafeMath.sol'; import './SafeCast.sol'; import './LiquidityMath.sol'; import './Constants.sol';
import './Constants.sol'; import './TickMath.sol';
import './LowGasSafeMath.sol'; import './SafeCast.sol'; import './FullMath.sol'; import './Constants.sol';
Use specific imports syntax per solidity docs recommendation.
Severity: Non-Critical
Use a solidity version of at least 0.8.4 to get bytes.concat() instead of abi.encodePacked(<bytes>,<bytes>) Use a solidity version of at least 0.8.12 to get string.concat() instead of abi.encodePacked(<str>,<str>) Use a solidity version of at least 0.8.13 to get the ability to use using for with a list of free functions
Found old version 0.7.6 of Solidity
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraFactory.sol#L2
Found old version 0.7.6 of Solidity
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraPool.sol#L2
Found old version 0.7.6 of Solidity
Found old version 0.7.6 of Solidity
Found old version 0.7.6 of Solidity
Found old version 0.7.6 of Solidity
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/base/PoolState.sol#L2
Found old version 0.7.6 of Solidity
Found old version 0.7.6 of Solidity
Found old version 0.7.6 of Solidity
Found old version 0.7.6 of Solidity
Found old version 0.7.6 of Solidity
Found old version 0.7.6 of Solidity
Found old version 0.7.6 of Solidity
Consider updating to a more recent solidity version.
Severity: Non-Critical
require(tokenA != tokenB);
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraFactory.sol#L60
require(token0 != address(0));
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraFactory.sol#L62
require(poolByPair[token0][token1] == address(0));
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraFactory.sol#L63
require(tokenA != tokenB);
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraFactory.sol#L60
require(token0 != address(0));
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraFactory.sol#L62
require(poolByPair[token0][token1] == address(0));
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraFactory.sol#L63
require(tokenA != tokenB);
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraFactory.sol#L60
require(token0 != address(0));
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraFactory.sol#L62
require(poolByPair[token0][token1] == address(0));
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraFactory.sol#L63
require(owner != _owner);
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraFactory.sol#L78
require(farmingAddress != _farmingAddress);
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraFactory.sol#L85
require(vaultAddress != _vaultAddress);
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraFactory.sol#L92
require(_lower.initialized);
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraPool.sol#L122
require(_upper.initialized);
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraPool.sol#L134
require(_lower.initialized);
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraPool.sol#L122
require(_upper.initialized);
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraPool.sol#L134
require((_blockTimestamp() - lastLiquidityAddTimestamp) >= _liquidityCooldown);
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraPool.sol#L229
require((communityFee0 <= Constants.MAX_COMMUNITY_FEE) && (communityFee1 <= Constants.MAX_COMMUNITY_FEE));
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraPool.sol#L953
require(msg.sender == IAlgebraFactory(factory).farmingAddress());
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraPool.sol#L960
require(newLiquidityCooldown <= Constants.MAX_LIQUIDITY_COOLDOWN && liquidityCooldown != newLiquidityCooldown);
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraPool.sol#L968
require(_factory != address(0));
require(factory == address(0));
require(_factory != address(0));
require(factory == address(0));
require(msg.sender == factory || msg.sender == IAlgebraFactory(factory).owner());
require(!self[0].initialized);
require(price > 0);
require(liquidity > 0);
require((product = amount * price) / amount == price); // if the product overflows, we know the denominator underflows
require(liquidityShifted > product); // in addition, we must check that the denominator does not underflow
require(price > quotient);
require(price > 0);
require(liquidity > 0);
require((product = amount * price) / amount == price); // if the product overflows, we know the denominator underflows
require(liquidityShifted > product); // in addition, we must check that the denominator does not underflow
require(price > quotient);
require(price > 0);
require(liquidity > 0);
require((product = amount * price) / amount == price); // if the product overflows, we know the denominator underflows
require(liquidityShifted > product); // in addition, we must check that the denominator does not underflow
require(price > quotient);
require(price > 0);
require(liquidity > 0);
require((product = amount * price) / amount == price); // if the product overflows, we know the denominator underflows
require(liquidityShifted > product); // in addition, we must check that the denominator does not underflow
require(price > quotient);
require(price > 0);
require(liquidity > 0);
require((product = amount * price) / amount == price); // if the product overflows, we know the denominator underflows
require(liquidityShifted > product); // in addition, we must check that the denominator does not underflow
require(price > quotient);
require(priceDelta < priceUpper); // forbids underflow and 0 priceLower
require(priceUpper >= priceLower);
Severity: Non-Critical
Use (e.g. 1e6) rather than decimal literals (e.g. 100000), for better code readability.
uint128 constant MAX_VOLUME_PER_LIQUIDITY = 100000 << 64; https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/DataStorageOperator.sol#L16
🌟 Selected for report: IllIllI
Also found by: 0x1f8b, 0x5rings, 0xNazgul, 0xRoxas, 0xSmartContract, 0xbepresent, 0xmatt, Aeros, Amithuddar, Awesome, Aymen0909, B2, Bnke0x0, ChristianKuri, CodingNameKiki, Deivitto, Diraco, Fitraldys, HardlyCodeMan, JC, Mukund, Noah3o6, Olivierdem, RaymondFam, ReyAdmirado, RockingMiles, Rolezn, Ruhum, Saintcode_, Shinchan, SnowMan, TomJ, Tomio, Tomo, V_B, Waze, __141345__, ajtra, asutorufos, aysha, beardofginger, bobirichman, brgltd, bulej93, c3phas, ch0bu, cryptonue, defsec, delfin454000, dharma09, durianSausage, emrekocak, erictee, fatherOfBlocks, francoHacker, gianganhnguyen, gogo, imare, kaden, karanctf, ladboy233, lukris02, m_Rassska, martin, medikko, mics, natzuu, oyc_109, peiw, rbserver, ret2basic, rotcivegaf, saian, shark, slowmoses, tnevler, trustindistrust, zeesaw, zishansami
24.0374 USDC - $24.04
Total Gas Optimizations: 15
Severity: Gas Optimizations
pool = address(uint256(keccak256(abi.encodePacked(hex'ff', poolDeployer, keccak256(abi.encode(token0, token1)), POOL_INIT_CODE_HASH))));
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraFactory.sol#L123
pool = address(new AlgebraPool{salt: keccak256(abi.encode(token0, token1))}());
Severity: Gas Optimizations
The overheads outlined below are PER LOOP, excluding the first loop
storage arrays incur a Gwarmaccess (100 gas) memory arrays use MLOAD (3 gas) calldata arrays use CALLDATALOAD (3 gas)
Caching the length changes each of these to a DUP<N> (3 gas), and gets rid of the extra DUP<N> needed to store the stack offset
for (uint256 i = 0; i < secondsAgos.length; i++) {
Severity: Gas Optimizations
When a function with a memory array is called externally, the abi.decode() step has to use a for-loop to copy each index of the calldata to the memory index. Each iteration of this for-loop costs at least 60 gas (i.e. 60 * <mem_array>.length). Using calldata directly, obliviates the need for such a loop in the contract code and runtime execution. Structs have the same overhead as an array of length one
function getTimepoints( uint32 time, uint32[] memory secondsAgos, int24 tick, uint16 index, uint128 liquidity ) https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/DataStorageOperator.sol#L88
function getTimepoints( Timepoint[UINT16_MODULO] storage self, uint32 time, uint32[] memory secondsAgos, int24 tick, uint16 index, uint128 liquidity
Severity: Gas Optimizations
Saves 6 gas per loop
for (uint256 i = 0; i < secondsAgos.length; i++) {
For example, use ++i instead of i++
Severity: Gas Optimizations
for (uint256 i = 0; i < secondsAgos.length; i++) {
Severity: Gas Optimizations
This change saves 6 gas per instance
require(currentLiquidity > 0, 'NP'); // Do not recalculate the empty ranges
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraPool.sol#L224
require(liquidityDesired > 0, 'IL');
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraPool.sol#L434
if (amount0 > 0) require((receivedAmount0 = balanceToken0() - receivedAmount0) > 0, 'IIAM');
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraPool.sol#L454
if (amount1 > 0) require((receivedAmount1 = balanceToken1() - receivedAmount1) > 0, 'IIAM');
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraPool.sol#L455
require(liquidityActual > 0, 'IIL2');
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraPool.sol#L469
require((amountRequired = int256(balanceToken0().sub(balance0Before))) > 0, 'IIA');
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraPool.sol#L641
require((amountRequired = int256(balanceToken1().sub(balance1Before))) > 0, 'IIA');
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraPool.sol#L645
require(_liquidity > 0, 'L');
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraPool.sol#L898
require(_feeConfig.gamma1 != 0 && _feeConfig.gamma2 != 0 && _feeConfig.volumeGamma != 0, 'Gammas must be > 0');
require(price > 0);
require(liquidity > 0);
Severity: Gas Optimizations
<x> * 2 is equivalent to <x> << 1 and <x> / 2 is the same as <x> >> 1. The MUL and DIV opcodes cost 5 gas, whereas SHL and SHR only cost 3 gas
res += (xLowestDegree * gHighestDegree) / 2;
Severity: Gas Optimizations
function _writeTimepoint( uint16 timepointIndex, uint32 blockTimestamp, int24 tick, uint128 liquidity, uint128 volumePerLiquidityInBlock
) private returns (uint16 newTimepointIndex) { https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraPool.sol#L551
function getAverages( uint32 time, int24 tick, uint16 index, uint128 liquidity
) external view override onlyPool returns (uint112 TWVolatilityAverage, uint256 TWVolumePerLiqAverage) { https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/DataStorageOperator.sol#L110
function write( uint16 index, uint32 blockTimestamp, int24 tick, uint128 liquidity, uint128 volumePerLiquidity
) external override onlyPool returns (uint16 indexUpdated) { https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/DataStorageOperator.sol#L120
function calculateVolumePerLiquidity( uint128 liquidity, int256 amount0, int256 amount1
) external pure override returns (uint128 volumePerLiquidity) { https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/DataStorageOperator.sol#L131
function getFee( uint32 _time, int24 _tick, uint16 _index, uint128 _liquidity
) external view override onlyPool returns (uint16 fee) { https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/DataStorageOperator.sol#L150
function getFee( uint88 volatility, uint256 volumePerLiquidity, Configuration memory config
) internal pure returns (uint16 fee) { https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/libraries/AdaptiveFee.sol#L25
function getSingleTimepoint( Timepoint[UINT16_MODULO] storage self, uint32 time, uint32 secondsAgo, int24 tick, uint16 index, uint16 oldestIndex, uint128 liquidity
) internal view returns (Timepoint memory targetTimepoint) { https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/libraries/DataStorage.sol#L205
function getAverages( Timepoint[UINT16_MODULO] storage self, uint32 time, int24 tick, uint16 index, uint128 liquidity
) internal view returns (uint88 volatilityAverage, uint256 volumePerLiqAverage) { https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/libraries/DataStorage.sol#L326
function getNewPriceAfterOutput( uint160 price, uint128 liquidity, uint256 output, bool zeroToOne
) internal pure returns (uint160 resultPrice) { https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/libraries/PriceMovementMath.sol#L36
function getNewPrice( uint160 price, uint128 liquidity, uint256 amount, bool zeroToOne, bool fromInput
) internal pure returns (uint160 resultPrice) { https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/libraries/PriceMovementMath.sol#L45
function cross( mapping(int24 => Tick) storage self, int24 tick, uint256 totalFeeGrowth0Token, uint256 totalFeeGrowth1Token, uint160 secondsPerLiquidityCumulative, int56 tickCumulative, uint32 time
) internal returns (int128 liquidityDelta) { https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/libraries/TickManager.sol#L129
Severity: Gas Optimizations
_position.fees0 += fees0;
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraPool.sol#L257
_position.fees1 += fees1;
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraPool.sol#L258
amountRequired -= (step.input + step.feeAmount).toInt256(); // decrease remaining input amount
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraPool.sol#L801
amountRequired += step.output.toInt256(); // increase remaining output amount (since its negative)
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraPool.sol#L804
step.feeAmount -= delta;
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraPool.sol#L810
communityFeeAmount += delta;
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraPool.sol#L811
if (currentLiquidity > 0) cache.totalFeeGrowth += FullMath.mulDiv(step.feeAmount, Constants.Q128, currentLiquidity);
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraPool.sol#L814
paid0 -= balance0Before;
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraPool.sol#L922
totalFeeGrowth0Token += FullMath.mulDiv(paid0 - fees0, Constants.Q128, _liquidity);
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraPool.sol#L931
paid1 -= balance1Before;
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraPool.sol#L936
totalFeeGrowth1Token += FullMath.mulDiv(paid1 - fees1, Constants.Q128, _liquidity);
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraPool.sol#L945
res += xLowestDegree * gHighestDegree;
res += (xLowestDegree * gHighestDegree) / 2;
res += (xLowestDegree * gHighestDegree) / 6;
res += (xLowestDegree * gHighestDegree) / 24;
res += (xLowestDegree * gHighestDegree) / 120;
res += (xLowestDegree * gHighestDegree) / 720;
res += (xLowestDegree * g) / 5040 + (xLowestDegree * x) / (40320);
last.tickCumulative += int56(tick) * delta;
last.secondsPerLiquidityCumulative += ((uint160(delta) << 128) / (liquidity > 0 ? liquidity : 1)); // just timedelta if liquidity == 0
last.volatilityCumulative += uint88(_volatilityOnRange(delta, prevTick, tick, last.averageTick, averageTick)); // always fits 88 bits
last.volumePerLiquidityCumulative += volumePerLiquidity;
index -= 1; // considering underflow
beforeOrAt.tickCumulative += ((atOrAfter.tickCumulative - beforeOrAt.tickCumulative) / timepointTimeDelta) * targetDelta;
beforeOrAt.secondsPerLiquidityCumulative += uint160(
beforeOrAt.volatilityCumulative += ((atOrAfter.volatilityCumulative - beforeOrAt.volatilityCumulative) / timepointTimeDelta) * targetDelta;
beforeOrAt.volumePerLiquidityCumulative +=
innerFeeGrowth0Token -= upper.outerFeeGrowth0Token;
innerFeeGrowth1Token -= upper.outerFeeGrowth1Token;
tick -= int24(255 - getMostSignificantBit(_row));
tick -= int24(bitNumber);
tick += 1;
tick += int24(getSingleSignificantBit(-_row & _row)); // least significant bit
tick += int24(255 - bitNumber);
Severity: Gas Optimizations
If needed, the value can be read from the verified contract source code. Savings are due to the compiler not having to create non-payable getter functions for deployment calldata, and not adding another entry to the method ID table
int32 public constant WINDOW = 1 days;
Set variable to private.
Severity: Gas Optimizations
assert(false);
Severity: Gas Optimizations
See https://github.com/code-423n4/2022-01-xdefi-findings/issues/128 which describes the fact that there is a larger deployment gas cost, but with enough runtime calls, the change ends up being cheaper
require(gamma1 != 0 && gamma2 != 0 && volumeGamma != 0, 'Gammas must be > 0');
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraFactory.sol#L110
require(limitSqrtPrice < currentPrice && limitSqrtPrice > TickMath.MIN_SQRT_RATIO, 'SPL');
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraPool.sol#L739
require(limitSqrtPrice > currentPrice && limitSqrtPrice < TickMath.MAX_SQRT_RATIO, 'SPL');
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraPool.sol#L743
require(limitSqrtPrice < currentPrice && limitSqrtPrice > TickMath.MIN_SQRT_RATIO, 'SPL');
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraPool.sol#L739
require(limitSqrtPrice > currentPrice && limitSqrtPrice < TickMath.MAX_SQRT_RATIO, 'SPL');
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraPool.sol#L743
require((communityFee0 <= Constants.MAX_COMMUNITY_FEE) && (communityFee1 <= Constants.MAX_COMMUNITY_FEE));
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraPool.sol#L953
require(newLiquidityCooldown <= Constants.MAX_LIQUIDITY_COOLDOWN && liquidityCooldown != newLiquidityCooldown);
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraPool.sol#L968
require(_feeConfig.gamma1 != 0 && _feeConfig.gamma2 != 0 && _feeConfig.volumeGamma != 0, 'Gammas must be > 0');
Severity: Gas Optimizations
Lower than uint256 size storage variables are less gas efficient. Using uint64 does not give any efficiency, actually, it is the opposite as EVM operates on default of 256-bit values so uint64 is more expensive in this case as it needs a conversion. It only gives improvements in cases where you can pack variables together, e.g. structs.
uint128 liquidity;
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraPool.sol#L42
uint32 lastLiquidityAddTimestamp;
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraPool.sol#L43
uint128 fees0;
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraPool.sol#L46
uint128 fees1;
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraPool.sol#L47
uint160 outerSecondPerLiquidity;
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraPool.sol#L98
uint32 outerSecondsSpent;
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraPool.sol#L99
uint32 globalTime = _blockTimestamp();
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraPool.sol#L148
uint32 timestamp = _blockTimestamp();
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraPool.sol#L198
uint32 _liquidityCooldown = liquidityCooldown;
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraPool.sol#L227
uint128 liquidityNext = LiquidityMath.addDelta(currentLiquidity, liquidityDelta);
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraPool.sol#L234
uint160 price;
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraPool.sol#L263
uint16 timepointIndex;
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraPool.sol#L265
uint32 time = _blockTimestamp();
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraPool.sol#L296
uint128 liquidityBefore = liquidity;
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraPool.sol#L354
uint16 newTimepointIndex = _writeTimepoint(cache.timepointIndex, _blockTimestamp(), cache.tick, liquidityBefore, volumePerLiquidityInBlock);
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraPool.sol#L355
uint128 liquidityForRA1 = uint128(FullMath.mulDiv(uint256(liquidityActual), receivedAmount1, amount1));
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraPool.sol#L463
uint160 currentPrice;
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraPool.sol#L596
uint128 currentLiquidity;
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraPool.sol#L598
uint128 volumePerLiquidityInBlock;
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraPool.sol#L677
uint160 secondsPerLiquidityCumulative;
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraPool.sol#L679
uint16 fee;
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraPool.sol#L687
uint160 stepSqrtPrice;
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraPool.sol#L693
uint160 nextTickPrice;
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraPool.sol#L696
uint32 blockTimestamp;
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraPool.sol#L718
uint128 _liquidity = liquidity;
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraPool.sol#L897
uint16 _fee = globalState.fee;
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraPool.sol#L900
uint8 _communityFeeToken0 = globalState.communityFeeToken0;
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraPool.sol#L925
uint8 _communityFeeToken1 = globalState.communityFeeToken1;
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/AlgebraPool.sol#L939
uint128 constant MAX_VOLUME_PER_LIQUIDITY = 100000 << 64;
uint16 oldestIndex;
uint16 nextIndex = index + 1;
uint160 price;
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/base/PoolState.sol#L9
uint16 fee;
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/base/PoolState.sol#L11
uint16 timepointIndex;
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/base/PoolState.sol#L12
uint8 communityFeeToken0;
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/base/PoolState.sol#L13
uint8 communityFeeToken1;
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/base/PoolState.sol#L14
uint128 public override liquidity;
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/base/PoolState.sol#L26
uint128 internal volumePerLiquidityInBlock;
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/base/PoolState.sol#L27
uint32 public override liquidityCooldown;
https://github.com/code-423n4/2022-09-quickswap/tree/main/src/core/contracts/base/PoolState.sol#L30
uint16 alpha1;
uint16 alpha2;
uint32 beta1;
uint32 beta2;
uint16 gamma1;
uint16 gamma2;
uint32 volumeBeta;
uint16 volumeGamma;
uint16 baseFee;
uint8 internal constant RESOLUTION = 96;
uint16 internal constant BASE_FEE = 100;
uint128 internal constant MAX_LIQUIDITY_PER_TICK = 11505743598341114571880798222544994;
uint32 internal constant MAX_LIQUIDITY_COOLDOWN = 1 days;
uint8 internal constant MAX_COMMUNITY_FEE = 250;
uint32 public constant WINDOW = 1 days;
uint32 blockTimestamp;
uint160 secondsPerLiquidityCumulative;
uint88 volatilityCumulative; // the volatility accumulator;
uint144 volumePerLiquidityCumulative;
uint32 delta = blockTimestamp - last.blockTimestamp;
uint32 oldestTimestamp = self[oldestIndex].blockTimestamp;
uint32 target = time - secondsAgo;
uint32 timepointTimeDelta = atOrAfter.blockTimestamp - beforeOrAt.blockTimestamp;
uint32 targetDelta = target - beforeOrAt.blockTimestamp;
uint16 oldestIndex;
uint16 nextIndex = index + 1;
uint32 oldestTimestamp = oldest.blockTimestamp;
uint88 _oldestVolatilityCumulative = oldest.volatilityCumulative;
uint144 _oldestVolumePerLiquidityCumulative = oldest.volumePerLiquidityCumulative;
uint32 _prevLastBlockTimestamp = _prevLast.blockTimestamp;
uint128 liquidityTotal;
uint160 outerSecondsPerLiquidity;
uint32 outerSecondsSpent;
uint128 liquidityTotalBefore = data.liquidityTotal;
uint128 liquidityTotalAfter = LiquidityMath.addDelta(liquidityTotalBefore, liquidityDelta);
uint8 bitNumber;
Severity: Gas Optimizations
The unchecked keyword is new in solidity version 0.8.0, so this only applies to that version or higher, which these instances are. This saves 30-40 gas PER LOOP
for (uint256 i = 0; i < secondsAgos.length; i++) {
Severity: Gas Optimizations
Save 6 gas per instance if using assembly to check for address(0)
e.g. assembly { if iszero(_addr) { mstore(0x00, "AddressZero") revert(0x00, 0x20) } }
function setFactory(address _factory) external override onlyOwner {