Platform: Code4rena
Start Date: 06/01/2023
Pot Size: $210,500 USDC
Total HM: 27
Participants: 73
Period: 14 days
Judge: 0xean
Total Solo HM: 18
Id: 203
League: ETH
Rank: 67/73
Findings: 1
Award: $72.44
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: IllIllI
Also found by: 0xA5DF, 0xSmartContract, 0xhacksmithh, AkshaySrivastav, Awesome, Aymen0909, Bauer, Bnke0x0, Breeje, Budaghyan, Cyfrin, Madalad, NoamYakov, RHaO-sec, Rageur, RaymondFam, ReyAdmirado, Rolezn, SAAJ, SaharDevep, Sathish9098, __141345__, amshirif, arialblack14, c3phas, carlitox477, chaduke, delfin454000, descharre, nadin, oyc_109, pavankv, saneryee, shark
72.4433 USDC - $72.44
If data can fit into 32 bytes, then you should use bytes32 datatype rather than bytes or strings as it is cheaper in solidity.
Deployer.sol Deployer.sol#L103-L105 Deployer.sol#L206-L207
RToken.sol#L149-L151 RToken.sol#L44
StRSR.sol#L42-L43 StRSR.sol#L162-L163
It is generally cheaper to load variables directly from calldata, rather than copying them to memory. Only use memory if the variable needs to be modified.
Deployer.sol#L103-L104 Deployer.sol#L107
Distributor.sol#L61 Distributor.sol#L161
function setPrimeBasket(IERC20[] calldata erc20s, uint192[] calldata targetAmts) external governance { require(erc20s.length > 0, "cannot empty basket"); // audit gas: (SLOAD 1) require(erc20s.length == targetAmts.length, "must be same length"); // // audit gas: (SLOAD 2) requireValidCollArray(erc20s);
........
function requireValidCollArray(IERC20[] calldata erc20s) internal view { IERC20 zero = IERC20(address(0));
for (uint256 i = 0; i < erc20s.length; i++) { require(erc20s[i] != rsr, "RSR is not valid collateral"); // audit gas: (SLOAD 1) require(erc20s[i] != IERC20(address(rToken)), "RToken is not valid collateral"); // audit gas: (SLOAD 2) require(erc20s[i] != IERC20(address(stRSR)), "stRSR is not valid collateral"); // audit gas: (SLOAD 3) require(erc20s[i] != zero, "address zero is not valid collateral"); // audit gas: (SLOAD 4) }
........
function _setDistribution(address dest, RevenueShare memory share) internal { require(dest != address(0), "dest cannot be zero"); if (dest == FURNACE) require(share.rsrDist == 0, "Furnace must get 0% of RSR"); if (dest == ST_RSR) require(share.rTokenDist == 0, "StRSR must get 0% of RToken"); // audit gas: (SLOAD 1) require(share.rsrDist <= 10000, "RSR distribution too high"); // audit gas: (SLOAD 2) require(share.rTokenDist <= 10000, "RToken distribution too high"); // audit gas: (SLOAD 3)
function withdraw(address account, uint256 endId) external notPausedOrFrozen { // == Refresh == assetRegistry.refresh();
// == Checks + Effects == require(basketHandler.fullyCollateralized(), "RToken uncollateralized"); // audit gas: (SLOAD 1) require(basketHandler.status() == CollateralStatus.SOUND, "basket defaulted"); // audit gas: (SLOAD 2)
function seizeRSR(uint256 rsrAmount) external notPausedOrFrozen { require(_msgSender() == address(backingManager), "not backing manager"); require(rsrAmount > 0, "Amount cannot be zero"); // audit gas: (SLOAD 1) uint192 initRate = exchangeRate();
uint256 rsrBalance = rsr.balanceOf(address(this)); require(rsrAmount <= rsrBalance, "Cannot seize more RSR than we hold"); // audit gas: (SLOAD 2) uint256 seizedRSR; uint256 rewards = rsrRewards(); // Remove RSR from stakeRSR uint256 stakeRSRToTake = (stakeRSR * rsrAmount + (rsrBalance - 1)) / rsrBalance; stakeRSR -= stakeRSRToTake; seizedRSR = stakeRSRToTake;
......................
BasketHandler.sol#L345-L346 BasketHandler.sol#L636
StRSR.sol#L698-L699 StRSR.sol#L299 StRSR.sol#L396 StRSR.sol#L402-L403 StRSR.sol#L412 StRSR.sol#L417 StRSR.sol#L513 RToken.sol RToken.sol
#0 - c4-judge
2023-01-24T23:04:36Z
0xean marked the issue as grade-b