Timeswap contest - Rolezn's results

Like Uniswap, but for lending & borrowing.

General Information

Platform: Code4rena

Start Date: 20/01/2023

Pot Size: $90,500 USDC

Total HM: 10

Participants: 59

Period: 7 days

Judge: Picodes

Total Solo HM: 4

Id: 206

League: ETH

Timeswap

Findings Distribution

Researcher Performance

Rank: 18/59

Findings: 3

Award: $326.64

QA:
grade-b
Gas:
grade-b

🌟 Selected for report: 0

🚀 Solo Findings: 0

Findings Information

🌟 Selected for report: RaymondFam

Also found by: Rolezn, SaeedAlipoor01988, kaden, mert_eren, nadin, pavankv, rbserver

Labels

bug
2 (Med Risk)
satisfactory
sponsor acknowledged
edited-by-warden
duplicate-247

Awards

212.7503 USDC - $212.75

External Links

Lines of code

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/TimeswapV2Option.sol#L220 https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/TimeswapV2Option.sol#L259 https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/TimeswapV2Option.sol#L262

Vulnerability details

Some tokens take a transfer fee (e.g. STA, PAXG), some do not currently charge a fee but may do so in the future (e.g. USDT, USDC).

Should a fee-on-transfer token be used, it could be abused to mint more shares. In the current implementation, TimeswapV2Option.sol#swap() and TimeswapV2Option.sol#collect() assume that the received amount is the same as the transfer amount, and uses it to calculate funds. As a result, users will be unable to properly use the functionality of swap and collect functions due to how fee-on-transfer tokens work.

<ins>Proof Of Concept</ins>
220: IERC20(param.isLong0ToLong1 ? token0 : token1).safeTransfer(param.tokenTo, param.isLong0ToLong1 ? token0AndLong0Amount : token1AndLong1Amount);

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/TimeswapV2Option.sol#L220

259: if (token0Amount != 0) IERC20(token0).safeTransfer(param.token0To, token0Amount);
262: if (token1Amount != 0) IERC20(token1).safeTransfer(param.token1To, token1Amount);

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/TimeswapV2Option.sol#L259

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/TimeswapV2Option.sol#L262

<ins>Recommended Mitigation Steps</ins>
  • Consider comparing before and after balance to get the actual transferred amount.
  • Alternatively, disallow tokens with fee-on-transfer mechanics to be added as reward tokens.

#0 - c4-judge

2023-02-02T21:22:48Z

Picodes marked the issue as primary issue

#1 - c4-sponsor

2023-02-08T13:00:55Z

vhawk19 marked the issue as sponsor disputed

#2 - c4-sponsor

2023-02-08T13:36:33Z

vhawk19 marked the issue as sponsor acknowledged

#3 - vhawk19

2023-02-08T13:36:43Z

This is currently not supported by design

#4 - c4-judge

2023-02-12T22:21:28Z

Picodes marked issue #247 as primary and marked this issue as a duplicate of 247

#5 - c4-judge

2023-02-12T22:37:39Z

Picodes marked the issue as satisfactory

Awards

65.3481 USDC - $65.35

Labels

bug
grade-b
QA (Quality Assurance)
Q-39

External Links

Summary<a name="Summary">

Low Risk Issues

IssueContexts
LOW‑1Low Level Calls With Solidity Version 0.8.14 Can Result In Optimiser Bug1
LOW‑2Use _safeMint instead of _mint4
LOW‑3Missing parameter validation in constructor5
LOW‑4Contracts are not using their OZ Upgradeable counterparts9
LOW‑5Remove unused code3

Total: 22 contexts over 5 issues

Non-critical Issues

IssueContexts
NC‑1Add a timelock to critical functions1
NC‑2Avoid Floating Pragmas: The Version Should Be Locked13
NC‑3Critical Changes Should Use Two-step Procedure1
NC‑4Function writing that does not comply with the Solidity Style Guide88
NC‑5Use delete to Clear Variables11
NC‑6NatSpec return parameters should be included in contractsAll in-scope contracts
NC‑7Lines are too long10
NC‑8Implementation contract may not be initialized8
NC‑9NatSpec comments should be increased in contractsAll in-scope contracts
NC‑10Use a more recent version of Solidity88

Total: 396 contexts over 10 issues

Low Risk Issues

<a href="#Summary">[LOW‑1]</a><a name="LOW&#x2011;1"> Low Level Calls With Solidity Version Before 0.8.14 Can Result In Optimiser Bug

The project contracts in scope 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

Simliar findings in Code4rena contests for reference: https://code4rena.com/reports/2022-06-illuminate/#5-low-level-calls-with-solidity-version-0814-can-result-in-optimiser-bug

<ins>Proof Of Concept</ins>

POC can be found in the above medium reference url.

Functions that execute low level calls in contracts with solidity version under 0.8.14

18: assembly {
            switch iszero(_length)
            case 0 {
                // Get a location of some free memory and store it in tempBytes as
                // Solidity does for memory variables.
                tempBytes := mload(0x40)

                // The first word of the slice result is potentially a partial
                // word read from the original array. To read it, we calculate
                // the length of that partial word and start copying that many
                // bytes into the array. The first word we copy will start with
                // data we don't care about, but the last `lengthmod` bytes will
                // land at the beginning of the contents of the new array. When
                // we're done copying, we overwrite the full first word with
                // the actual length of the slice.
                let lengthmod := and(_length, 31)

                // The multiplication in the next line is necessary
                // because when slicing multiples of 32 bytes (lengthmod == 0)
                // the following copy loop was copying the origin's length
                // and then ending prematurely not copying everything it should.
                let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod)))
                let end := add(mc, _length)

                for {
                    // The multiplication in the next line has the same exact purpose
                    // as the one above.
                    let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start)
                } lt(mc, end) {
                    mc := add(mc, 0x20)
                    cc := add(cc, 0x20)
                } {
                    mstore(mc, mload(cc))
                }

                mstore(tempBytes, _length)

                //update free-memory pointer
                //allocating the array padded to 32 bytes like the compiler does now
                mstore(0x40, and(add(mc, 31), not(31)))
            }
            //if we want a zero-length slice let's just return a zero-length array
            default {
                tempBytes := mload(0x40)
                //zero out the 32 bytes slice we are about to return
                //we need to do it because Solidity does not garbage collect
                mstore(tempBytes, 0)

                mstore(0x40, add(tempBytes, 0x20))
            }
        }

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-library/src/BytesLib.sol#L18

<ins>Recommended Mitigation Steps</ins>

Consider upgrading to at least solidity v0.8.15.

<a href="#Summary">[LOW‑2]</a><a name="LOW&#x2011;2"> Use _safeMint instead of _mint

According to openzepplin's ERC721, the use of _mint is discouraged, use _safeMint whenever possible. https://docs.openzeppelin.com/contracts/3.x/api/token/erc721#ERC721-_mint-address-uint256-

<ins>Proof Of Concept</ins>
128: _mint(param.to, id, param.liquidityAmount, bytes(""));

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/TimeswapV2LiquidityToken.sol#L128

110: _mint(param.long0To, id, (param.long0Amount), bytes(""));

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/TimeswapV2Token.sol#L110

139: _mint(param.long1To, id, (param.long1Amount), bytes(""));

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/TimeswapV2Token.sol#L139

168: _mint(param.shortTo, id, (param.shortAmount), bytes(""));

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/TimeswapV2Token.sol#L168

<ins>Recommended Mitigation Steps</ins>

Use _safeMint whenever possible instead of _mint

<a href="#Summary">[LOW‑3]</a><a name="LOW&#x2011;3"> Missing parameter validation in constructor

Some parameters of constructors are not checked for invalid values.

<ins>Proof Of Concept</ins>
37: address chosenOwner

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/TimeswapV2PoolFactory.sol#L37

18: address chosenOwner

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/base/OwnableTwoSteps.sol#L18

36: address chosenOptionFactory
36: address chosenPoolFactory

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/TimeswapV2LiquidityToken.sol#L36-L36

41: address chosenOptionFactory

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/TimeswapV2Token.sol#L41

<ins>Recommended Mitigation Steps</ins>

Validate the parameters.

<a href="#Summary">[LOW‑4]</a><a name="LOW&#x2011;4"> Contracts are not using their OZ Upgradeable counterparts

The non-upgradeable standard version of OpenZeppelin’s library are inherited / used by the contracts. It would be safer to use the upgradeable versions of the library contracts to avoid unexpected behaviour.

<ins>Proof of Concept</ins>
4: import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
5: import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/TimeswapV2Option.sol#L4-L5

4: import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
5: import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/TimeswapV2OptionFactory.sol#L4-L5

4: import {ERC1155} from "@openzeppelin/contracts/token/ERC1155/ERC1155.sol";

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/TimeswapV2LiquidityToken.sol#L4

4: import {ERC1155} from "@openzeppelin/contracts/token/ERC1155/ERC1155.sol";

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/TimeswapV2Token.sol#L4

6: import {ERC1155} from "@openzeppelin/contracts/token/ERC1155/ERC1155.sol";

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/base/ERC1155Enumerable.sol#L6

6: import "@openzeppelin/contracts/token/ERC1155/IERC1155.sol";

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/interfaces/IERC1155Enumerable.sol#L6

4: import {IERC1155} from "@openzeppelin/contracts/token/ERC1155/IERC1155.sol";

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/interfaces/ITimeswapV2Token.sol#L4

<ins>Recommended Mitigation Steps</ins>

Where applicable, use the contracts from @openzeppelin/contracts-upgradeable instead of @openzeppelin/contracts.

<a href="#Summary">[LOW‑5]</a><a name="LOW&#x2011;5"> Remove unused code

This code is not used in the main project contract files, remove it or add event-emit Code that is not in use, suggests that they should not be present and could potentially contain insecure functionalities.

<ins>Proof Of Concept</ins>
function invalidTransaction

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/enums/Transaction.sol#L47

function addFees

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/libraries/FeeCalculation.sol#L47

function _afterTokenTransfer

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/base/ERC1155Enumerable.sol#L81

Non Critical Issues

<a href="#Summary">[NC‑1]</a><a name="NC&#x2011;1"> Add a timelock to critical functions

It is a good practice to give time for users to react and adjust to critical changes. A timelock provides more guarantees and reduces the level of trust required, thus decreasing risk for users. It also indicates that the project is legitimate (less risk of a malicious owner making a sandwich attack on a user). Consider adding a timelock to the following functions:

<ins>Proof Of Concept</ins>
23: function setPendingOwner(address chosenPendingOwner) external override {

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/base/OwnableTwoSteps.sol#L23

<a href="#Summary">[NC‑2]</a><a name="NC&#x2011;2"> Avoid Floating Pragmas: The Version Should Be Locked

Avoid floating pragmas for non-library contracts.

While floating pragmas make sense for libraries to allow them to be included with multiple different versions of applications, it may be a security risk for application implementations.

A known vulnerable compiler version may accidentally be selected or security tools might fall-back to an older compiler version ending up checking a different EVM compilation that is ultimately deployed on the blockchain.

It is recommended to pin to a concrete compiler version.

<ins>Proof Of Concept</ins>
Found usage of floating pragmas ^0.8.8 of Solidity in [TimeswapV2LiquidityToken.sol]

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/TimeswapV2LiquidityToken.sol#L2

Found usage of floating pragmas ^0.8.8 of Solidity in [TimeswapV2Token.sol]

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/TimeswapV2Token.sol#L2

Found usage of floating pragmas ^0.8.0 of Solidity in [ERC1155Enumerable.sol]

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/base/ERC1155Enumerable.sol#L4

Found usage of floating pragmas ^0.8.0 of Solidity in [IERC1155Enumerable.sol]

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/interfaces/IERC1155Enumerable.sol#L4

Found usage of floating pragmas ^0.8.8 of Solidity in [CallbackParam.sol]

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/structs/CallbackParam.sol#L2

Found usage of floating pragmas ^0.8.8 of Solidity in [CallbackParam.sol]

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/structs/CallbackParam.sol#L2

Found usage of floating pragmas ^0.8.8 of Solidity in [CallbackParam.sol]

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/structs/CallbackParam.sol#L2

Found usage of floating pragmas ^0.8.8 of Solidity in [FeesPosition.sol]

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/structs/FeesPosition.sol#L2

Found usage of floating pragmas ^0.8.8 of Solidity in [Param.sol]

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/structs/Param.sol#L2

Found usage of floating pragmas ^0.8.8 of Solidity in [Param.sol]

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/structs/Param.sol#L2

Found usage of floating pragmas ^0.8.8 of Solidity in [Param.sol]

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/structs/Param.sol#L2

Found usage of floating pragmas ^0.8.8 of Solidity in [Position.sol]

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/structs/Position.sol#L2

Found usage of floating pragmas ^0.8.8 of Solidity in [Position.sol]

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/structs/Position.sol#L2

<a href="#Summary">[NC‑3]</a><a name="NC&#x2011;3"> Critical Changes Should Use Two-step Procedure

The critical procedures should be two step process.

See similar findings in previous Code4rena contests for reference: https://code4rena.com/reports/2022-06-illuminate/#2-critical-changes-should-use-two-step-procedure

<ins>Proof Of Concept</ins>
23: function setPendingOwner(address chosenPendingOwner) external override {

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/base/OwnableTwoSteps.sol#L23

<ins>Recommended Mitigation Steps</ins>

Lack of two-step procedure for critical operations leaves them error-prone. Consider adding two step procedure on the critical functions.

<a href="#Summary">[NC‑4]</a><a name="NC&#x2011;4"> Function writing that does not comply with the Solidity Style Guide

Order of Functions; ordering helps readers identify which functions they can call and to find the constructor and fallback definitions easier. But there are contracts in the project that do not comply with this.

https://docs.soliditylang.org/en/v0.8.17/style-guide.html

Functions should be grouped according to their visibility and ordered:

  • constructor
  • receive function (if exists)
  • fallback function (if exists)
  • external
  • public
  • internal
  • private
  • within a grouping, place the view and pure functions last
<ins>Proof Of Concept</ins>

All in-scope contracts

<a href="#Summary">[NC‑5]</a><a name="NC&#x2011;5"> Use delete to Clear Variables

delete a assigns the initial value for the type to a. i.e. for integers it is equivalent to a = 0, but it can also be used on arrays, where it assigns a dynamic array of length zero or a static array of the same length with all elements reset. For structs, it assigns a struct with all members reset. Similarly, it can also be used to set an address to zero address. It has no effect on whole mappings though (as the keys of mappings may be arbitrary and are generally unknown). However, individual keys and what they map to can be deleted: If a is a mapping, then delete a[x] will delete the value stored at x.

The delete key better conveys the intention and is also more idiomatic. Consider replacing assignments of zero with delete statements.

<ins>Proof Of Concept</ins>
166: quotient0 = 0;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-library/src/FullMath.sol#L166

93: liquidityPosition.long0Fees = 0;
101: liquidityPosition.long1Fees = 0;
109: liquidityPosition.shortFees = 0;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/structs/LiquidityPosition.sol#L93

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/structs/LiquidityPosition.sol#L101

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/structs/LiquidityPosition.sol#L109

228: pool.long0ProtocolFees = 0;
236: pool.long1ProtocolFees = 0;
244: pool.shortProtocolFees = 0;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/structs/Pool.sol#L228

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/structs/Pool.sol#L236

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/structs/Pool.sol#L244

633: pool.long0Balance = 0;
646: pool.long1Balance = 0;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/structs/Pool.sol#L633

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/structs/Pool.sol#L646

685: pool.long1Balance = 0;
706: pool.long0Balance = 0;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/structs/Pool.sol#L685

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/structs/Pool.sol#L706

<a href="#Summary">[NC‑6]</a><a name="NC&#x2011;6"> NatSpec return parameters should be included in contracts

It is recommended that Solidity contracts are fully annotated using NatSpec for all public interfaces (everything in the ABI). It is clearly stated in the Solidity official documentation. In complex projects such as Defi, the interpretation of all functions and their arguments and returns is important for code readability and auditability.

https://docs.soliditylang.org/en/v0.8.15/natspec-format.html

<ins>Proof Of Concept</ins>

All in-scope contracts

<ins>Recommended Mitigation Steps</ins>

Include return parameters in NatSpec comments

Recommendation Code Style: (from Uniswap3)

    /// @notice Adds liquidity for the given recipient/tickLower/tickUpper position
    /// @dev The caller of this method receives a callback in the form of IUniswapV3MintCallback#uniswapV3MintCallback
    /// in which they must pay any token0 or token1 owed for the liquidity. The amount of token0/token1 due depends
    /// on tickLower, tickUpper, the amount of liquidity, and the current price.
    /// @param recipient The address for which the liquidity will be created
    /// @param tickLower The lower tick of the position in which to add liquidity
    /// @param tickUpper The upper tick of the position in which to add liquidity
    /// @param amount The amount of liquidity to mint
    /// @param data Any data that should be passed through to the callback
    /// @return amount0 The amount of token0 that was paid to mint the given amount of liquidity. Matches the value in the callback
    /// @return amount1 The amount of token1 that was paid to mint the given amount of liquidity. Matches the value in the callback
    function mint(
        address recipient,
        int24 tickLower,
        int24 tickUpper,
        uint128 amount,
        bytes calldata data
    ) external returns (uint256 amount0, uint256 amount1);

<a href="#Summary">[NC‑7]</a><a name="NC&#x2011;7"> Lines are too long

Usually lines in source code are limited to 80 characters. Today's screens are much larger so it's reasonable to stretch this in some cases. Since the files will most likely reside in GitHub, and GitHub starts using a scroll bar in all cases when the length is over 164 characters, the lines below should be split when they reach that length Reference: https://docs.soliditylang.org/en/v0.8.10/style-guide.html#maximum-line-length

<ins>Proof Of Concept</ins>
62: /// @param amount If isLong0ToLong1 and transaction is GivenToken0AndLong0, this is the amount of token0 withdrawn, and the amount of long0 position burnt.

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/structs/Param.sol#L62

63: /// If isLong1ToLong0 and transaction is GivenToken0AndLong0, this is the amount of token0 to be deposited, and the amount of long0 position minted.

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/structs/Param.sol#L63

64: /// If isLong0ToLong1 and transaction is GivenToken1AndLong1, this is the amount of token1 to be deposited, and the amount of long1 position minted.

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/structs/Param.sol#L64

62: /// @param amount If isLong0ToLong1 and transaction is GivenToken0AndLong0, this is the amount of token0 withdrawn, and the amount of long0 position burnt.

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/structs/Param.sol#L62

63: /// If isLong1ToLong0 and transaction is GivenToken0AndLong0, this is the amount of token0 to be deposited, and the amount of long0 position minted.

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/structs/Param.sol#L63

64: /// If isLong0ToLong1 and transaction is GivenToken1AndLong1, this is the amount of token1 to be deposited, and the amount of long1 position minted.

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/structs/Param.sol#L64

62: /// @param amount If isLong0ToLong1 and transaction is GivenToken0AndLong0, this is the amount of token0 withdrawn, and the amount of long0 position burnt.

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/structs/Param.sol#L62

63: /// If isLong1ToLong0 and transaction is GivenToken0AndLong0, this is the amount of token0 to be deposited, and the amount of long0 position minted.

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/structs/Param.sol#L63

64: /// If isLong0ToLong1 and transaction is GivenToken1AndLong1, this is the amount of token1 to be deposited, and the amount of long1 position minted.

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/structs/Param.sol#L64

87: /// @dev Calculate the amount of liquidity positions and amount of long positions in base denomination or short position whichever is larger or smaller.

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/libraries/ConstantProduct.sol#L87

<a href="#Summary">[NC‑8]</a><a name="NC&#x2011;8"> Implementation contract may not be initialized

OpenZeppelin recommends that the initializer modifier be applied to constructors. Per OZs Post implementation contract should be initialized to avoid potential griefs or exploits. https://forum.openzeppelin.com/t/uupsupgradeable-vulnerability-post-mortem/15680/5

<ins>Proof Of Concept</ins>
19: constructor()

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/NoDelegateCall.sol#L19

65: constructor() NoDelegateCall()

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/TimeswapV2Option.sol#L65

77: constructor() NoDelegateCall()

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/TimeswapV2Pool.sol#L77

37: constructor(address chosenOwner, uint256 chosenTransactionFee, uint256 chosenProtocolFee) OwnableTwoSteps(chosenOwner)

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/TimeswapV2PoolFactory.sol#L37

18: constructor(address chosenOwner)

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/base/OwnableTwoSteps.sol#L18

36: constructor(address chosenOptionFactory, address chosenPoolFactory) ERC1155("Timeswap V2 uint160 address")

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/TimeswapV2LiquidityToken.sol#L36

41: constructor(address chosenOptionFactory) ERC1155("Timeswap V2 address")

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/TimeswapV2Token.sol#L41

<a href="#Summary">[NC‑9]</a><a name="NC&#x2011;9"> NatSpec comments should be increased in contracts

It is recommended that Solidity contracts are fully annotated using NatSpec for all public interfaces (everything in the ABI). It is clearly stated in the Solidity official documentation. In complex projects such as Defi, the interpretation of all functions and their arguments and returns is important for code readability and auditability. https://docs.soliditylang.org/en/v0.8.15/natspec-format.html

<ins>Proof Of Concept</ins>

All in-scope contracts

<ins>Recommended Mitigation Steps</ins>

NatSpec comments should be increased in contracts

<a href="#Summary">[NC‑10]</a><a name="NC&#x2011;10"> Use a more recent version of Solidity

<a href="https://blog.soliditylang.org/2021/04/21/solidity-0.8.4-release-announcement/">0.8.4</a>: bytes.concat() instead of abi.encodePacked(<bytes>,<bytes>)

<a href="https://blog.soliditylang.org/2022/02/16/solidity-0.8.12-release-announcement/">0.8.12</a>: string.concat() instead of abi.encodePacked(<str>,<str>)

<a href="https://blog.soliditylang.org/2022/03/16/solidity-0.8.13-release-announcement/">0.8.13</a>: Ability to use using for with a list of free functions

<a href="https://blog.soliditylang.org/2022/05/18/solidity-0.8.14-release-announcement/">0.8.14</a>:

ABI Encoder: When ABI-encoding values from calldata that contain nested arrays, correctly validate the nested array length against calldatasize() in all cases. Override Checker: Allow changing data location for parameters only when overriding external functions.

<a href="https://blog.soliditylang.org/2022/06/15/solidity-0.8.15-release-announcement/">0.8.15</a>:

Code Generation: Avoid writing dirty bytes to storage when copying bytes arrays. Yul Optimizer: Keep all memory side-effects of inline assembly blocks.

<a href="https://blog.soliditylang.org/2022/08/08/solidity-0.8.16-release-announcement/">0.8.16</a>:

Code Generation: Fix data corruption that affected ABI-encoding of calldata values represented by tuples: structs at any nesting level; argument lists of external functions, events and errors; return value lists of external functions. The 32 leading bytes of the first dynamically-encoded value in the tuple would get zeroed when the last component contained a statically-encoded array.

<a href="https://blog.soliditylang.org/2022/09/08/solidity-0.8.17-release-announcement/">0.8.17</a>:

Yul Optimizer: Prevent the incorrect removal of storage writes before calls to Yul functions that conditionally terminate the external EVM call.

<ins>Proof Of Concept</ins>
pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-library/src/BytesLib.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-library/src/CatchError.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-library/src/Error.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-library/src/FullMath.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-library/src/Math.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-library/src/Ownership.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-library/src/SafeCast.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-library/src/StrikeConversion.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/NoDelegateCall.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/NoDelegateCall.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/TimeswapV2Option.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/TimeswapV2OptionDeployer.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/TimeswapV2OptionFactory.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/enums/Position.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/enums/Position.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/enums/Transaction.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/enums/Transaction.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/interfaces/ITimeswapV2Option.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/interfaces/ITimeswapV2OptionDeployer.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/interfaces/ITimeswapV2OptionFactory.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/interfaces/callbacks/ITimeswapV2OptionBurnCallback.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/interfaces/callbacks/ITimeswapV2OptionCollectCallback.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/interfaces/callbacks/ITimeswapV2OptionMintCallback.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/interfaces/callbacks/ITimeswapV2OptionSwapCallback.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/libraries/OptionFactory.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/libraries/OptionPair.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/libraries/Proportion.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/structs/CallbackParam.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/structs/CallbackParam.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/structs/CallbackParam.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/structs/Option.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/structs/Param.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/structs/Param.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/structs/Param.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/structs/Process.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/structs/StrikeAndMaturity.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/NoDelegateCall.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/NoDelegateCall.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/TimeswapV2Pool.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/TimeswapV2PoolDeployer.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/TimeswapV2PoolFactory.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/base/OwnableTwoSteps.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/enums/Transaction.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/enums/Transaction.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/interfaces/IOwnableTwoSteps.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/interfaces/ITimeswapV2Pool.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/interfaces/ITimeswapV2PoolDeployer.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/interfaces/ITimeswapV2PoolFactory.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/interfaces/callbacks/ITimeswapV2PoolBurnCallback.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/interfaces/callbacks/ITimeswapV2PoolDeleverageCallback.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/interfaces/callbacks/ITimeswapV2PoolLeverageCallback.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/interfaces/callbacks/ITimeswapV2PoolMintCallback.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/interfaces/callbacks/ITimeswapV2PoolRebalanceCallback.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/libraries/ConstantProduct.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/libraries/ConstantSum.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/libraries/Duration.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/libraries/DurationCalculation.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/libraries/DurationWeight.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/libraries/Fee.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/libraries/FeeCalculation.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/libraries/PoolFactory.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/libraries/PoolPair.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/libraries/ReentrancyGuard.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/structs/CallbackParam.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/structs/CallbackParam.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/structs/CallbackParam.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/structs/LiquidityPosition.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/structs/Param.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/structs/Param.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/structs/Param.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/structs/Pool.sol#L2

pragma solidity ^0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/TimeswapV2LiquidityToken.sol#L2

pragma solidity ^0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/TimeswapV2Token.sol#L2

pragma solidity ^0.8.0;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/base/ERC1155Enumerable.sol#L4

pragma solidity ^0.8.0;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/interfaces/IERC1155Enumerable.sol#L4

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/interfaces/ITimeswapV2LiquidityToken.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/interfaces/ITimeswapV2Token.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/interfaces/callbacks/ITimeswapV2LiquidityTokenMintCallback.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/interfaces/callbacks/ITimeswapV2TokenMintCallback.sol#L2

pragma solidity ^0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/structs/CallbackParam.sol#L2

pragma solidity ^0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/structs/CallbackParam.sol#L2

pragma solidity ^0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/structs/CallbackParam.sol#L2

pragma solidity ^0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/structs/FeesPosition.sol#L2

pragma solidity ^0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/structs/Param.sol#L2

pragma solidity ^0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/structs/Param.sol#L2

pragma solidity ^0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/structs/Param.sol#L2

pragma solidity ^0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/structs/Position.sol#L2

pragma solidity ^0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/structs/Position.sol#L2

<ins>Recommended Mitigation Steps</ins>

Consider updating to a more recent solidity version.

#0 - c4-judge

2023-02-02T11:48:23Z

Picodes marked the issue as grade-b

Awards

48.5424 USDC - $48.54

Labels

bug
G (Gas Optimization)
grade-b
G-23

External Links

Summary<a name="Summary">

Gas Optimizations

IssueContextsEstimated Gas Saved
GAS‑1abi.encode() is less efficient than abi.encodepacked()9900
GAS‑2Setting the constructor to payable10130
GAS‑3Using delete statement can save gas11-
GAS‑4Use hardcoded address instead address(this)35-
GAS‑5Multiple Address Mappings Can Be Combined Into A Single Mapping Of An Address To A Struct, Where Appropriate3-
GAS‑6Optimize names to save gas14308
GAS‑7<x> += <y> Costs More Gas Than <x> = <x> + <y> For State Variables73-
GAS‑8Public Functions To External1-
GAS‑9Usage of uints/ints smaller than 32 bytes (256 bits) incurs overhead85-
GAS‑10Use solidity version 0.8.17 to gain some gas boost685984
GAS‑11Using storage instead of memory saves gas51750

Total: 314 contexts over 11 issues

Gas Optimizations

<a href="#Summary">[GAS‑1]</a><a name="GAS&#x2011;1"> abi.encode() is less efficient than abi.encodepacked()

See for more information: https://github.com/ConnorBlockchain/Solidity-Encode-Gas-Comparison

<ins>Proof Of Concept</ins>
35: optionPair = address(new TimeswapV2Option{salt: keccak256(abi.encode(token0, token1))}());

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/TimeswapV2OptionDeployer.sol#L35

28: poolPair = address(new TimeswapV2Pool{salt: keccak256(abi.encode(optionPair))}());

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/TimeswapV2PoolDeployer.sol#L28

46: bytes32 key = keccak256(abi.encode(token0, token1, strike, maturity));

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/TimeswapV2Token.sol#L46

53: bytes32 key = keccak256(abi.encode(token0, token1, strike, maturity));

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/TimeswapV2Token.sol#L53

61: bytes32 key = keccak256(abi.encode(token0, token1, strike, maturity));

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/TimeswapV2Token.sol#L61

35: return keccak256(abi.encode(timeswapV2TokenPosition));

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/structs/Position.sol#L35

40: return keccak256(abi.encode(timeswapV2LiquidityTokenPosition));

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/structs/Position.sol#L40

35: return keccak256(abi.encode(timeswapV2TokenPosition));

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/structs/Position.sol#L35

40: return keccak256(abi.encode(timeswapV2LiquidityTokenPosition));

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/structs/Position.sol#L40

<a href="#Summary">[GAS‑2]</a><a name="GAS&#x2011;2"> Setting the constructor to payable

Saves ~13 gas per instance

<ins>Proof Of Concept</ins>
19: constructor()

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/NoDelegateCall.sol#L19

19: constructor()

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/NoDelegateCall.sol#L19

65: constructor() NoDelegateCall()

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/TimeswapV2Option.sol#L65

19: constructor()

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/NoDelegateCall.sol#L19

19: constructor()

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/NoDelegateCall.sol#L19

77: constructor() NoDelegateCall()

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/TimeswapV2Pool.sol#L77

37: constructor(address chosenOwner, uint256 chosenTransactionFee, uint256 chosenProtocolFee) OwnableTwoSteps(chosenOwner)

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/TimeswapV2PoolFactory.sol#L37

18: constructor(address chosenOwner)

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/base/OwnableTwoSteps.sol#L18

36: constructor(address chosenOptionFactory, address chosenPoolFactory) ERC1155("Timeswap V2 uint160 address")

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/TimeswapV2LiquidityToken.sol#L36

41: constructor(address chosenOptionFactory) ERC1155("Timeswap V2 address")

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/TimeswapV2Token.sol#L41

<a href="#Summary">[GAS‑3]</a><a name="GAS&#x2011;3"> Using delete statement can save gas

<ins>Proof Of Concept</ins>
166: quotient0 = 0;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-library/src/FullMath.sol#L166

93: liquidityPosition.long0Fees = 0;
101: liquidityPosition.long1Fees = 0;
109: liquidityPosition.shortFees = 0;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/structs/LiquidityPosition.sol#L93

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/structs/LiquidityPosition.sol#L101

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/structs/LiquidityPosition.sol#L109

228: pool.long0ProtocolFees = 0;
236: pool.long1ProtocolFees = 0;
244: pool.shortProtocolFees = 0;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/structs/Pool.sol#L228

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/structs/Pool.sol#L236

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/structs/Pool.sol#L244

633: pool.long0Balance = 0;
646: pool.long1Balance = 0;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/structs/Pool.sol#L633

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/structs/Pool.sol#L646

685: pool.long1Balance = 0;
706: pool.long0Balance = 0;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/structs/Pool.sol#L685

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/structs/Pool.sol#L706

<a href="#Summary">[GAS‑4]</a><a name="GAS&#x2011;4"> Use hardcode address instead address(this)

Instead of using address(this), it is more gas-efficient to pre-calculate and use the hardcoded address. Foundry's script.sol and solmate's LibRlp.sol contracts can help achieve this.

References: https://book.getfoundry.sh/reference/forge-std/compute-create-address

https://twitter.com/transmissions11/status/1518507047943245824

<ins>Proof Of Concept</ins>
30: if (address(this) != original) revert CannotBeDelegateCalled();

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/NoDelegateCall.sol#L30

30: if (address(this) != original) revert CannotBeDelegateCalled();

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/NoDelegateCall.sol#L30

128: IERC20(token0).balanceOf(address(this)) + token0AndLong0Amount,
129: IERC20(token1).balanceOf(address(this)) + token1AndLong1Amount
145: if (token0AndLong0Amount != 0) Error.checkEnough(IERC20(token0).balanceOf(address(this)), currentProcess.balance0Target);
148: if (token1AndLong1Amount != 0) Error.checkEnough(IERC20(token1).balanceOf(address(this)), currentProcess.balance1Target);

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/TimeswapV2Option.sol#L128

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/TimeswapV2Option.sol#L129

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/TimeswapV2Option.sol#L145

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/TimeswapV2Option.sol#L148

215: param.isLong0ToLong1 ? IERC20(token0).balanceOf(address(this)) - token0AndLong0Amount : IERC20(token0).balanceOf(address(this)) + token0AndLong0Amount,
216: param.isLong0ToLong1 ? IERC20(token1).balanceOf(address(this)) + token1AndLong1Amount : IERC20(token1).balanceOf(address(this)) - token1AndLong1Amount
235: Error.checkEnough(IERC20(param.isLong0ToLong1 ? token1 : token0).balanceOf(address(this)), param.isLong0ToLong1 ? currentProcess.balance1Target : currentProcess.balance0Target);

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/TimeswapV2Option.sol#L215

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/TimeswapV2Option.sol#L216

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/TimeswapV2Option.sol#L235

51: optionPair = deploy(address(this), token0, token1);

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/TimeswapV2OptionFactory.sol#L51

30: if (address(this) != original) revert CannotBeDelegateCalled();

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/NoDelegateCall.sol#L30

30: if (address(this) != original) revert CannotBeDelegateCalled();

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/NoDelegateCall.sol#L30

267: if (long0Amount != 0) long0BalanceTarget = ITimeswapV2Option(optionPair).positionOf(param.strike, param.maturity, address(this), TimeswapV2OptionPosition.Long0) + long0Amount;
271: if (long1Amount != 0) long1BalanceTarget = ITimeswapV2Option(optionPair).positionOf(param.strike, param.maturity, address(this), TimeswapV2OptionPosition.Long1) + long1Amount;
274: uint256 shortBalanceTarget = ITimeswapV2Option(optionPair).positionOf(param.strike, param.maturity, address(this), TimeswapV2OptionPosition.Short) + shortAmount;
293: if (long0Amount != 0) Error.checkEnough(ITimeswapV2Option(optionPair).positionOf(param.strike, param.maturity, address(this), TimeswapV2OptionPosition.Long0), long0BalanceTarget);
295: if (long1Amount != 0) Error.checkEnough(ITimeswapV2Option(optionPair).positionOf(param.strike, param.maturity, address(this), TimeswapV2OptionPosition.Long1), long1BalanceTarget);
297: Error.checkEnough(ITimeswapV2Option(optionPair).positionOf(param.strike, param.maturity, address(this), TimeswapV2OptionPosition.Short), shortBalanceTarget);

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/TimeswapV2Pool.sol#L267

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/TimeswapV2Pool.sol#L271

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/TimeswapV2Pool.sol#L274

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/TimeswapV2Pool.sol#L293

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/TimeswapV2Pool.sol#L295

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/TimeswapV2Pool.sol#L297

393: if (long0Amount != 0) long0BalanceTarget = ITimeswapV2Option(optionPair).positionOf(param.strike, param.maturity, address(this), TimeswapV2OptionPosition.Long0) + long0Amount;
397: if (long1Amount != 0) long1BalanceTarget = ITimeswapV2Option(optionPair).positionOf(param.strike, param.maturity, address(this), TimeswapV2OptionPosition.Long1) + long1Amount;
411: if (long0Amount != 0) Error.checkEnough(ITimeswapV2Option(optionPair).positionOf(param.strike, param.maturity, address(this), TimeswapV2OptionPosition.Long0), long0BalanceTarget);
413: if (long1Amount != 0) Error.checkEnough(ITimeswapV2Option(optionPair).positionOf(param.strike, param.maturity, address(this), TimeswapV2OptionPosition.Long1), long1BalanceTarget);

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/TimeswapV2Pool.sol#L393

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/TimeswapV2Pool.sol#L397

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/TimeswapV2Pool.sol#L411

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/TimeswapV2Pool.sol#L413

444: uint256 balanceTarget = ITimeswapV2Option(optionPair).positionOf(param.strike, param.maturity, address(this), TimeswapV2OptionPosition.Short) + shortAmount;
461: Error.checkEnough(ITimeswapV2Option(optionPair).positionOf(param.strike, param.maturity, address(this), TimeswapV2OptionPosition.Short), balanceTarget);

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/TimeswapV2Pool.sol#L444

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/TimeswapV2Pool.sol#L461

482: address(this),
511: ITimeswapV2Option(optionPair).positionOf(param.strike, param.maturity, address(this), param.isLong0ToLong1 ? TimeswapV2OptionPosition.Long0 : TimeswapV2OptionPosition.Long1),

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/TimeswapV2Pool.sol#L482

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/TimeswapV2Pool.sol#L511

65: pair = deploy(address(this), optionPair, transactionFee, protocolFee);

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/TimeswapV2PoolFactory.sol#L65

125: uint160 liquidityBalanceTarget = ITimeswapV2Pool(poolPair).liquidityOf(param.strike, param.maturity, address(this)) + param.liquidityAmount;
143: Error.checkEnough(ITimeswapV2Pool(poolPair).liquidityOf(param.strike, param.maturity, address(this)), liquidityBalanceTarget);

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/TimeswapV2LiquidityToken.sol#L125

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/TimeswapV2LiquidityToken.sol#L143

87: long0BalanceTarget = ITimeswapV2Option(optionPair).positionOf(param.strike, param.maturity, address(this), TimeswapV2OptionPosition.Long0) + param.long0Amount;
117: long1BalanceTarget = ITimeswapV2Option(optionPair).positionOf(param.strike, param.maturity, address(this), TimeswapV2OptionPosition.Long1) + param.long1Amount;
146: shortBalanceTarget = ITimeswapV2Option(optionPair).positionOf(param.strike, param.maturity, address(this), TimeswapV2OptionPosition.Short) + param.shortAmount;
186: if (param.long0Amount != 0) Error.checkEnough(ITimeswapV2Option(optionPair).positionOf(param.strike, param.maturity, address(this), TimeswapV2OptionPosition.Long0), long0BalanceTarget);
189: if (param.long1Amount != 0) Error.checkEnough(ITimeswapV2Option(optionPair).positionOf(param.strike, param.maturity, address(this), TimeswapV2OptionPosition.Long1), long1BalanceTarget);
192: if (param.shortAmount != 0) Error.checkEnough(ITimeswapV2Option(optionPair).positionOf(param.strike, param.maturity, address(this), TimeswapV2OptionPosition.Short), shortBalanceTarget);

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/TimeswapV2Token.sol#L87

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/TimeswapV2Token.sol#L117

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/TimeswapV2Token.sol#L146

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/TimeswapV2Token.sol#L186

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/TimeswapV2Token.sol#L189

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/TimeswapV2Token.sol#L192

<ins>Recommended Mitigation Steps</ins>

Use hardcoded address

<a href="#Summary">[GAS‑5]</a><a name="GAS&#x2011;5"> Multiple Address Mappings Can Be Combined Into A Single Mapping Of An Address To A Struct, Where Appropriate

Saves a storage slot for the mapping. Depending on the circumstances and sizes of types, can avoid a Gsset (20000 gas) per mapping combined. Reads and subsequent writes can also be cheaper when a function requires both values and they both fit in the same storage slot.

<ins>Proof Of Concept</ins>
23: mapping(address => uint256) long0;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/structs/Option.sol#L23

24: mapping(address => uint256) long1;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/structs/Option.sol#L24

25: mapping(address => uint256) short;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/structs/Option.sol#L25

For the above, can create a struct for example:

struct structShortLong{
	uint256 long0;
	uint256 long1;
	uint256 short;
}





### <a href="#Summary">[GAS&#x2011;6]</a><a name="GAS&#x2011;6"> Optimize names to save gas

Contracts most called functions could simply save gas by function ordering via Method ID. Calling a function at runtime will be cheaper if the function is positioned earlier in the order (has a relatively lower Method ID) because 22 gas are added to the cost of a function for every position that came before it. The caller can save on gas if you prioritize most called functions. 

See more <a href="https://medium.com/joyso/solidity-how-does-function-name-affect-gas-consumption-in-smart-contract-47d270d8ac92">here</a>

#### <ins>Proof Of Concept</ins>

All in-scope contracts

#### <ins>Recommended Mitigation Steps</ins>
Find a lower method ID name for the most called functions for example Call() vs. Call1() is cheaper by 22 gas
For example, the function IDs in the Gauge.sol contract will be the most used; A lower method ID may be given.



### <a href="#Summary">[GAS&#x2011;7]</a><a name="GAS&#x2011;7"> `<x> += <y>` Costs More Gas Than `<x> = <x> + <y>` For State Variables

#### <ins>Proof Of Concept</ins>


```solidity
163: productA1 += (quotient1 * divisor);

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-library/src/FullMath.sol#L163

190: option.long0[msg.sender] -= token0AndLong0Amount;
191: option.long1[msg.sender] -= token1AndLong1Amount;
192: option.short[msg.sender] -= shortAmount;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/TimeswapV2Option.sol#L190-L192

237: if (param.isLong0ToLong1) option.long0[msg.sender] -= token0AndLong0Amount;
238: else option.long1[msg.sender] -= token1AndLong1Amount;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/TimeswapV2Option.sol#L237-L238

277: option.short[msg.sender] -= shortAmount;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/TimeswapV2Option.sol#L277

62: option.long0[msg.sender] -= amount;
63: option.long0[to] += amount;
65: option.long1[to] += amount;
66: option.long1[msg.sender] -= amount;
68: option.short[msg.sender] -= amount;
69: option.short[to] += amount;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/structs/Option.sol#L62

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/structs/Option.sol#L63

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/structs/Option.sol#L65

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/structs/Option.sol#L66

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/structs/Option.sol#L68

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/structs/Option.sol#L69

103: option.totalLong0 += token0AndLong0Amount;
104: option.long0[long0To] += token0AndLong0Amount;
108: option.totalLong1 += token1AndLong1Amount;
109: option.long1[long1To] += token1AndLong1Amount;
112: option.short[shortTo] += shortAmount;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/structs/Option.sol#L103

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/structs/Option.sol#L104

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/structs/Option.sol#L108

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/structs/Option.sol#L109

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/structs/Option.sol#L112

141: option.totalLong0 -= token0AndLong0Amount;
142: option.totalLong1 -= token1AndLong1Amount;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/structs/Option.sol#L141-L142

173: option.totalLong0 -= token0AndLong0Amount;
174: option.totalLong1 += token1AndLong1Amount;
175: option.long1[longTo] += token1AndLong1Amount;
177: option.totalLong1 -= token1AndLong1Amount;
178: option.totalLong0 += token0AndLong0Amount;
179: option.long0[longTo] += token0AndLong0Amount;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/structs/Option.sol#L173

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/structs/Option.sol#L174

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/structs/Option.sol#L175

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/structs/Option.sol#L177

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/structs/Option.sol#L178

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/structs/Option.sol#L179

208: option.totalLong0 -= token0Amount;
209: option.totalLong1 -= token1Amount;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/structs/Option.sol#L208-L209

149: if (isAdd) longAmount -= fees;
150: else shortAmount -= fees;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/libraries/ConstantProduct.sol#L149-L150

180: shortAmount -= fees;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/libraries/ConstantProduct.sol#L180

212: longAmount -= fees;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/libraries/ConstantProduct.sol#L212

244: amount -= fees;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/libraries/ConstantProduct.sol#L244

295: denominator2 += longAmount;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/libraries/ConstantProduct.sol#L295

55: liquidityPosition.long0Fees += FeeCalculation.getFees(liquidity, liquidityPosition.long0FeeGrowth, long0FeeGrowth);
56: liquidityPosition.long1Fees += FeeCalculation.getFees(liquidity, liquidityPosition.long1FeeGrowth, long1FeeGrowth);
57: liquidityPosition.shortFees += FeeCalculation.getFees(liquidity, liquidityPosition.shortFeeGrowth, shortFeeGrowth);

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/structs/LiquidityPosition.sol#L55-L57

66: liquidityPosition.liquidity += liquidityAmount;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/structs/LiquidityPosition.sol#L66

70: liquidityPosition.long0Fees += long0Fees;
71: liquidityPosition.long1Fees += long1Fees;
72: liquidityPosition.shortFees += shortFees;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/structs/LiquidityPosition.sol#L70-L72

76: liquidityPosition.liquidity -= liquidityAmount;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/structs/LiquidityPosition.sol#L76

80: liquidityPosition.long0Fees -= long0Fees;
81: liquidityPosition.long1Fees -= long1Fees;
82: liquidityPosition.shortFees -= shortFees;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/structs/LiquidityPosition.sol#L80-L82

361: if (long0Amount != 0) pool.long0Balance += long0Amount;
362: if (long1Amount != 0) pool.long1Balance += long1Amount;
365: pool.liquidity += liquidityAmount;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/structs/Pool.sol#L361

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/structs/Pool.sol#L362

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/structs/Pool.sol#L365

452: if (long0Amount != 0) pool.long0Balance -= long0Amount;
453: if (long1Amount != 0) pool.long1Balance -= long1Amount;
455: pool.liquidity -= liquidityAmount;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/structs/Pool.sol#L452

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/structs/Pool.sol#L453

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/structs/Pool.sol#L455

537: if (long0Amount != 0) pool.long0Balance += long0Amount;
538: if (long1Amount != 0) pool.long1Balance += long1Amount;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/structs/Pool.sol#L537-L538

636: pool.long0Balance -= (long0Amount + long0Fees);
650: pool.long1Balance -= (long1Amount + long1Fees);

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/structs/Pool.sol#L636

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/structs/Pool.sol#L650

677: pool.long1Balance -= (long1Amount + longFees);
677: pool.long1Balance -= (long1Amount + longFees);
695: pool.long0Balance += long0Amount;
710: pool.long0Balance -= (long0Amount + longFees);
710: pool.long0Balance -= (long0Amount + longFees);
722: pool.long1Balance += long1Amount;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/structs/Pool.sol#L677

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/structs/Pool.sol#L677

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/structs/Pool.sol#L695

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/structs/Pool.sol#L710

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/structs/Pool.sol#L710

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/structs/Pool.sol#L722

61: _idTotalSupply[id] += amount;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/base/ERC1155Enumerable.sol#L61

95: _idTotalSupply[id] -= amount;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/base/ERC1155Enumerable.sol#L95

117: _currentIndex[to] += 1;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/base/ERC1155Enumerable.sol#L117

31: feesPosition.long0Fees += FeeCalculation.getFees(liquidity, feesPosition.long0FeeGrowth, long0FeeGrowth);
32: feesPosition.long1Fees += FeeCalculation.getFees(liquidity, feesPosition.long1FeeGrowth, long1FeeGrowth);
33: feesPosition.shortFees += FeeCalculation.getFees(liquidity, feesPosition.shortFeeGrowth, shortFeeGrowth);

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/structs/FeesPosition.sol#L31-L33

53: feesPosition.long0Fees += long0Fees;
54: feesPosition.long1Fees += long1Fees;
55: feesPosition.shortFees += shortFees;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/structs/FeesPosition.sol#L53-L55

59: feesPosition.long0Fees -= long0Fees;
60: feesPosition.long1Fees -= long1Fees;
61: feesPosition.shortFees -= shortFees;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/structs/FeesPosition.sol#L59-L61

<a href="#Summary">[GAS‑8]</a><a name="GAS&#x2011;8"> Public Functions To External

The following functions could be set external to save gas and improve code quality. External call cost is less expensive than of public functions.

<ins>Proof Of Concept</ins>
function positionOf(address owner, TimeswapV2TokenPosition calldata timeswapV2TokenPosition) public view returns (uint256 amount) {

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/TimeswapV2Token.sol#L66

<a href="#Summary">[GAS‑9]</a><a name="GAS&#x2011;9"> Usage of uints/ints smaller than 32 bytes (256 bits) incurs overhead

When using elements that are smaller than 32 bytes, your contract's gas usage may be higher. This is because the EVM operates on 32 bytes at a time. Therefore, if the element is smaller than that, the EVM must use more operations in order to reduce the size of the element from 32 bytes to the desired size.

https://docs.soliditylang.org/en/v0.8.11/internals/layout_in_storage.html Each operation involving a uint8 costs an extra 22-28 gas (depending on whether the other operand is also a variable of type uint8) as compared to ones involving uint256, due to the compiler having to clear the higher bits of the memory word before operating on the uint8, as well as the associated stack operations of doing so. Use a larger size then downcast where needed

<ins>Proof Of Concept</ins>
205: uint160 deltaRate;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/libraries/ConstantProduct.sol#L205

12: uint96 internal constant NOT_INTERACTED = 0;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/libraries/ReentrancyGuard.sol#L12

15: uint96 internal constant NOT_ENTERED = 1;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/libraries/ReentrancyGuard.sol#L15

18: uint96 internal constant ENTERED = 2;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/libraries/ReentrancyGuard.sol#L18

72: uint160 liquidityAmount;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/structs/CallbackParam.sol#L72

72: uint160 liquidityAmount;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/structs/CallbackParam.sol#L72

72: uint160 liquidityAmount;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/structs/CallbackParam.sol#L72

16: uint160 liquidity;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/structs/LiquidityPosition.sol#L16

52: uint160 liquidity = liquidityPosition.liquidity;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/structs/LiquidityPosition.sol#L52

42: uint160 liquidity;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/structs/Pool.sol#L42

43: uint96 lastTimestamp;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/structs/Pool.sol#L43

44: uint160 sqrtInterestRate;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/structs/Pool.sol#L44

125: uint160 liquidityBalanceTarget = ITimeswapV2Pool(poolPair).liquidityOf(param.strike, param.maturity, address(this)) + param.liquidityAmount;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/TimeswapV2LiquidityToken.sol#L125

70: uint160 liquidityAmount;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/structs/CallbackParam.sol#L70

70: uint160 liquidityAmount;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/structs/CallbackParam.sol#L70

70: uint160 liquidityAmount;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/structs/CallbackParam.sol#L70

90: uint160 liquidityAmount;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/structs/Param.sol#L90

90: uint160 liquidityAmount;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/structs/Param.sol#L90

90: uint160 liquidityAmount;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/structs/Param.sol#L90

<a href="#Summary">[GAS‑10]</a><a name="GAS&#x2011;10"> Use solidity version 0.8.17 to gain some gas boost

Upgrade to the latest solidity version 0.8.17 to get additional gas savings.

<ins>Proof Of Concept</ins>
pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-library/src/BytesLib.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-library/src/CatchError.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-library/src/Error.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-library/src/FullMath.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-library/src/Math.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-library/src/Ownership.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-library/src/SafeCast.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-library/src/StrikeConversion.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/NoDelegateCall.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/TimeswapV2Option.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/TimeswapV2OptionDeployer.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/TimeswapV2OptionFactory.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/enums/Position.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/enums/Transaction.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/interfaces/ITimeswapV2Option.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/interfaces/ITimeswapV2OptionDeployer.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/interfaces/ITimeswapV2OptionFactory.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/interfaces/callbacks/ITimeswapV2OptionBurnCallback.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/interfaces/callbacks/ITimeswapV2OptionCollectCallback.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/interfaces/callbacks/ITimeswapV2OptionSwapCallback.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/libraries/OptionFactory.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/libraries/OptionPair.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/libraries/Proportion.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/structs/CallbackParam.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/structs/Option.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/structs/Param.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/structs/Process.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-option/src/structs/StrikeAndMaturity.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/NoDelegateCall.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/TimeswapV2Pool.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/TimeswapV2PoolDeployer.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/TimeswapV2PoolFactory.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/base/OwnableTwoSteps.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/enums/Transaction.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/interfaces/IOwnableTwoSteps.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/interfaces/ITimeswapV2Pool.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/interfaces/ITimeswapV2PoolDeployer.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/interfaces/ITimeswapV2PoolFactory.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/interfaces/callbacks/ITimeswapV2PoolBurnCallback.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/interfaces/callbacks/ITimeswapV2PoolDeleverageCallback.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/interfaces/callbacks/ITimeswapV2PoolMintCallback.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/interfaces/callbacks/ITimeswapV2PoolRebalanceCallback.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/libraries/ConstantProduct.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/libraries/ConstantSum.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/libraries/Duration.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/libraries/DurationCalculation.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/libraries/DurationWeight.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/libraries/Fee.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/libraries/FeeCalculation.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/libraries/PoolFactory.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/libraries/PoolPair.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/libraries/ReentrancyGuard.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/structs/CallbackParam.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/structs/LiquidityPosition.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/structs/Param.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-pool/src/structs/Pool.sol#L2

pragma solidity ^0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/TimeswapV2LiquidityToken.sol#L2

pragma solidity ^0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/TimeswapV2Token.sol#L2

pragma solidity ^0.8.0;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/base/ERC1155Enumerable.sol#L4

pragma solidity ^0.8.0;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/interfaces/IERC1155Enumerable.sol#L4

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/interfaces/ITimeswapV2LiquidityToken.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/interfaces/ITimeswapV2Token.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/interfaces/callbacks/ITimeswapV2LiquidityTokenMintCallback.sol#L2

pragma solidity =0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/interfaces/callbacks/ITimeswapV2TokenMintCallback.sol#L2

pragma solidity ^0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/structs/CallbackParam.sol#L2

pragma solidity ^0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/structs/FeesPosition.sol#L2

pragma solidity ^0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/structs/Param.sol#L2

pragma solidity ^0.8.8;

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/structs/Position.sol#L2

<a href="#Summary">[GAS‑11]</a><a name="GAS&#x2011;11"> Using storage instead of memory saves gas

When fetching data from a storage location, assigning the data to a memory variable causes all fields of the struct/array to be read from storage, which incurs a Gcoldsload (2100 gas) for each field of the struct/array. If the fields are read from the new memory variable, they incur an additional MLOAD rather than a cheap stack read. Instead of declearing the variable with the memory keyword, declaring the variable with the storage keyword and caching any fields that need to be re-read in stack variables, will be much cheaper, only incuring the Gcoldsload for the fields actually read. The only time it makes sense to read the whole struct/array into a memory variable, is if the full struct/array is being returned by the function, is being passed to a function that requires memory, or if the array/struct is being read from another memory array/struct

<ins>Proof Of Concept</ins>
238: TimeswapV2LiquidityTokenPosition memory timeswapV2LiquidityTokenPosition = _timeswapV2LiquidityTokenPositions[id];
264: TimeswapV2LiquidityTokenPosition memory timeswapV2LiquidityTokenPosition = _timeswapV2LiquidityTokenPositions[id];

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/TimeswapV2LiquidityToken.sol#L238

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/TimeswapV2LiquidityToken.sol#L264

238: TimeswapV2LiquidityTokenPosition memory timeswapV2LiquidityTokenPosition = _timeswapV2LiquidityTokenPositions[id];
264: TimeswapV2LiquidityTokenPosition memory timeswapV2LiquidityTokenPosition = _timeswapV2LiquidityTokenPositions[id];
275: FeesPosition memory feesPosition = _feesPositions[id][owner];

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/TimeswapV2LiquidityToken.sol#L238

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/TimeswapV2LiquidityToken.sol#L264

https://github.com/code-423n4/2023-01-timeswap/tree/main/packages/v2-token/src/TimeswapV2LiquidityToken.sol#L275

#0 - c4-judge

2023-02-02T12:41:17Z

Picodes marked the issue as grade-c

#1 - c4-judge

2023-02-02T12:41:30Z

Picodes marked the issue as grade-b

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