Platform: Code4rena
Start Date: 12/07/2022
Pot Size: $35,000 USDC
Total HM: 13
Participants: 78
Period: 3 days
Judge: 0xean
Total Solo HM: 6
Id: 135
League: ETH
Rank: 31/78
Findings: 1
Award: $102.64
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: joestakey
Also found by: 0x040, 0x1f8b, 0xDjango, 0xNazgul, 0xsam, Avci, Aymen0909, Bnke0x0, CRYP70, ElKu, Fitraldys, Funen, JC, Kaiziron, MadWookie, Meera, ReyAdmirado, Sm4rty, Soosh, TomJ, Waze, _Adam, __141345__, ajtra, benbaessler, c3phas, csanuragjain, durianSausage, exd0tpy, fatherOfBlocks, hake, ignacio, karanctf, kyteg, m_Rassska, oyc_109, rbserver, robee, rokinot, samruna, sashik_eth, simon135, slywaters
102.6444 USDC - $102.64
a = a + b
instead of a += b
MLOAD
<< SLOAD
immutable
instead of state variablesconstants/immutable/state
as private/internal
calldataloud
vs mload
Internal
functions can be inlineduint
instead of uint8
, uint64
, if it's possibleContracts:
file: Swivel/Swivel.sol ............................... // Lines: [100-100] unchecked {i++;} // Lines: [269-269] unchecked {i++;} // Lines: [417-417] unchecked { i++; } // Lines: [563-563] unchecked { i++; }
a = a + b
instead of a += b
<a name="G-02"></a>Contracts:
file: Swivel/Swivel.sol ............................... // Lines: [121-121, 158-158, 193-193, 222-222, 287-287, 318-318, 348-348, 383-383] filled[hash] += a; file: MarketPlace/Erc20.sol ............................... // Lines: [92-92; 114-114; 202-202] balanceOf[to] += amount; // Lines: [87-87; 109-109, 209;209] balanceOf[msg.sender] -= amount; // Lines: [197-197; 114-114;] totalSupply += amount; // Lines: [214-214] totalSupply -= amount; file: VaultTracker/VaultTracker.sol ............................... // Lines: [67-68] vlt.redeemable += interest; vlt.notional += a; // Lines: [102-103] vlt.redeemable += interest; vlt.notional -= a; // Lines: [174-175] from.redeemable += interest; from.notional -= a; // Lines: [193-194] to.redeemable += newVaultInterest; to.notional += a; // Lines: [230-234] sVault.redeemable += interest; sVault.notional += a;
Contracts:
file: Creator/Creator.sol ............................... // Lines: [30-39] function create ( uint8 p, address u, uint256 m, address c, address sw, string memory n, string memory s, uint8 d ) external authorized(marketPlace) returns (address, address) {} // Lines: [47-47] function setAdmin(address a) external authorized(admin) returns (bool) {} // Lines: [54-54] function setMarketPlace(address m) external authorized(admin) returns (bool) {} ```
Also in files VaultTracker.sol, MarketPlace.sol, Swivel.sol where there is a authorized(admin) modifier
MLOAD
<< SLOAD
<a name="G-04"></a>MLOAD
costs only 3 units of gas, SLOAD
(warm access) is about 100 units. Therefore, cache, when it's possible.Contracts:
file: MarketPlace/MarketPlace.sol ............................... // Lines: [46-46] if (swivel != address(0)) { revert Exception(20, 0, 0, swivel, address(0)); } // swivel could be cached // Lines: [71-77] if (swivel == address(0)) { revert Exception(21, 0, 0, address(0), address(0)); } (address zct, address tracker) = ICreator(creator).create(p, underAddr, m, c, swivel, n, s, IErc20(underAddr).decimals()) ; // swivel could be cached // Lines: [156-164] ISwivel(swivel).authRedeem(p, u, market.cTokenAddr, t, a); ISwivel(swivel).authRedeem(p, u, market.cTokenAddr, t, amount); // swivel could be cached ```
immutable
instead of state variables<a name="G-05"></a>Contracts:
file: Swivel/Swivel.sol ............................... // Lines: [33-33] address public aaveAddr; // TODO immutable? file: MarketPlace/Erc20.sol ............................... // Lines: [23-26] string public name; string public symbol; file: MarketPlace/MarketPlace.sol ............................... // Lines: [25-25] address public swivel;
constants/immutable/state
as private/internal
<a name="G-06"></a>Contracts:
file: Swivel/Swivel.sol ............................... // Lines: [17-21] mapping (bytes32 => bool) public cancelled; mapping (bytes32 => uint256) public filled; mapping (address => uint256) public withdrawals; mapping (address => uint256) public approvals; // Lines: [25-29] string constant public NAME = 'Swivel Finance'; string constant public VERSION = '3.0.0'; uint256 constant public HOLD = 3 days; bytes32 public immutable domain; address public immutable marketPlace; // Lines: [35-35] uint16 constant public MIN_FEENOMINATOR = 33; // Lines: [37-37] uint16[4] public feenominators; // Lines: [39-39] uint256 public feeChange; file: MarketPlace/Erc20.sol ............................... // Lines: [35-37] mapping(address => uint256) public balanceOf; mapping(address => mapping(address => uint256)) public allowance; mapping(address => uint256) public nonces; file: MarketPlace/MarketPlace.sol ............................... // Lines: [21-25] mapping (uint8 => mapping (address => mapping (uint256 => Market))) public markets; mapping (uint8 => bool) public paused; address public admin; address public swivel;
calldataloud
vs mload
<a name="G-07"></a>Contracts:
file: Swivel/Swivel.sol ............................... // Lines: [495-495] function setFee(uint16[] memory i, uint16[] memory d) external authorized(admin) returns (bool) {} file: MarketPlace/MarketPlace.sol ............................... // Lines: [64-70] function createMarket( uint8 p, uint256 m, address c, string memory n, string memory s ) external authorized(admin) unpaused(p) returns (bool) {}
Internal
functions can be inlined<a name="G-08"></a>JUMP
s which costs around 12 gas uints for each JUMP
.Contracts:
file: MarketPlace/MarketPlace.sol ............................... // Lines: [215-215] function calculateReturn(uint8 p, address u, uint256 m, uint256 a) internal view returns (uint256) {}
Contracts:
file: Swivel/Swivel.sol ............................... // Lines: [496-496] uint256 len = i.length; // there is no reason for this allocation. Use `i.length` in loops. // Lines: [545-545] uint256 len = u.length; // Lines: [549-549] uint256 max = 2**256 - 1; // just use const without invoking pow()
uint
instead of uint8
, uint64
, if it's possible<a name="G-10"></a>uint8
, uint64
leads to overheads.Contracts:
file: Swivel/Swivel.sol ............................... // Lines: [15-15] error Exception(uint8, uint256, uint256, address, address); // Lines: [15-15] uint16 constant public MIN_FEENOMINATOR = 33; // Lines: [15-15] uint16 constant public MIN_FEENOMINATOR = 33; // Lines: [15-15] uint16 constant public MIN_FEENOMINATOR = 33; // Lines: [495-495] function setFee(uint16[] memory i, uint16[] memory d) external authorized(admin) returns (bool) {} // Lines: [578-578] function splitUnderlying(uint8 p, address u, uint256 m, uint256 a) external returns (bool) {} // Lines: [600-600] function combineTokens(uint8 p, address u, uint256 m, uint256 a) external returns (bool) {} // Lines: [620-620] function authRedeemZcToken(uint8 p, address u, address c, address t, uint256 a) external authorized(marketPlace) returns(bool) {} // Lines: [634-634] function redeemZcToken(uint8 p, address u, uint256 m, uint256 a) external returns (bool) {} // Lines: [651-651] function redeemVaultInterest(uint8 p, address u, uint256 m) external returns (bool) {} // Lines: [670-670] function redeemSwivelVaultInterest(uint8 p, address u, uint256 m) external returns (bool) {} // Lines: [706-706] function deposit(uint8 p, address u, address c, uint256 a) internal returns (bool) {} // Lines: [739-739] function withdraw(uint8 p, address u, address c, uint256 a) internal returns (bool) {} file: MarketPlace/Compounding.sol ............................... // Lines: [50-50] function underlying(uint8 p, address c) internal view returns (address) {} // Lines: [68-68] function exchangeRate(uint8 p, address c) internal view returns (uint256) {} file: MarketPlace/MarketPlace.sol ............................... // Lines: [28-36] event Create(uint8 indexed protocol, address indexed underlying, uint256 indexed maturity, address cToken, address zcToken, address vaultTracker); event Mature(uint8 indexed protocol, address indexed underlying, uint256 indexed maturity, uint256 maturityRate, uint256 matured); event RedeemZcToken(uint8 indexed protocol, address indexed underlying, uint256 indexed maturity, address sender, uint256 amount); event RedeemVaultInterest(uint8 indexed protocol, address indexed underlying, uint256 indexed maturity, address sender); event CustodialInitiate(uint8 indexed protocol, address indexed underlying, uint256 indexed maturity, address zcTarget, address nTarget, uint256 amount); event CustodialExit(uint8 indexed protocol, address indexed underlying, uint256 indexed maturity, address zcTarget, address nTarget, uint256 amount); event P2pZcTokenExchange(uint8 indexed protocol, address indexed underlying, uint256 indexed maturity, address from, address to, uint256 amount); event P2pVaultExchange(uint8 indexed protocol, address indexed underlying, uint256 indexed maturity, address from, address to, uint256 amount); event TransferVaultNotional(uint8 indexed protocol, address indexed underlying, uint256 indexed maturity, address from, address to, uint256 amount); ```
Contracts:
file: Swivel/Swivel.sol ............................... // Lines: [30-30] address public admin; // could be tight up with `feenominators` ```
#0 - robrobbins
2022-08-31T17:26:36Z
adressing g: 09. no need to mstore the length of calldata arrays. rest are dupes or wontfix