code-423n4 / 2021-12-perennial-findings

0 stars 0 forks source link

Adding unchecked directive can save gas #57

Open code423n4 opened 2 years ago

code423n4 commented 2 years ago

Handle

WatchPug

Vulnerability details

For the arithmetic operations that will never over/underflow, using the unchecked directive (Solidity v0.8 has default overflow/underflow checks) can save some gas from the unnecessary internal over/underflow checks.

For example:

https://github.com/code-423n4/2021-12-perennial/blob/fd7c38823833a51ae0c6ae3856a3d93a7309c0e4/protocol/contracts/oracle/ChainlinkOracle.sol#L50-L60

    function sync() public {
        (, int256 feedPrice, , uint256 timestamp, ) = feed.latestRoundData();
        Fixed18 price = Fixed18Lib.ratio(feedPrice, SafeCast.toInt256(_decimalOffset));

        if (priceAtVersion.length == 0 || timestamp > timestampAtVersion[currentVersion()] + minDelay) {
            priceAtVersion.push(price);
            timestampAtVersion.push(timestamp);

            emit Version(currentVersion(), timestamp, price);
        }
    }

timestampAtVersion[currentVersion()] + minDelay won't overflow.

https://github.com/code-423n4/2021-12-perennial/blob/fd7c38823833a51ae0c6ae3856a3d93a7309c0e4/protocol/contracts/product/types/position/PrePosition.sol#L169-L176

    function oracleVersionToSettle(PrePosition storage self, IOracle oracle) internal view returns (uint256) {
        uint256 current = oracle.currentVersion();
        uint256 next = self.oracleVersion + 1;

        if (next == 1) return current;      // no pre position
        if (next > current) return current; // pre in future
        return next;                        // settle pre
    }

self.oracleVersion + 1 won't overflow.

GalloDaSballo commented 2 years ago

Finding is valid, each unchecked should save around 30 - 40 gas