Skip to content

Gas optimization, Flexible code #427

@abhi3700

Description

@abhi3700

Background

In this line:

require((owner = _ownerOf[id]) != address(0), "NOT_MINTED");

require(owner != address(0), "ZERO_ADDRESS");

although they are view functions, it's cheaper to simply return _ownerOf[id] & _balanceOf[owner]. Also, it's more developer-friendly or flexible I think.
Like in this test code:

/// address who owns the nft token id, can only burn
function testBurnWorks() public {
    vm.expectEmit(true, true, true, true);
    emit Burned(ALICE, 1);
    vm.prank(ALICE);
    myNFT.burn(1);
    // assertEq(myNFT.ownerOf(1), address(0));
}

I could call simply ownerOf function after burning NFT to verify. Otherwise, i have to use new_balance - old_balance.

Analysis

ownerOf

The current code costs 622 gas:

 ├─ [622] MyNFT::ownerOf(2) [staticcall]
    │   └─ ← [Return] ECRecover: [0x0000000000000000000000000000000000000001]

Modifying the code with:

- require((owner = _ownerOf[id]) != address(0), "NOT_MINTED");
+ return _ownerOf[id];

Function code (NEW):

function ownerOf(uint256 id) public view virtual returns (address) {
    return _ownerOf[id];
}

The new code would cost 588 gas:

├─ [588] MyNFT::ownerOf(2) [staticcall]
    │   └─ ← [Return] ECRecover: [0x0000000000000000000000000000000000000001]

balanceOf

Same reasoning in balanceOf function with new function code:

function balanceOf(address owner) public view virtual returns (uint256) {
    return _balanceOf[owner];
}
├─ [634] MyNFT::balanceOf(ECRecover: [0x0000000000000000000000000000000000000001]) [staticcall]
    │   └─ ← [Return] 4
├─ [582] MyNFT::balanceOf(ECRecover: [0x0000000000000000000000000000000000000001]) [staticcall]
    │   └─ ← [Return] 4
    └─ ← [Stop]

Summary

  • In ownerOf function, we can save by 52 gas per call.
  • In balanceOf function, we can save by 34 gas per call.
  • Also, the code becomes more developer friendly or flexible.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions