-
Notifications
You must be signed in to change notification settings - Fork 11.9k
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
Issue #1727: Improve revert reason when assuming interface compliance contracts. #1943
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you @NoopurShinde! Sorry for the delay.
package.json
Outdated
@@ -53,9 +53,9 @@ | |||
"eslint-config-standard": "^11.0.0", | |||
"eslint-plugin-import": "^2.18.2", | |||
"eslint-plugin-mocha-no-only": "^1.1.0", | |||
"eslint-plugin-node": "^5.2.1", | |||
"eslint-plugin-node": "^10.0.0", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you please undo the changes in package.json
? We prefer to have PRs that focus on separate issues.
return (retval == _ERC721_RECEIVED); | ||
bytes memory payload = abi.encodeWithSignature( | ||
"onERC721Received(address,address,uint256,bytes)", | ||
msg.sender, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please use _msgSender()
instead, for compatibility with Context
. This is used for integration with the GSN.
msg.sender, | |
_msgSender(), |
bytes memory payload = abi.encodeWithSignature( | ||
"onERC721Received(address,address,uint256,bytes)", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please use abi.encodeWithSelector
with IERC721Receiver(to).onERC721Received.selector
as the first argument. This ensures that we don't mess up the string constant.
|
||
contract ERC721ReceiverNotImplementedMock{ | ||
bytes4 private _retval; | ||
bool private _reverts; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please remove these two variables since they're not used.
function onERC721Received(address operator, address from, uint256 tokenId, bytes memory data) | ||
public returns (bytes4) | ||
{ | ||
require(!_reverts, "ERC721ReceiverMock: Transaction rejected by receiver"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
require(!_reverts, "ERC721ReceiverMock: Transaction rejected by receiver"); | |
require(!_reverts, "ERC721ReceiverRevertsMock: Transaction rejected by receiver"); |
(bool success, bytes memory returndata) = to.call(payload); | ||
if (!success) { | ||
if (returndata.length > 0){ | ||
revert(string(returndata)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From reading the Solidity documentation, it seems that both revert
and require
abi-encode their arguments as if they were a call to an Error(string)
function.
If I understand correctly, this means that we're "wrapping" the revert reason twice, since returndata
is already encoded here. I think we have to drop to assembly and use the revert
opcode directly to avoid this re-encoding and to bubble up the value as-is.
Let me know if this was clear @NoopurShinde.
if (!success) { | ||
if (returndata.length > 0){ | ||
revert(string(returndata)); | ||
}else | ||
revert("ERC721: to address does not implement ERC721Received interface"); | ||
} else {return true;} | ||
// bytes4 retval = IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, _data); | ||
// return (retval == _ERC721_RECEIVED); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please tidy up the whitespace here to conform to our usual style and remove the commented out lines. 🙂
Hi all! |
Hi all! |
Hi folks! |
* adding mock contacts, test code * adding changes to ERC721.sol per @frangio's comments on original PR #1943 * fix solhint warnings * Update contracts/token/ERC721/ERC721.sol Co-Authored-By: Francisco Giordano <frangio.1@gmail.com> * same revert wording per @frangio's review suggestion * per @frangio's feedback, changing the inline assembly to accomplish: we want to ignore the first 4 bytes of content, so we should read the length and decrease it by 4, then take the memory location and add 4 to it, then store the new length at the new memory location, then that is the new byte array that we want. * change revert msg assembly per PR comment by @frangio * unify revert msg in test code * fix some failed tests, wording change * Update contracts/token/ERC721/ERC721.sol Co-Authored-By: Francisco Giordano <frangio.1@gmail.com> * Update contracts/token/ERC721/ERC721.sol Co-Authored-By: Francisco Giordano <frangio.1@gmail.com> * fix test case, revert without reason * fix 'ERC721ReceiverRevertsMock: Transaction rejected by receiver' * style change per review by @frangio * fix revert reason forwarding * remove duplicate contracts/mocks/ERC721ReceiverRevertsMock.sol per review https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2018\#issuecomment-574381034 * Add changelog entry * Fix tests * Make tests more clear Co-authored-by: Francisco Giordano <frangio.1@gmail.com> Co-authored-by: Nicolás Venturo <nicolas.venturo@gmail.com>
* adding mock contacts, test code * adding changes to ERC721.sol per @frangio's comments on original PR OpenZeppelin#1943 * fix solhint warnings * Update contracts/token/ERC721/ERC721.sol Co-Authored-By: Francisco Giordano <frangio.1@gmail.com> * same revert wording per @frangio's review suggestion * per @frangio's feedback, changing the inline assembly to accomplish: we want to ignore the first 4 bytes of content, so we should read the length and decrease it by 4, then take the memory location and add 4 to it, then store the new length at the new memory location, then that is the new byte array that we want. * change revert msg assembly per PR comment by @frangio * unify revert msg in test code * fix some failed tests, wording change * Update contracts/token/ERC721/ERC721.sol Co-Authored-By: Francisco Giordano <frangio.1@gmail.com> * Update contracts/token/ERC721/ERC721.sol Co-Authored-By: Francisco Giordano <frangio.1@gmail.com> * fix test case, revert without reason * fix 'ERC721ReceiverRevertsMock: Transaction rejected by receiver' * style change per review by @frangio * fix revert reason forwarding * remove duplicate contracts/mocks/ERC721ReceiverRevertsMock.sol per review https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2018\#issuecomment-574381034 * Add changelog entry * Fix tests * Make tests more clear Co-authored-by: Francisco Giordano <frangio.1@gmail.com> Co-authored-by: Nicolás Venturo <nicolas.venturo@gmail.com>
Solved issue Improve revert reason when assuming interface compliance #1727: Improve revert reason when assuming interface compliance contracts.
Fixes
Added the below code in ERC721.sol
Added 2 dummy contracts in /contracts/mocks; one which does not implement ERC721Received and one which implements it but reverts as the contract rejects the transaction.
Updated the test cases in ERC721.behavior.js to test the code added in ERC721.sol