Platform: Code4rena
Start Date: 26/07/2022
Pot Size: $75,000 USDC
Total HM: 29
Participants: 179
Period: 6 days
Judge: LSDan
Total Solo HM: 6
Id: 148
League: ETH
Rank: 63/179
Findings: 4
Award: $181.99
π Selected for report: 0
π Solo Findings: 0
π Selected for report: berndartmueller
Also found by: 0x1f8b, 0x52, 0xA5DF, 0xsanson, CRYP70, GimelSec, Krow10, TrungOre, auditor0517, hansfriese, hyh, panprog, rajatbeladiya, rbserver, teddav
93.2805 USDC - $93.28
not able to set voteEscrow
contract address to RewardDistributor
. So stakerRewards()
and multiStakerClaim()
will not work and no one will be able to claim their rewards.
https://github.com/code-423n4/2022-07-golom/blob/e5efa8f9d6dda92a90b8b2c4902320acf0c26816/contracts/rewards/RewardDistributor.sol#L172 https://github.com/code-423n4/2022-07-golom/blob/e5efa8f9d6dda92a90b8b2c4902320acf0c26816/contracts/rewards/RewardDistributor.sol#L215
pendingVoteEscrow
used to initialize ve
but pendingVoteEscrow
will be zero address.
Manual Analysis
https://github.com/code-423n4/2022-07-golom/blob/e5efa8f9d6dda92a90b8b2c4902320acf0c26816/contracts/rewards/RewardDistributor.sol#L300
use _voteEscrow
insted of pendingVoteEscrow
#0 - KenzoAgada
2022-08-02T09:24:56Z
Duplicate of #611
π Selected for report: GimelSec
Also found by: 0x52, 0xA5DF, 0xSky, 0xsanson, Bahurum, CertoraInc, GalloDaSballo, JohnSmith, Lambda, MEP, Twpony, arcoun, berndartmueller, cryptphi, hansfriese, kenzo, kyteg, panprog, rajatbeladiya, scaraven, simon135, zzzitron
26.7695 USDC - $26.77
https://github.com/code-423n4/2022-07-golom/blob/e5efa8f9d6dda92a90b8b2c4902320acf0c26816/contracts/vote-escrow/VoteEscrowDelegation.sol#L71-L89 https://github.com/code-423n4/2022-07-golom/blob/e5efa8f9d6dda92a90b8b2c4902320acf0c26816/contracts/vote-escrow/VoteEscrowDelegation.sol#L101
numCheckPoints
is used to calculate checkpoints for each delegated tokenId
here, initial nCheckpoints
is set to zero, substract it to by 1 will throw Underflow error
. So delegate
will not work
it.only('should delegate', async () => { let ve_underlying_amount = ethers.utils.parseEther('10'); let ve_underlying_approve_amount = ethers.utils.parseUnits('10', 28); await golomToken.mint(maker.address, ve_underlying_approve_amount); await golomToken.approve(voteEscrow.address, ve_underlying_approve_amount); const lockDuration = 365 * 24 * 3600 * 4; // 4 year const rewards_starts_at = 2659187519; await ethers.provider.send('evm_setNextBlockTimestamp', [rewards_starts_at]); let re = await voteEscrow.create_lock(ve_underlying_amount, lockDuration); await voteEscrow.delegate(1, 1); // error with underflow error }); `Error: VM Exception while processing transaction: reverted with panic code 0x11 (Arithmetic operation underflowed or overflowed outside of an unchecked block)`
Manual Analysis
add below check to _writeCheckpoint
Checkpoint memory oldCheckpoint; if (nCheckpoints > 0) { oldCheckpoint = checkpoints[toTokenId][nCheckpoints - 1]; }
#0 - KenzoAgada
2022-08-02T09:19:04Z
Duplicate of #630
26.7695 USDC - $26.77
https://github.com/code-423n4/2022-07-golom/blob/e5efa8f9d6dda92a90b8b2c4902320acf0c26816/contracts/vote-escrow/VoteEscrowDelegation.sol#L80 https://github.com/code-423n4/2022-07-golom/blob/e5efa8f9d6dda92a90b8b2c4902320acf0c26816/contracts/vote-escrow/VoteEscrowDelegation.sol#L168-L175
delegate call not checking for existing Ids and pushes same tokenId multiple times which is also used for calculate votes. Votes can play a key role in governance ( did not checked governance contract, as it is not in the scope ), bad actor can manipulate proposals in any way.
it.only('should increase vote on same delegate call', async () => { try { let ve_underlying_amount = ethers.utils.parseEther('10'); let ve_underlying_approve_amount = ethers.utils.parseUnits('10', 28); await golomToken.mint(maker.address, ve_underlying_approve_amount); await golomToken.approve(voteEscrow.address, ve_underlying_approve_amount); const lockDuration = 365 * 24 * 3600 * 4; // 4 year const rewards_starts_at = 2659187519; await ethers.provider.send('evm_setNextBlockTimestamp', [rewards_starts_at]); let re = await voteEscrow.create_lock(ve_underlying_amount, lockDuration); await voteEscrow.delegate(1, 1); const votes1 = await voteEscrow.getVotes(1); await voteEscrow.delegate(1, 1); const votes2 = await voteEscrow.getVotes(1); await voteEscrow.delegate(1, 1); const votes3 = await voteEscrow.getVotes(1); console.log('votes1===', Number(votes1)); // 9981963390993345000 console.log('votes2===', Number(votes2)); // 19963926623437730000 console.log('votes3===', Number(votes3)); // 29945889697333154000 } catch (error: any) { console.log('error===', error); } });
Manual Analysis
check for existing delegatedId
or keep track using mapping
insted of array
#0 - KenzoAgada
2022-08-02T12:00:48Z
Duplicate of #169
π Selected for report: IllIllI
Also found by: 0x1f8b, 0x4non, 0x52, 0xA5DF, 0xDjango, 0xLovesleep, 0xNazgul, 0xNineDec, 0xSmartContract, 0xackermann, 0xc0ffEE, 0xf15ers, 0xmatt, 0xsanson, 0xsolstars, 8olidity, AuditsAreUS, Bahurum, Bnke0x0, CRYP70, CertoraInc, Ch_301, Chom, CryptoMartian, Deivitto, DevABDee, Dravee, ElKu, Franfran, Funen, GalloDaSballo, GimelSec, GiveMeTestEther, Green, JC, Jmaxmanblue, JohnSmith, Jujic, Junnon, Kenshin, Krow10, Kumpa, Lambda, MEP, Maxime, MiloTruck, Mohandes, NoamYakov, Picodes, RedOneN, Rohan16, Rolezn, Ruhum, RustyRabbit, Sm4rty, Soosh, StErMi, StyxRave, Tadashi, TomJ, Treasure-Seeker, TrungOre, Waze, _Adam, __141345__, ajtra, ak1, apostle0x01, arcoun, asutorufos, async, benbaessler, berndartmueller, bin2chen, brgltd, c3phas, cRat1st0s, carlitox477, chatch, codetilda, codexploder, cryptonue, cryptphi, csanuragjain, cthulhu_cult, delfin454000, dipp, dirk_y, djxploit, ellahi, exd0tpy, fatherOfBlocks, giovannidisiena, hansfriese, horsefacts, hyh, idkwhatimdoing, indijanc, jayfromthe13th, jayphbee, joestakey, kenzo, kyteg, lucacez, luckypanda, mics, minhquanym, obront, oyc_109, pedr02b2, rajatbeladiya, rbserver, reassor, robee, rokinot, rotcivegaf, sach1r0, saian, saneryee, sashik_eth, scaraven, shenwilly, simon135, sseefried, supernova, teddav, ych18, zuhaibmohd, zzzitron
35.1687 USDC - $35.17
same address will intiate two different transactions.
here msg.value
can be more than needed. Add function to windraw eth which can be extra deposited eth or accidently sent to this contract .
https://github.com/code-423n4/2022-07-golom/blob/e5efa8f9d6dda92a90b8b2c4902320acf0c26816/contracts/core/GolomTrader.sol#L242 https://github.com/code-423n4/2022-07-golom/blob/e5efa8f9d6dda92a90b8b2c4902320acf0c26816/contracts/core/GolomTrader.sol#L269 https://github.com/code-423n4/2022-07-golom/blob/e5efa8f9d6dda92a90b8b2c4902320acf0c26816/contracts/core/GolomTrader.sol#L381
Solidity integer division might truncate. As a result, performing multiplication before division can sometimes avoid loss of precision.
https://github.com/code-423n4/2022-07-golom/blob/e5efa8f9d6dda92a90b8b2c4902320acf0c26816/contracts/core/GolomTrader.sol#L382 https://github.com/code-423n4/2022-07-golom/blob/e5efa8f9d6dda92a90b8b2c4902320acf0c26816/contracts/rewards/RewardDistributor.sol#L151
Not checking return values of transfer for WETH/ERC20 could lead to loss of user's fund on transfer failure. ERC20 implementations are not always consistent. Some implementations of transfer and transferFrom could return βfalseβ on failure instead of reverting. It is safer to wrap such calls into require() statements to these failures.
GolomToken
has pragma solidity version number with ^0.8.11. The caret (^) points to unlocked pragma, meaning compiler will use the specified version or above. It's good practice to use specific solidity version to know compiler bug fixes and optimisations were enabled at the time of compiling the contract.
add zero address check validation
remove unnecessary commented code
it could be Insufficient ETH