Platform: Code4rena
Start Date: 21/06/2022
Pot Size: $50,000 USDC
Total HM: 31
Participants: 99
Period: 5 days
Judges: moose-code, JasoonS, denhampreen
Total Solo HM: 17
Id: 139
League: ETH
Rank: 91/99
Findings: 1
Award: $26.57
🌟 Selected for report: 0
🚀 Solo Findings: 0
🌟 Selected for report: BowTiedWardens
Also found by: 0v3rf10w, 0x1f8b, 0x29A, 0xKitsune, 0xNazgul, 0xf15ers, 0xkatana, 0xmint, 8olidity, ACai, Bnke0x0, Chom, ElKu, Fabble, Fitraldys, FudgyDRS, Funen, GalloDaSballo, GimelSec, IllIllI, JC, Kaiziron, Lambda, Limbooo, MiloTruck, Noah3o6, Nyamcil, Picodes, PwnedNoMore, Randyyy, RedOneN, Sm4rty, StErMi, TomJ, Tomio, TrungOre, UnusualTurtle, Waze, _Adam, aga7hokakological, ajtra, antonttc, asutorufos, bardamu, c3phas, defsec, delfin454000, exd0tpy, fatherOfBlocks, hansfriese, ignacio, joestakey, kenta, ladboy233, m_Rassska, mics, minhquanym, oyc_109, pashov, reassor, robee, s3cunda, sach1r0, saian, sashik_eth, scaraven, sikorico, simon135, slywaters
26.5713 USDC - $26.57
unchecked
to save gasExpression that cant overflow/underflow can be placed in a unchecked block which will avoid the default overflow/underflow checks introduced in 0.8 and save gas
require(creditAmount <= creditBalances[msg.sender], "Not enough funds"); creditBalances[msg.sender] = creditBalances[msg.sender] - creditAmount;
require(_allowances[_from][msg.sender] >= _value, "Allowance too low"); uint256 newValue = _allowances[_from][msg.sender] - _value;
Storage variables can be cached in a local variables and reused instead of reading from storage to save gas
CURVE_POOL
in setToAndFromCurve()
replace curvePoolTo
, curvePoolFrom
with from
, to
curvePoolFrom = from; curvePoolTo = to; emit LogSetCurvePool(CURVE_POOL, curvePoolTo, curvePoolFrom);
decimal
can be replaced with function parameter _decimal
decimal = _decimal; WAD = 10**decimal;
_totalSupply
can be replaced with currentTotalSupply
uint256 currentTotalSupply = _totalSupply; require(_totalSupply > 0, "Can't rebase if not circulating");
_totalSupply
in
contract[i]
in
if ( contracts[i] != address(0) && IStaking(contracts[i]).canBatchTransactions() ) { IStaking(contracts[i]).sendWithdrawalRequests(); }
contracts[i]
in
bool canBatch = IStaking(contracts[i]).canBatchTransactions(); batch[i] = Batch(contracts[i], canBatch);
contracts[_index]
in
return ( contracts[_index], IStaking(contracts[_index]).canBatchTransactions() );
When variables are created it contains default values, explicitly initialising with default values(0, address(0), false) is not necessary
int128 from = 0; int128 to = 0;
address address0 = ICurvePool(CURVE_POOL).coins(0); address address1 = ICurvePool(CURVE_POOL).coins(1); int128 from = 0; int128 to = 0; if (TOKE_POOL == address0 && STAKING_TOKEN == address1) { to = 1; } else if (TOKE_POOL == address1 && STAKING_TOKEN == address0) { from = 1; } require(from == 1 || to == 1, "Invalid Curve Pool"); curvePoolFrom = from; curvePoolTo = to;
address address0 = ICurvePool(CURVE_POOL).coins(0); address address1 = ICurvePool(CURVE_POOL).coins(1); if (TOKE_POOL == address0 && STAKING_TOKEN == address1) { curvePoolTo = 1; } else if (TOKE_POOL == address1 && STAKING_TOKEN == address0) { curvePoolFrom = 1; } else { revert("Invalid Curve Pool"); }
exit out of the loop after deleting address instead of iterating over the entire array
for (uint256 i; i < contractsLength; ) { if (contracts[i] == _address) { delete contracts[i]; } unchecked { ++i; } }
Add return statement after delete statement, or swap last index with target index and pop the last element to avoid iterating over long array