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

Add ERC2771Forwarder fuzz tests for avoiding loss of unused ETH #4396

Merged
merged 10 commits into from
Jul 8, 2023

Conversation

ernestognw
Copy link
Member

Complementary to #4346

PR Checklist

  • Tests
  • Documentation
  • Changeset entry (run npx changeset add)

@changeset-bot
Copy link

changeset-bot bot commented Jun 28, 2023

⚠️ No Changeset found

Latest commit: dc99416

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@ernestognw ernestognw marked this pull request as draft June 28, 2023 15:58
@ernestognw
Copy link
Member Author

Marking as draft until #4346 is merged

@ernestognw ernestognw requested review from frangio and Amxx June 29, 2023 16:42
Copy link
Collaborator

@Amxx Amxx left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left some minor comments, otherwise looks good.

ernestognw and others added 2 commits June 29, 2023 16:15
Co-authored-by: Hadrien Croubois <hadrien.croubois@gmail.com>
@ernestognw ernestognw requested a review from Amxx June 29, 2023 22:19
ERC2771Forwarder.t.js Outdated Show resolved Hide resolved
frangio and others added 3 commits June 30, 2023 11:31
Co-authored-by: Hadrien Croubois <hadrien.croubois@gmail.com>
Co-authored-by: ernestognw <ernestognw@gmail.com>
@ernestognw ernestognw requested a review from Amxx July 4, 2023 22:18
Comment on lines 95 to 114
function testExecuteAvoidsETHStuck(uint256 initialBalance, uint256 value) public {
vm.assume(initialBalance < _MAX_ETHER);
vm.assume(value < _MAX_ETHER);

vm.deal(address(_erc2771Forwarder), initialBalance);

uint256 nonce = _erc2771Forwarder.nonces(_signer);

vm.deal(address(this), value);
_erc2771Forwarder.execute{value: value}(
_forgeRequestData({
value: value,
nonce: nonce,
deadline: uint48(block.timestamp + 1),
data: abi.encodeCall(CallReceiverMock.mockFunction, ())
})
);

assertEq(address(_erc2771Forwarder).balance, initialBalance);
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This test is fuzzing the initialBalance and the value, but not the "paths" in the execute function. It only runs a function that we know is ok, with a deadline we know is ok, and a nonce we know is correct, with a fixed amount of gas

Ideally, we would want to consider many data, to check that whatever the outcome of the subcall, balances are preserved.

Maybe you could have a uint8 argument that is used to select one of "many" function. mockFunction will only be one of them. It should include: non payable functions, function that revert, function that panic, ...

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

or just do 50/50 between mockFunction and mockFunctionRevertsNoReason

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right, ideally, we would fuzz multiple functions. However, it becomes difficult to conditionally expect a revert in the test, so I did the 50/50 between mockFunction and mockFunctionRevertNoReason you proposed to cover both paths.

The deadline, nonce and gas are fixed because the contract is about making sure there's no value left in the contract and I don't think there's a way the deadline or nonce might affect that. However, gas may affect it because of the _checkForwardedGas but it's already proven in the comments.

I think the suggestion you proposed for this test is enough for its purpose (not leaving ETH stuck). I also tried to fuzz the gas very early in #4346 but it becomes messier because we have to conditionally expect reverts as well, and it's difficult to predict. Would appreciate if you have any idea how it may work in case you think it's a valuable addition

ernestognw and others added 2 commits July 5, 2023 11:34
Co-authored-by: Hadrien Croubois <hadrien.croubois@gmail.com>
Amxx
Amxx previously approved these changes Jul 5, 2023
Copy link
Contributor

@frangio frangio left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good but I have one comment.

test/metatx/ERC2771Forwarder.t.sol Outdated Show resolved Hide resolved
@frangio frangio merged commit f5bf723 into OpenZeppelin:master Jul 8, 2023
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants