Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Actionable List] Replace revert strings with custom errors #3614

Closed
3 tasks
Amxx opened this issue Aug 12, 2022 · 11 comments
Closed
3 tasks

[Actionable List] Replace revert strings with custom errors #3614

Amxx opened this issue Aug 12, 2022 · 11 comments

Comments

@Amxx
Copy link
Collaborator

Amxx commented Aug 12, 2022

馃 Motivation

Custom Errors, which were introduced in 0.8.4, contribute to reduce the contract size and improve clarity of revert reasons.

A quick study shows that replacing a (short) revert string with a custom error can save 8.5k gas, and slightly decrease the run cost.

error SomeError();
error SomeErrorWithArgs(address);

contract A { function test() external { revert("some short message"); } }
// deploy: 90599
// run: 21288

contract B { function test() external { revert("some long message that will cause deployment to be more expensive, but hopefully not execution"); } }
// deploy: 109401
// run: 21318

contract C { function test() external { revert SomeError(); } }
// deploy: 81953
// run: 21228

contract D { function test() external { revert SomeErrorWithArgs(msg.sender); } }
// deploy: 83225
// run: 21245

馃摑 Next steps

There are some question to resolve before moving forward with that change:

  • Check/validate custom error support by developer tools (hardhat + truffle / hardhat + waffle, etherscan, ...)
    • Adapt our tests if needed
  • List all revert string, and decide what custom error to use for each one
    • some custom errors might be reusable between contracts (ex: InsufficientBalance for ERCs 20, 777, 1155)
    • decide which parameter (if any) to include in the custom error
  • Decide where to define the errors
    • In each file: makes re-use difficult
    • In a global file: messy
    • Other?

See

@Amxx Amxx added this to the 5.0 milestone Aug 12, 2022
@Amxx
Copy link
Collaborator Author

Amxx commented Aug 15, 2022

#2839

@Amxx Amxx changed the title Replace revert strings with custom errors [TODO List] Replace revert strings with custom errors Aug 15, 2022
@Amxx Amxx changed the title [TODO List] Replace revert strings with custom errors [Actionnable List] Replace revert strings with custom errors Aug 15, 2022
@akhil-is-watching
Copy link

Hi I'd really like to take up this issue.

@Amxx
Copy link
Collaborator Author

Amxx commented Aug 16, 2022

Thank you @akhil-is-watching, but I think the next steps for now are mostly internal discussion with the team. While let everyone know on the issue if we can use any help.

@frangio frangio changed the title [Actionnable List] Replace revert strings with custom errors [Actionable List] Replace revert strings with custom errors Aug 17, 2022
@wiasliaw
Copy link
Contributor

There are two testing development tools had supported the custom error.

I recommend hardhat-chai-matchers. it provide better readability.

// hardhat-chai-matchers
await expect(contract.call()).to.be.revertedWithCustomError(
  contract,
  "SomeCustomError"
);

but waffle provider a matcher combined reason string and custom error

// waffle
// reason string
await expect(token.checkRole('ADMIN'))
  .to.be.revertedWith(/AccessControl: account .* is missing role .*/);

// custom error
await expect(token.transfer(receiver, 100))
    .to.be.revertedWith('InsufficientBalance')
    .withArgs(0, 100);

@Amxx
Copy link
Collaborator Author

Amxx commented Oct 17, 2022

I like waffle's "withArgs" (its the same for events)

@wiasliaw
Copy link
Contributor

@Amxx Hardhat supports withArgs too.

await expect(contract.call())
  .to.be.revertedWithCustomError(contract, "SomeCustomError")
  .withArgs(anyValue, "some error data string");

@frangio
Copy link
Contributor

frangio commented Oct 25, 2022

hardhat-chai-matchers should be preferred over Waffle nowadays.

@ItsShadowl
Copy link

hardhat-chai-matchers should be preferred over Waffle nowadays.

I believe both supports Custom Errors, and the implementation can be tested with either.

We use Custom Error all over our codebase where possible. It is lighter.

@ernestognw
Copy link
Member

Closing in favor of #2839 since there's more activity and attention over there

@ernestognw ernestognw removed this from the 5.0 milestone May 16, 2023
@radeksvarz
Copy link

There are two testing development tools had supported the custom error.

I recommend hardhat-chai-matchers. it provide better readability.

// hardhat-chai-matchers
await expect(contract.call()).to.be.revertedWithCustomError(
  contract,
  "SomeCustomError"
);

but waffle provider a matcher combined reason string and custom error

// waffle
// reason string
await expect(token.checkRole('ADMIN'))
  .to.be.revertedWith(/AccessControl: account .* is missing role .*/);

// custom error
await expect(token.transfer(receiver, 100))
    .to.be.revertedWith('InsufficientBalance')
    .withArgs(0, 100);

Foundry can be also included on the list with vm.expectRevert(CustomError.selector);

@Amxx
Copy link
Collaborator Author

Amxx commented May 16, 2023

@radeksvarz

Our tests are written in JS for many reasons (including ensuring compatibility with libraries frequently used by frontends). We are not going to migrate everything to foundry. That would require a tremendous effort, and the added value to our end users is debatable.

We do use foundry to fusing though.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants