Reason strings for all require statements
See original GitHub issueSupersedes #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 ofERC20: insufficient balance for transfer
, or evenLimitedCrowdsale: 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 asrequire(_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.
Issue Analytics
- State:
- Created 4 years ago
- Comments:9 (9 by maintainers)
What about just “zero” or “empty”?
Closed via https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1704.