Platform: Code4rena
Start Date: 12/07/2022
Pot Size: $75,000 USDC
Total HM: 16
Participants: 100
Period: 7 days
Judge: LSDan
Total Solo HM: 7
Id: 145
League: ETH
Rank: 64/100
Findings: 2
Award: $118.73
π Selected for report: 0
π Solo Findings: 0
π Selected for report: IllIllI
Also found by: 0x1f8b, 0x29A, 0xDjango, 0xNazgul, 0xNineDec, 0xf15ers, 8olidity, Aussie_Battlers, Bnke0x0, Ch_301, Critical, Deivitto, Dravee, ElKu, Funen, GimelSec, JC, JohnSmith, Lambda, MiloTruck, PwnedNoMore, ReyAdmirado, Rohan16, Rolezn, Ruhum, RustyRabbit, Sm4rty, TomJ, Waze, _Adam, __141345__, alan724, asutorufos, benbaessler, berndartmueller, bin2chen, brgltd, bulej93, c3phas, cRat1st0s, cryptonue, cryptphi, csanuragjain, delfin454000, dxdv, exd0tpy, fatherOfBlocks, gogo, hake, hyh, joestakey, kyteg, lcfr_eth, minhtrng, p_crypt0, pashov, pedr02b2, philogy, rajatbeladiya, rbserver, rishabh, robee, rokinot, sach1r0, sashik_eth, seyni, simon135, svskaushik, zuhaibmohd, zzzitron
78.8735 USDC - $78.87
https://github.com/code-423n4/2022-07-ens/blob/1772ac3d16c8e84bb9c1e02a0c4e321cd6f5652b/contracts/wrapper/NameWrapper.sol#L2 https://github.com/code-423n4/2022-07-ens/blob/04539b27307abd65068b96dd20fc686b451bf9fc/contracts/dnssec-oracle/BytesUtils.sol#L1
https://github.com/code-423n4/2022-07-ens/blob/04539b27307abd65068b96dd20fc686b451bf9fc/contracts/dnssec-oracle/Owned.sol#L18-L21 https://github.com/code-423n4/2022-07-ens/blob/04539b27307abd65068b96dd20fc686b451bf9fc/contracts/wrapper/Controllable.sol#L11
instead of the owner giveing it to him already becuse if the new owner cant be come new owner (keys missing) then its wasted address and you might have to redeploy. https://github.com/code-423n4/2022-07-ens/blob/04539b27307abd65068b96dd20fc686b451bf9fc/contracts/dnssec-oracle/Owned.sol#L18-L21
instead of : authorised use : authorized https://github.com/code-423n4/2022-07-ens/blob/1772ac3d16c8e84bb9c1e02a0c4e321cd6f5652b/contracts/wrapper/NameWrapper.sol#L329
becauser transfer can revert because it only can foward 2300 gas which is msg.sender fallback functions is anything not just an emit it will revert. https://github.com/code-423n4/2022-07-ens/blob/04539b27307abd65068b96dd20fc686b451bf9fc/contracts/ethregistrar/ETHRegistrarController.sol#L204https://github.com/code-423n4/2022-07-ens/blob/04539b27307abd65068b96dd20fc686b451bf9fc/contracts/ethregistrar/ETHRegistrarController.sol#L183
π Selected for report: 0xKitsune
Also found by: 0x040, 0x1f8b, 0x29A, 0xNazgul, 0xNineDec, 0xsam, 8olidity, Aussie_Battlers, Aymen0909, Bnke0x0, CRYP70, Ch_301, Chom, Deivitto, Dravee, ElKu, Fitraldys, Funen, GimelSec, IllIllI, JC, JohnSmith, Lambda, MiloTruck, Noah3o6, RedOneN, ReyAdmirado, Rohan16, Rolezn, Ruhum, Sm4rty, TomJ, Tomio, Waze, _Adam, __141345__, ajtra, ak1, arcoun, asutorufos, benbaessler, brgltd, bulej93, c3phas, cRat1st0s, cryptonue, delfin454000, durianSausage, fatherOfBlocks, gogo, hake, hyh, joestakey, karanctf, kyteg, lcfr_eth, lucacez, m_Rassska, rajatbeladiya, rbserver, robee, rokinot, sach1r0, sahar, samruna, sashik_eth, seyni, simon135, zuhaibmohd
39.8564 USDC - $39.86
Custom errors from Solidity 0.8.4 are cheaper than revert strings (cheaper deployment cost and runtime cost when the revert condition is met) Source Custom Errors in Solidity: Starting from Solidity v0.8.4, there is a convenient and gas-efficient way to explain to users why an operation failed through the use of custom errors. Until now, you could already use strings to give more information about failures (e.g., revert("Insufficient funds.");), but they are rather expensive, especially when it comes to deploy cost, and it is difficult to use dynamic information in them. Custom errors are defined using the error statement, which can be used inside and outside of contracts (including interfaces and libraries).
./contracts/root/Ownable.sol:10: require(isOwner(msg.sender)); ./contracts/root/Root.sol:26: require(!locked[label]); ./contracts/utils/LowLevelCallUtils.sol:22: require( ./contracts/wrapper/BytesUtil.sol:13: require(offset + len <= self.length); ./contracts/wrapper/BytesUtil.sol:28: require(offset == self.length - 1, "namehash: Junk at end of name"); ./contracts/wrapper/BytesUtil.sol:42: require(idx < self.length, "readLabel: Index out of bounds"); ./contracts/wrapper/Controllable.sol:17: require(controllers[msg.sender], "Controllable: Caller is not a controller"); ./contracts/wrapper/ERC1155Fuse.sol:60: require( ./contracts/wrapper/ERC1155Fuse.sol:85: require( ./contracts/wrapper/ERC1155Fuse.sol:107: require( ./contracts/wrapper/ERC1155Fuse.sol:176: require(to != address(0), "ERC1155: transfer to the zero address"); ./contracts/wrapper/ERC1155Fuse.sol:177: require( ./contracts/wrapper/ERC1155Fuse.sol:195: require( ./contracts/wrapper/ERC1155Fuse.sol:199: require(to != address(0), "ERC1155: transfer to the zero address"); ./contracts/wrapper/ERC1155Fuse.sol:200: require( ./contracts/wrapper/ERC1155Fuse.sol:215: require( ./contracts/wrapper/ERC1155Fuse.sol:248: require(owner == address(0), "ERC1155: mint of existing token"); ./contracts/wrapper/ERC1155Fuse.sol:249: require(newOwner != address(0), "ERC1155: mint to the zero address"); ./contracts/wrapper/ERC1155Fuse.sol:250: require( ./contracts/wrapper/ERC1155Fuse.sol:290: require( ## ++i costs less gas compared to i++ or i += 1 ++i costs less gas compared to i++ or i += 1 for unsigned integer, as pre-increment is cheaper (about 5 gas per iteration). This statement is true even with the optimizer enabled. i++ increments i and returns the initial value of i. Which means: uint i = 1; i++; // == 1 but i == 2 But ++i returns the actual incremented value: uint i = 1; ++i; // == 2 and i == 2 too, so no need for a temporary variable In the first case, the compiler has to create a temporary variable (when used) for returning 1 instead of 2 uint256 i = 0; i < depositedTokens.values.length; i++) https://github.com/code-423n4/2022-07-ens/blob/04539b27307abd65068b96dd20fc686b451bf9fc/contracts/dnssec-oracle/RRUtils.sol#L235 https://github.com/code-423n4/2022-07-ens/blob/04539b27307abd65068b96dd20fc686b451bf9fc/contracts/dnssec-oracle/RRUtils.sol#L250 https://github.com/code-423n4/2022-07-ens/blob/04539b27307abd65068b96dd20fc686b451bf9fc/contracts/dnssec-oracle/RRUtils.sol#L235
because there is no check for msg.value =0 so it saves gas
./contracts/registry/FIFSRegistrar.sol:33: function register(bytes32 label, address owner) public only_owner(label)
to save gas ex: 0x000000000000 https://github.com/code-423n4/2022-07-ens/blob/04539b27307abd65068b96dd20fc686b451bf9fc/contracts/ethregistrar/ETHRegistrarController.sol#L100
./contracts/wrapper/NameWrapper.sol:132: if (address(upgradeContract) != address(0)) { ./contracts/wrapper/NameWrapper.sol:139: if (address(upgradeContract) != address(0)) { ./contracts/wrapper/NameWrapper.sol:318: if (resolver != address(0)) { ./contracts/wrapper/NameWrapper.sol:661: if (owner == address(0)) { ./contracts/wrapper/NameWrapper.sol:763: if (oldWrappedOwner != address(0)) { ./contracts/wrapper/NameWrapper.sol:766: emit NameUnwrapped(node, address(0)); ./contracts/wrapper/NameWrapper.sol:799: if (address(upgradeContract) == address(0)) { ./contracts/wrapper/NameWrapper.sol:911: if (resolver != address(0)) { ./contracts/wrapper/NameWrapper.sol:919: if (newOwner == address(0x0) || newOwner == address(this)) { ./contracts/wrapper/ERC1155Fuse.sol:176: require(to != address(0), "ERC1155: transfer to the zero address"); ./contracts/wrapper/ERC1155Fuse.sol:199: require(to != address(0), "ERC1155: transfer to the zero address"); ./contracts/wrapper/ERC1155Fuse.sol:248: require(owner == address(0), "ERC1155: mint of existing token"); ./contracts/wrapper/ERC1155Fuse.sol:249: require(newOwner != address(0), "ERC1155: mint to the zero address"
// Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. https://github.com/code-423n4/2022-07-ens/blob/04539b27307abd65068b96dd20fc686b451bf9fc/contracts/wrapper/Controllable.sol#L7
./contracts/dnssec-oracle/BytesUtils.sol:346: require(char >= 0x30 && char <= 0x7A);
./contracts/wrapper/ERC1155Fuse.sol:92: for (uint256 i = 0; i < accounts.length; ++i) { ./contracts/wrapper/ERC1155Fuse.sol:205: for (uint256 i = 0; i < ids.length; ++i) { ./contracts/ethregistrar/ETHRegistrarController.sol:256: for (uint256 i = 0; i < data.length; i++) {
Solidity version 0.8+ comes with implicit overflow and underflow checks on unsigned integers. When an overflow or an underflow isnβt possible (as an example, when a comparison is made before the arithmetic operation), some gas can be saved by using an unchecked block: Checked or Unchecked Arithmetic. I suggest wrapping with an unchecked block: Same thing with second unchecked because total can't overflow amount cant overflow
./contracts/wrapper/ERC1155Fuse.sol:92: for (uint256 i = 0; i < accounts.length; ++i) { ./contracts/wrapper/ERC1155Fuse.sol:205: for (uint256 i = 0; i < ids.length; ++i) { ./contracts/ethregistrar/ETHRegistrarController.sol:256: for (uint256 i = 0; i < data.length; i++) {