code-423n4 / 2022-01-trader-joe-findings

2 stars 0 forks source link

Cache and read storage variables from the stack can save gas #234

Open code423n4 opened 2 years ago

code423n4 commented 2 years ago

Handle

WatchPug

Vulnerability details

For the storage variables that will be accessed multiple times, cache and read from the stack can save ~100 gas from each extra read (SLOAD after Berlin).

For example:

https://github.com/code-423n4/2022-01-trader-joe/blob/a1579f6453bc4bf9fb0db9c627beaa41135438ed/contracts/LaunchEvent.sol#L327-L333

if (newAllocation > user.allocation) {
    // Burn tokens and update allocation.
    rJoeNeeded = getRJoeAmount(newAllocation - user.allocation);
    // ...
}

user.allocation can be cached.

Recommendation

Change to:

uint256 oldAllocation = user.allocation;
if (newAllocation > oldAllocation) {
    // Burn tokens and update allocation.
    rJoeNeeded = getRJoeAmount(newAllocation - oldAllocation);
    // ...
}

https://github.com/code-423n4/2022-01-trader-joe/blob/a1579f6453bc4bf9fb0db9c627beaa41135438ed/contracts/LaunchEvent.sol#L455-L459

if (tokenReserve > 0) {
    uint256 amount = tokenReserve;
    tokenReserve = 0;
    token.transfer(msg.sender, amount);
}

tokenReserve can be cached.

Recommendation

Change to:

uint256 amount = tokenReserve;
if (amount > 0) {
    tokenReserve = 0;
    token.transfer(msg.sender, amount);
}

https://github.com/code-423n4/2022-01-trader-joe/blob/a1579f6453bc4bf9fb0db9c627beaa41135438ed/contracts/LaunchEvent.sol#L290-L302

function currentPhase() public view returns (Phase) {
    if (block.timestamp < auctionStart || auctionStart == 0) {
        return Phase.NotStarted;
    } else if (block.timestamp < auctionStart + PHASE_ONE_DURATION) {
        return Phase.PhaseOne;
    } else if (
        block.timestamp <
        auctionStart + PHASE_ONE_DURATION + PHASE_TWO_DURATION
    ) {
        return Phase.PhaseTwo;
    }
    return Phase.PhaseThree;
}

auctionStart can be cached.

Recommendation

Change to:

https://github.com/code-423n4/2022-01-trader-joe/blob/a1579f6453bc4bf9fb0db9c627beaa41135438ed/contracts/LaunchEvent.sol#L290-L303

function currentPhase() public view returns (Phase) {
    uint256 auctionStart_ = auctionStart;
    if (block.timestamp < auctionStart_ || auctionStart_ == 0) {
        return Phase.NotStarted;
    } else if (block.timestamp < auctionStart_ + PHASE_ONE_DURATION) {
        return Phase.PhaseOne;
    } else if (
        block.timestamp <
        auctionStart_ + PHASE_ONE_DURATION + PHASE_TWO_DURATION
    ) {
        return Phase.PhaseTwo;
    }
    return Phase.PhaseThree;
}