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: 15/100
Findings: 3
Award: $1,056.57
🌟 Selected for report: 0
🚀 Solo Findings: 0
937.2294 USDC - $937.23
https://github.com/code-423n4/2022-07-ens/blob/04539b27307abd65068b96dd20fc686b451bf9fc/contracts/dnssec-oracle/DNSSECImpl.sol#L126 https://github.com/code-423n4/2022-07-ens/blob/04539b27307abd65068b96dd20fc686b451bf9fc/contracts/dnssec-oracle/RRUtils.sol#L267
RRUtils.serialNumberGte
casts the passed uint32
to an int32
before doing the calculation. This cast can overflow, resulting in negative values, which invalidates the calculation and results in RRSet that are valid but cannot be validated.
An RRSet has an expiration timestamp of 2147483648 (Tue Jan 19 2038 03:14:08 GMT+0000). On Jan 18 2038 (timestamp 2147382000), the RRSet is validated. Inside serialNumberGte
, we have:
int32(2147483648) - int32(2147382000) = -2147483648 - 2147382000
This causes a reversion.
Although it is stated, the implementation does not actually implement RFC1982, where comparison is defined as:
s1 is said to be less than s2 if, and only if, s1 is not equal to s2, and (i1 < i2 and i2 - i1 < 2^(SERIAL_BITS - 1)) or (i1 > i2 and i1 - i2 > 2^(SERIAL_BITS - 1))
Furthermore, it is stated that "Arithmetic and comparisons applied to i1 and i2 use ordinary unbounded integer arithmetic." which of course is not the case for Soildity.
So you could either actually implement RFC1982 (incorporating bounded arithmetic in Solidity) or use a normal comparison.
#0 - Arachnid
2022-07-28T22:30:09Z
This is a bug - we should be using an unchecked block - but suggest that the severity is QA, since it doesn't apply until 2038 at the earliest and the contract is upgradeable.
#1 - Arachnid
2022-07-28T22:30:56Z
RE RFC1982, see my comment on #211.
#2 - dmvt
2022-08-04T21:09:35Z
Duplicate of #211
🌟 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
79.4817 USDC - $79.48
StablePriceOracle
(https://github.com/code-423n4/2022-07-ens/blob/04539b27307abd65068b96dd20fc686b451bf9fc/contracts/ethregistrar/StablePriceOracle.sol#L54), which seems unnecessary.setNameForAddr
(https://github.com/code-423n4/2022-07-ens/blob/04539b27307abd65068b96dd20fc686b451bf9fc/contracts/registry/ReverseRegistrar.sol#L124), it is mentioned that "First updates the resolver to the default reverse resolver if necessary.". However, this is not done, the user provided resolver address is used.safeBatchTransferFrom
(https://github.com/code-423n4/2022-07-ens/blob/04539b27307abd65068b96dd20fc686b451bf9fc/contracts/wrapper/ERC1155Fuse.sol#L209), if oldOwner == to
, the iteration could be skipped (like it is done for safeTransferFrom
).canCallSetSubnodeOwner
(https://github.com/code-423n4/2022-07-ens/blob/1772ac3d16c8e84bb9c1e02a0c4e321cd6f5652b/contracts/wrapper/NameWrapper.sol#L649) seems to be out of date, canReplaceSubdomain
does not exist / is not checked.🌟 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.8559 USDC - $39.86
unchecked
because no overflow is possible:
setUpgradeContract
, the variable _upgradeAddress
could be used for the three calls on line 139 - 141 (https://github.com/code-423n4/2022-07-ens/blob/1772ac3d16c8e84bb9c1e02a0c4e321cd6f5652b/contracts/wrapper/NameWrapper.sol#L139) instead of always reading upgradeContract
from memory.#0 - jefflau
2022-08-01T10:10:44Z
In setUpgradeContract, the variable _upgradeAddress could be used for the three calls on line 139 - 141 (https://github.com/code-423n4/2022-07-ens/blob/1772ac3d16c8e84bb9c1e02a0c4e321cd6f5652b/contracts/wrapper/NameWrapper.sol#L139) instead of always reading upgradeContract from memory.
It's reading from storage to get the value it currently is, not the value passed it, which is why the variables is underscored.