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

Fix/improve revert reason #1727 #2018

Merged
merged 24 commits into from
Jan 23, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
839b6bf
adding mock contacts, test code
alant Dec 8, 2019
bcb3125
adding changes to ERC721.sol per @frangio's comments on original PR #…
alant Dec 8, 2019
2ee16ec
fix solhint warnings
alant Dec 8, 2019
027822d
Update contracts/token/ERC721/ERC721.sol
alant Dec 10, 2019
07dcbd3
same revert wording per @frangio's review suggestion
alant Dec 10, 2019
1755395
Merge branch 'fix/improve-revert-reason-#1727' of https://github.com/…
alant Dec 10, 2019
be4d51d
per @frangio's feedback, changing the inline assembly to accomplish: …
alant Dec 10, 2019
f0a90f6
change revert msg assembly per PR comment by @frangio
alant Dec 11, 2019
ab1fb60
unify revert msg in test code
alant Dec 11, 2019
59cba42
Merge branch 'master' into fix/improve-revert-reason-#1727
alant Dec 11, 2019
cd436a6
fix some failed tests, wording change
alant Dec 12, 2019
ee84cda
Update contracts/token/ERC721/ERC721.sol
alant Dec 13, 2019
829032d
Update contracts/token/ERC721/ERC721.sol
alant Dec 13, 2019
f5a6a95
Merge branch 'fix/improve-revert-reason-#1727' of https://github.com/…
alant Dec 13, 2019
1162b59
fix test case, revert without reason
alant Dec 24, 2019
6aec945
fix 'ERC721ReceiverRevertsMock: Transaction rejected by receiver'
alant Jan 7, 2020
604f88b
Merge branch 'master' into fix/improve-revert-reason-#1727
alant Jan 7, 2020
9668a49
style change per review by @frangio
alant Jan 14, 2020
cf5c2b8
Merge branch 'fix/improve-revert-reason-#1727' of https://github.com/…
alant Jan 14, 2020
f279bec
fix revert reason forwarding
frangio Jan 14, 2020
6f33362
remove duplicate contracts/mocks/ERC721ReceiverRevertsMock.sol per re…
alant Jan 15, 2020
4c2930d
Add changelog entry
nventuro Jan 23, 2020
2538e97
Fix tests
nventuro Jan 23, 2020
f3e382a
Make tests more clear
nventuro Jan 23, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
### Improvements
* `ERC777`: `_burn` is now internal, providing more flexibility and making it easier to create tokens that deflate. ([#1908](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/1908))
* `ReentrancyGuard`: greatly improved gas efficiency by using the net gas metering mechanism introduced in the Istanbul hardfork. ([#1992](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/1992), [#1996](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/1996))
* `ERC721`: improved revert reason when transferring tokens to a non-recipient contract. ([#2018](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2018))

### Breaking changes
* `ERC165Checker` now requires a minimum Solidity compiler version of 0.5.10. ([#1829](https://github.com/OpenZeppelin/openzeppelin-solidity/pull/1829))
Expand Down
25 changes: 22 additions & 3 deletions contracts/token/ERC721/ERC721.sol
Original file line number Diff line number Diff line change
Expand Up @@ -330,9 +330,28 @@ contract ERC721 is Context, ERC165, IERC721 {
if (!to.isContract()) {
return true;
}

bytes4 retval = IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, _data);
return (retval == _ERC721_RECEIVED);
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory returndata) = to.call(abi.encodeWithSelector(
IERC721Receiver(to).onERC721Received.selector,
_msgSender(),
from,
tokenId,
_data
));
if (!success) {
if (returndata.length > 0) {
// solhint-disable-next-line no-inline-assembly
assembly {
alant marked this conversation as resolved.
Show resolved Hide resolved
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert("ERC721: transfer to non ERC721Receiver implementer");
}
} else {
bytes4 retval = abi.decode(returndata, (bytes4));
return (retval == _ERC721_RECEIVED);
}
}

/**
Expand Down
24 changes: 13 additions & 11 deletions test/token/ERC721/ERC721.behavior.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ const { expect } = require('chai');
const { ZERO_ADDRESS } = constants;
const { shouldSupportInterfaces } = require('../../introspection/SupportsInterface.behavior');

const ERC721ReceiverMock = contract.fromArtifact('ERC721ReceiverMock');
const ERC721Mock = contract.fromArtifact('ERC721Mock');
const ERC721ReceiverMock = contract.fromArtifact('ERC721ReceiverMock');

function shouldBehaveLikeERC721 (
creator,
Expand Down Expand Up @@ -307,19 +307,20 @@ function shouldBehaveLikeERC721 (

describe('to a receiver contract that throws', function () {
it('reverts', async function () {
const invalidReceiver = await ERC721ReceiverMock.new(RECEIVER_MAGIC_VALUE, true);
const revertingReceiver = await ERC721ReceiverMock.new(RECEIVER_MAGIC_VALUE, true);
await expectRevert(
this.token.safeTransferFrom(owner, invalidReceiver.address, tokenId, { from: owner }),
this.token.safeTransferFrom(owner, revertingReceiver.address, tokenId, { from: owner }),
'ERC721ReceiverMock: reverting'
);
});
});

describe('to a contract that does not implement the required function', function () {
it('reverts', async function () {
const invalidReceiver = this.token;
await expectRevert.unspecified(
this.token.safeTransferFrom(owner, invalidReceiver.address, tokenId, { from: owner })
const nonReceiver = this.token;
await expectRevert(
this.token.safeTransferFrom(owner, nonReceiver.address, tokenId, { from: owner }),
'ERC721: transfer to non ERC721Receiver implementer'
);
});
});
Expand Down Expand Up @@ -369,19 +370,20 @@ function shouldBehaveLikeERC721 (

context('to a receiver contract that throws', function () {
it('reverts', async function () {
const invalidReceiver = await ERC721ReceiverMock.new(RECEIVER_MAGIC_VALUE, true);
const revertingReceiver = await ERC721ReceiverMock.new(RECEIVER_MAGIC_VALUE, true);
await expectRevert(
this.ERC721Mock.safeMint(invalidReceiver.address, tokenId),
this.ERC721Mock.safeMint(revertingReceiver.address, tokenId),
'ERC721ReceiverMock: reverting'
);
});
});

context('to a contract that does not implement the required function', function () {
it('reverts', async function () {
const invalidReceiver = this.token;
await expectRevert.unspecified(
this.ERC721Mock.safeMint(invalidReceiver.address, tokenId)
const nonReceiver = this.token;
await expectRevert(
this.ERC721Mock.safeMint(nonReceiver.address, tokenId),
'ERC721: transfer to non ERC721Receiver implementer'
);
});
});
Expand Down