code-423n4 / 2022-04-xtribe-findings

2 stars 0 forks source link

Gas Optimizations #95

Open code423n4 opened 2 years ago

code423n4 commented 2 years ago

decrementWeightUntilFree can be optimized by using _userGauges[user].at(i) and _userGauges[user].length() directly instead of storing _userGauges[user].values() as gaugeList and calling gaugeList.length and gaugeList[i].

Implementation:

function _decrementWeightUntilFree(address user, uint256 weight) internal {
    uint256 userFreeWeight = balanceOf[user] - getUserWeight[user];

    // early return if already free
    if (userFreeWeight >= weight) return;

    uint32 currentCycle = _getGaugeCycleEnd();

    // cache totals for batch updates
    uint112 userFreed;
    uint112 totalFreed;

    // Loop through all user gauges, live and deprecated
    //address[] memory gaugeList = _userGauges[user].values();

    // Free gauges until through entire list or under weight
    uint256 size = _userGauges[user].length();
    //uint256 size = gaugeList.length;
    for (uint256 i = 0; i < size && (userFreeWeight + totalFreed) < weight; ) {
        //address gauge = gaugeList[i];
        address gauge = _userGauges[user].at(i);
        uint112 userGaugeWeight = getUserGaugeWeight[user][gauge];
        if (userGaugeWeight != 0) {
            // If the gauge is live (not deprecated), include its weight in the total to remove
            if (!_deprecatedGauges.contains(gauge)) {
                totalFreed += userGaugeWeight;
            }
            userFreed += userGaugeWeight;
            _decrementGaugeWeight(user, gauge, userGaugeWeight, currentCycle);

            unchecked {
                i++;
            }
        }
    }

    getUserWeight[user] -= userFreed;
    _writeGaugeWeight(_totalWeight, _subtract, totalFreed, currentCycle);
}

Gas testing function:

function testGasGauge() public {
    token.mint(address(this), 100e18);
    token.setMaxGauges(5);

    uint160 i = 1; // address 0 causes reverts
    while (i < 3) {
        token.addGauge(address(i));
        token.incrementGauge(address(i), 50e18);
        i++;
    }

    startMeasuringGas("transfer call");
    token.transfer(address(1000000), 1);
    stopMeasuringGas();
}
Joeysantoro commented 2 years ago

good optimization