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’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reason strings for all require statements #1709

Closed
nventuro opened this issue Apr 5, 2019 · 9 comments
Closed

Reason strings for all require statements #1709

nventuro opened this issue Apr 5, 2019 · 9 comments
Labels
contracts Smart contract code. feature New contracts, functions, or helpers.
Milestone

Comments

@nventuro
Copy link
Contributor

nventuro commented Apr 5, 2019

Supersedes #888.

This is way overdue, but a big push during these last couple weeks for it took it to the point where we're now comfortable to include it in the library.

There was some discussion about formatting in our forum, which culminated in this post, which has some rough guidelines (pasting at the end of this message for reference).

I also did some testing and verified that we can safely add revert reasons to all of OpenZeppelin's contracts, without them going over the gas limit for a block. The situation may differ for setups with particularly large contracts, but most users should be unaffected. Nonetheless, I opened an issue on the Solidity repo suggesting they provide a way to remove these strings, so that they can be stripped for production builds, if desired.

Our goal is to have all require statements also include a human-readable revert reason, unique across all of OpenZeppelin. Contributions are welcome! Please also update the tests with the shouldFail.reverting.withMessage test helper, so that we can both be sure of the actual revert reason, and prevent regression errors by having these messages change.

Rough guidelines:

I think there's a fine line between machine-like messages and having bits of Shakespeare embedded in a smart contract. Some of 0x's messages are quite terse, but then again, in some cases the revert will take place deep down the stack (e.g. you'll get a SafeMath: subtraction overflow instead of ERC20: insufficient balance for transfer, or even LimitedCrowdsale: all tokens have been sold), and it'll be up to the developer to figure out how the call got there. As long as each message is unique in their contract, and they are descriptive enough so that one can get an idea of what the revert means (in the context of that contract) without looking at the code, we should be fine.

Here are some examples I think are aligned with this guideline:

  • SafeMath: multiplication overflow
  • SafeMath: division by zero
  • ERC20: null transfer recipient
  • ERC165: invalid interface id
  • MinterRole: caller doesn't have the Minter role
  • ConditionalEscrow: withdrawal disallowed
  • RefundEscrow: can only close when active
  • RefundEscrow: can only withdraw when closed
  • PaymentSplitter: caller has no shares
  • PaymentSplitter: empty payment

Note that some are a bit different (like the RefundEscrow ones) since they originate from a statement such as require(_state == State.Closed), in which the message cannot describe why the performed call is wrong since the state cannot be returned (e.g. cannot withdraw while active), so we must resort to simply reporting the conditions for a successful call.

@balajipachai
Copy link
Contributor

@nventuro I have started working on it :)

@princesinha19
Copy link
Contributor

@nventuro what about ERC721. I think it should be the same as ERC20: null transfer recipient

@princesinha19
Copy link
Contributor

@nventuro what about other requtire statement other than require(owner != address(0)). Like require(_exists(tokenId)) Should I write token doesn't exist?

balajipachai added a commit to balajipachai/openzeppelin-solidity that referenced this issue Apr 6, 2019
@nventuro
Copy link
Contributor Author

nventuro commented Apr 8, 2019

@nventuro what about other requtire statement other than require(owner != address(0)). Like require(_exists(tokenId)) Should I write token doesn't exist?

I think so, yes (unless we can also add token to transfer doesn't exist, for mint, transfer, burn`, etc.).

@frangio
Copy link
Contributor

frangio commented Apr 8, 2019

ERC20: null transfer recipient

I thought we had agreed not to use the word "null" for the zero address. It's a bit confusing because in the context of Ethereum transactions a null value in the to field has a special meaning (makes it a contract creation transaction).

@nventuro
Copy link
Contributor Author

nventuro commented Apr 9, 2019

zero-address transfer recipient? A bit of a mouthful.

@frangio
Copy link
Contributor

frangio commented Apr 9, 2019

What about just "zero" or "empty"?

@princesinha19
Copy link
Contributor

What about 'empty or zero transaction recipient'.

princesinha19 added a commit to princesinha19/openzeppelin-solidity that referenced this issue Apr 9, 2019
nventuro pushed a commit that referenced this issue Apr 24, 2019
* Error handling in ERC20 and ERC721

* Added message string for require.

* Fixed solhint errors.

* Updated PR as per issue #1709

* changes as per #1709 and openzeppelin forum.

* Changes in require statement

* Changes in require statement

* build pipeline fix

* Changes as per @nventuro's comment.

* Update revert reason strings.

* Fianal update of revert reason strings.

* WIP: Updating reason strings in test cases

* WIP: Added changes to ERC20 and ERC721

* Fixes linting errors in *.tes.js files

* Achieved 100% code coverage

* Updated the test cases with shouldFail.reverting.withMessage()

* Fix package-lock.

* address review comments

* fix linter issues

* fix remaining revert reasons
@nventuro
Copy link
Contributor Author

nventuro commented May 8, 2019

Closed via #1704.

@nventuro nventuro closed this as completed May 8, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
contracts Smart contract code. feature New contracts, functions, or helpers.
Projects
None yet
Development

No branches or pull requests

4 participants