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: 156/179
Findings: 2
Award: $21.32
馃専 Selected for report: 0
馃殌 Solo Findings: 0
馃専 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
Detailed description of the impact of this finding.
transfer() and send() should be avoided (because they take a hard dependency on gas costs by forwarding a fixed amount of gas: 2300).
call{value: ...}("") should be used, for example: contractB.call{value: 1000}("")
Provide direct links to all referenced code in GitHub. Add screenshots, logs, or any other relevant proof that illustrates the concept.
Any gas specific code should be avoided because gas costs can and will change.
For example, the gas cost for SLOAD was raised from 50 to 200 in 2016, and again in EIP 1884, with some impacts described in: https://chainsecurity.com/istanbul-hardfork-eips-increasing-gas-costs-and-more/
https://ethereum.stackexchange.com/questions/78124/is-transfer-still-safe-after-the-istanbul-update
use .call(value) instead of transfer.
#0 - KenzoAgada
2022-08-03T14:06:15Z
Duplicate of #343
馃専 Selected for report: JohnSmith
Also found by: 0x1f8b, 0xA5DF, 0xDjango, 0xKitsune, 0xLovesleep, 0xNazgul, 0xSmartContract, 0xmatt, 0xsam, Aymen0909, Bnke0x0, CRYP70, Chandr, Chinmay, CodingNameKiki, Deivitto, Dravee, ElKu, Fitraldys, Funen, GalloDaSballo, Green, IllIllI, JC, Jmaxmanblue, Junnon, Kaiziron, Kenshin, Krow10, Maxime, Migue, MiloTruck, Noah3o6, NoamYakov, Randyyy, RedOneN, ReyAdmirado, Rohan16, Rolezn, Ruhum, Sm4rty, StyxRave, TomJ, Tomio, _Adam, __141345__, ajtra, ak1, apostle0x01, asutorufos, async, benbaessler, brgltd, c3phas, cRat1st0s, carlitox477, delfin454000, djxploit, durianSausage, ellahi, erictee, fatherOfBlocks, gerdusx, gogo, hyh, jayfromthe13th, jayphbee, joestakey, kaden, kenzo, kyteg, ladboy233, lucacez, m_Rassska, mics, minhquanym, oyc_109, pfapostol, rbserver, reassor, rfa, robee, rokinot, sach1r0, saian, samruna, sashik_eth, simon135, supernova, tofunmi, zuhaibmohd
21.3211 USDC - $21.32
can use abi.encodePacked() instead of abi.encode() to save gas.
EIP712_DOMAIN_TYPEHASH = keccak256( abi.encode( keccak256('EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)'), keccak256(bytes('GOLOM.IO')), keccak256(bytes('1')), chainId, address(this) ) );
return keccak256( abi.encode( keccak256( 'order(address collection,uint256 tokenId,address signer,uint256 orderType,uint256 totalAmt,payment exchange,payment prePayment,bool isERC721,uint256 tokenAmt,uint256 refererrAmt,bytes32 root,address reservedAddress,uint256 nonce,uint256 deadline)payment(uint256 paymentAmt,address paymentAddress)' ),
bytes32 computedHash = keccak256(abi.encode(leaf));
function _settleBalances( Order calldata o, uint256 amount, address referrer, Payment calldata p ) internal
internal can be marked private.
function fillAsk( Order calldata o, uint256 amount, address referrer, Payment calldata p, address receiver ) public payable nonReentrant
public can be marked as external
function fillBid( Order calldata o, uint256 amount, address referrer, Payment calldata p ) public nonReentrant {
function fillCriteriaBid( Order calldata o, uint256 amount, uint256 tokenId, bytes32[] calldata proof, address referrer, Payment calldata p ) public nonReentrant {
function addFee(address[2] memory addr, uint256 fee) public onlyTrader
function traderClaim(address addr, uint256[] memory epochs) public {
function exchangeClaim(address addr, uint256[] memory epochs) public {
function multiStakerClaim(uint256[] memory tokenids, uint256[] memory epochs) public {
function stakerRewards(uint256 tokenid) public view returns (
function traderRewards(address addr) public view returns
function exchangeRewards(address addr) public view returns
Custom errors are available from solidity version 0.8.4. Custom errors save ~50 gas each time they鈥檙e hitby avoiding having to allocate and store the revert string. Not defining the strings also save deployment gas
require(signaturesigner == o.signer, 'invalid signature');
require( o.totalAmt >= o.exchange.paymentAmt + o.prePayment.paymentAmt + o.refererrAmt + (o.totalAmt * 50) / 10000, 'amt not matching' );
require(msg.value >= o.totalAmt * amount + p.paymentAmt, 'mgmtm');
require(o.orderType == 0, 'invalid orderType');
require(status == 3, 'order not valid');
require(amountRemaining >= amount, 'order already filled');
require(amount == 1, 'only 1 erc721 at 1 time');
require(address(ve) != address(0), ' VE not added yet');
路路路 require(tokenowner == ve.ownerOf(tokenids[tindex]), 'Can only claim for a single Address together'); 路路路
路路路 require(epochs[index] < epoch, 'cant claim for future epochs'); require(claimed[tokenids[tindex]][epochs[index]] == 0, 'cant claim if already claimed'); 路路路
路路路 require(address(ve) != address(0), ' VE not added yet'); 路路路
路路路 require(traderEnableDate <= block.timestamp, 'RewardDistributor: time not over yet'); 路路路
路路路 require(voteEscrowEnableDate <= block.timestamp, 'RewardDistributor: time not over yet'); 路路路
bool public isAirdropMinted;
bool public isGenesisRewardMinted;
we can use uint8, 0 or 1 to indicate the state change.
uint256 tokenToEmit = (dailyEmission * (rewardToken.totalSupply() - rewardToken.balanceOf(address(ve)))) / rewardToken.totalSupply(); uint256 stakerReward = (tokenToEmit * rewardToken.balanceOf(address(ve))) / rewardToken.totalSupply();
rewardTokn.totalSupply() and rewardToken.balanceOf(address(ve)) are called muptiple times. both can be cached in uint256 variable to save gas. such as
uint256 totalSupply = rewardTokn.totalSupply() uint256 veBalance = rewardToken.balanceOf(address(ve))
<array>.length can be cached.
for (uint256 index = 0; index < epochs.length; index++) {
epochs.length can be cached.
for (uint256 tindex = 0; tindex < tokenids.length; tindex++) {