ENS Contest - descharre's results

Decentralised naming for web3

General Information

Platform: Code4rena

Start Date: 14/04/2023

Pot Size: $90,500 USDC

Total HM: 7

Participants: 59

Period: 14 days

Judge: LSDan

Total Solo HM: 3

Id: 232

League: ETH

ENS

Findings Distribution

Researcher Performance

Rank: 27/59

Findings: 1

Award: $119.79

Gas:
grade-b

🌟 Selected for report: 0

🚀 Solo Findings: 0

Findings Information

🌟 Selected for report: JCN

Also found by: Sathish9098, d3e4, descharre, naman1778, niser93, openwide, saneryee

Labels

bug
G (Gas Optimization)
grade-b
G-04

Awards

119.7884 USDC - $119.79

External Links

Summary

IDFindingGas savedInstances
G-01Static array is cheaper than dynamic array1801
G-02Modifier onlyOwner can be more gas efficiënt87001
G-03Use shift left instead of multiplying281
G-04Only append once to buffer102
G-05next() can be made more gas efficiënt5321

Details

[G-01] Static array is cheaper than dynamic array

When the size of an array is known before hand it can be made static to save gas. In the resolve() function, the array has a length of 1. Around 180 gas can be saved with this optimization.

OffchainDNSResolver

L14:
error OffchainLookup(
    address sender,
-   string[] urls,
+   string[1] urls,
    bytes callData,
    bytes4 callbackFunction,
    bytes extraData
);

L49
    function resolve(
        bytes calldata name,
        bytes calldata data
    ) external view returns (bytes memory) {
-       string[] memory urls = new string[](1);
-       urls[0] = gatewayURL;
+       string[1] memory urls = [gatewayURL];

        revert OffchainLookup(
            address(this),
            urls,
            abi.encodeCall(IDNSGateway.resolve, (name, TYPE_TXT)),
            OffchainDNSResolver.resolveCallback.selector,
            abi.encode(name, data)
        );
    }

[G-02] Modifier onlyOwner can be more gas efficiënt

The onlyOwner modifier in DNSRegistrar always checks the owner of ens and root in the modifier itself. Assuming the owner rarely changes it's better to set the owner in the constructor and have an additional setter function for when it changes.

DNSRegistrar: 8700 gas can be saved for the functions that uses onlyOwner

L31:
+    address private owner;

L67: in constructor
+    Root root = Root(ens.owner(bytes32(0)));
+    owner = root.owner();

L73:
    modifier onlyOwner() {
-       Root root = Root(ens.owner(bytes32(0)));
-       address owner = root.owner();
        require(msg.sender == owner);
        _;
    }

Additional setter function
    function setOwner(){
        Root root = Root(ens.owner(bytes32(0)));
        owner = root.owner();
    }

[G-03] Use shift left instead of multiplying

You can use the bitwise left shift operator instead of multiplying when the number is a power of 2.

  1. Multiplying by 2: x << 1
  2. Multiplying by 4: x << 2
  3. Multiplying by 8: x << 3 And so on

This optimization can be used in the computeKeytag() function, instead of multiplying by 8 you can use shift left by 3. This will around 28 gas for the functions proveAndClaim() and proveAndClaimWithResolver().

-   uint256 unused = 256 - (data.length - i) * 8;
+   uint256 unused = 256 - ((data.length - i) << 3);

[G-04] Only append once to buffer

The buffer in DNSClaimChecker is appended twice. However if you use abi.encodepacked you can append once with the same result. Around 10 gas saved for the functions proveAndClaim() and proveAndClaimWithResolver()

        Buffer.buffer memory buf;
        buf.init(name.length + 5);
-       buf.append("\x04_ens");
-       buf.append(name);
+       buf.append(abi.encodePacked("\x04_ens", name));

Same optimization can be made at: DNSSECImpl.sol#L399-L400

[G-05] next() can be made more gas efficiënt

The next() function can be more gas optimized if you optimize the offsett. Gas will be saved on every iteration of a for loop that uses the next() function. For example in the tests the average gas saved is:

    function next(RRIterator memory iter) internal pure {
        iter.offset = iter.nextOffset;
        if (iter.offset >= iter.data.length) {
            return;
        }

        // Skip the name
        uint256 off = iter.offset + nameLength(iter.data, iter.offset);

        // Read type, class, and ttl
        iter.dnstype = iter.data.readUint16(off);
-       off += 2;
-       iter.class = iter.data.readUint16(off);
+       iter.class = iter.data.readUint16(off + 2);
-       off += 2;
-       iter.ttl = iter.data.readUint32(off);
+       iter.ttl = iter.data.readUint32(off + 4);
-       off += 4;

        // Read the rdata
-       uint256 rdataLength = iter.data.readUint16(off);
+       uint256 rdataLength = iter.data.readUint16(off + 8);
-       off += 2;
+       off += 10;
        iter.rdataOffset = off;
        iter.nextOffset = off + rdataLength;
    }

#0 - c4-judge

2023-05-08T15:38:28Z

dmvt marked the issue as grade-b

AuditHub

A portfolio for auditors, a security profile for protocols, a hub for web3 security.

Built bymalatrax © 2024

Auditors

Browse

Contests

Browse

Get in touch

ContactTwitter