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: 35/179
Findings: 5
Award: $362.48
๐ 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
https://github.com/code-423n4/2022-07-golom/blob/main/contracts/rewards/RewardDistributor.sol#L300
In RewardDistributor contract, the ve
contract can never be set.
Itโs supposed to be set in addVoteEscrow()
(and then confirmed in executeAddVoteEscrow()
)
But the line if (address(ve) == address(0))
will always be true because the ve
variable doesnโt have any other setter. And since pendingVoteEscrow
is always 0, it will keep setting ve
to address(0).
Fix: The first call should automatically set the address passed as parameter. Then next calls will implement the timelock Rewrite the function addVoteEscrow() as:
function addVoteEscrow(address _voteEscrow) external onlyOwner { if (address(ve) == address(0)) { ve = VE(_voteEscrow); } else { voteEscrowEnableDate = block.timestamp + 1 days; pendingVoteEscrow = _voteEscrow; } }
#0 - KenzoAgada
2022-08-02T09:25:15Z
Duplicate of #611
๐ Selected for report: cloudjunky
Also found by: 0x1f8b, 0x4non, 0x52, 0xDjango, 0xHarry, 0xNazgul, 0xNineDec, 0xf15ers, 0xsanson, 0xsolstars, 8olidity, Bnke0x0, CertoraInc, Chom, Deivitto, Dravee, GalloDaSballo, GimelSec, IllIllI, Jmaxmanblue, JohnSmith, Jujic, Kenshin, Krow10, Lambda, MEP, Noah3o6, RedOneN, Ruhum, StErMi, StyxRave, TomJ, Treasure-Seeker, TrungOre, _Adam, __141345__, arcoun, asutorufos, bardamu, bearonbike, bin2chen, brgltd, bulej93, c3phas, cRat1st0s, carlitox477, cccz, codexploder, cryptonue, cryptphi, cthulhu_cult, dharma09, dipp, djxploit, durianSausage, ellahi, giovannidisiena, hansfriese, horsefacts, hyh, immeas, indijanc, jayjonah8, jayphbee, joestakey, kenzo, kyteg, ladboy233, minhquanym, navinavu, obront, oyc_109, peritoflores, rbserver, reassor, rokinot, rotcivegaf, saian, scaraven, shenwilly, simon135, sseefried, teddav, zzzitron
0.0037 USDC - $0.00
https://github.com/code-423n4/2022-07-golom/blob/main/contracts/core/GolomTrader.sol#L151
Asks or bids could fail if one of the addresses involved is a contract and cannot receive ETH
The function payEther is used in all functions: fillAsk()
, fillBid()
and fillCriteriaBid()
(_settleBalances()
).
This function just tries to call transfer()
to transfer ETH to the receiver. If the receiver is a contract and doesnโt have a receive() payable
function, then the .transfer()
will revert and the bid or ask will not be able to be filled.
Provide direct links to all referenced code in GitHub. Add screenshots, logs, or any other relevant proof that illustrates the concept.
Fix:
Add a fallback in payEther()
to use WETH if ETH transfer fails
(success, ) = payAddress.call{ value: payAmt }(โโ); if (!success) { WETH.deposit{ value: payAmt }(โฆ): require(WETH.transfer(payAddress, payAmt)); }
#0 - 0xsaruman
2022-08-24T11:06:55Z
๐ Selected for report: codexploder
Also found by: 0x1f8b, 0xNineDec, 0xsanson, RustyRabbit, Treasure-Seeker, berndartmueller, chatch, teddav
104.014 USDC - $104.01
Judge has assessed an item in Issue #42 as Medium risk. The relevant finding follows:
Permit signature replay across forks Details: GolomTrader.sol defines chainId at contract deployment without reconstructing it for every signature. However, as stated in the security considerations section of EIP2612, "If the DOMAIN_SEPARATOR contains the chainId and is defined at contract deployment instead of reconstructed for every signature, there is a risk of possible replay attacks between chains in the event of a future chain split.โ ****
Impact: Low (depends on the hard forking of a well-established blockchain)
Mitigation: Consider caching the chainId as is done in OpenZeppelin contracts.
#0 - dmvt
2022-10-21T15:53:53Z
Duplicate of #391
https://github.com/code-423n4/2022-07-golom/blob/main/contracts/core/GolomTrader.sol#L176
validateOrder()
is vulnerable to signature forgery because it doesnโt check if the result of ecrecover is address(0)
ecrecover returns address(0) if the signature is invalid. Here, the only check made is require(signaturesigner == o.signer, 'invalid signature')
Since the Order data is controlled by the user, we can just pass o.signer = address(0)
. So this check is passed.
The rest of the data for the Order can be filled as we desire, so we can transfer to ourself any NFT owned by anyone who gave approval to Golom.
The totalAmt can just be set to 0 and we get all NFTs for free.
manual
Fix: check that the result of ecrecover is not address(0)
require(signaturesigner != address(0))
#0 - KenzoAgada
2022-08-05T02:01:30Z
Duplicate of #357
๐ 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
1-
Set a fixed version for Solidity, not a floating version.
Remove ^
in pragma solidity ^0.8.11;
It should be pragma solidity 0.8.11;
GovernerBravo.sol, GolomToken.sol, โฆ
2-
No need for ABIEncoderV2
with Solidity 0.8
Remove pragma experimental ABIEncoderV2;
3- File names do not match contract names + there are typos in the filenames GovernerBravo.sol but inside the contract is called GovernorAlpha Either fix the filename or the contract name. If you change the filename, GovernerBravo.sol should be GovernorBravo.sol (with an "o").
Same for Timlock.sol, but the name of the contract is Timelock. Or VoteEscrowDelegation.sol -> VoteEscrow contract.
4- Add 0-address checks in constructors and setter functions. For example: RewardDistributor.sol in constructor https://github.com/code-423n4/2022-07-golom/blob/main/contracts/rewards/RewardDistributor.sol#L74 Or in the constructor of GolomToken: https://github.com/code-423n4/2022-07-golom/blob/main/contracts/governance/GolomToken.sol#L28
5- Remove console.log in RewardDistributor.sol