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

feat: add wrapper function for low level calls #2264

Merged

Conversation

julianmrodri
Copy link
Contributor

@julianmrodri julianmrodri commented Jun 4, 2020

#2260

Fixes #2260

This PR creates a function Address.functionCall which can be used to wrap low level calls that need to be performed on other Smart contracts. .

It also modifies the ERC721.sol and SafeERC20.solcontracts to use this new function instead of performing directly the low level call. Tests for these contracts needed to be updated to match the new revert messages in certain situations.

contracts/utils/Address.sol Outdated Show resolved Hide resolved
@frangio
Copy link
Contributor

frangio commented Jun 4, 2020

This is looking great!

@julianmrodri
Copy link
Contributor Author

Thanks! I think I might need some guidance on the Tests to include. Which kind of calls should I mock? Do you have any preference on what contract to use and what samples to use for the Unit tests?

@nventuro
Copy link
Contributor

nventuro commented Jun 5, 2020

We might want to also add a value field for ETH transfers.

Thanks! I think I might need some guidance on the Tests to include.

Off the top of my head, interesting scenarios are the following (thought we might not need to test them all):

  • call to a contract that implements the called function and returns some data
  • call to a contract that implements the called function but reverts
  • call to a contract that implements the called function but runs out of gas
  • call to a contract that doesn't implement the function (and reverts)
  • call to a non-contract

If we add a value field, we might also want to test functions that are not payable.

@julianmrodri julianmrodri force-pushed the feature/call-wrapper-function-#2260 branch from 369f8b7 to dde2161 Compare June 8, 2020 01:46
@julianmrodri
Copy link
Contributor Author

@nventuro @frangio I've added the error message parameter so now we have the two options for functionCall (with or without the custom message). I also added some of the tests.

I would like you to review the TESTS to see if this is the correct direction. I had to make too many decisions and is better for you to validate if this is OK. Feel free to let me know if this is not the correct way of doing this!

So far I covered:

  • Call to a contract that implements the called function successfully
  • Call to a contract that implements the called function but reverts
  • Call to a contract that doesn't implement the function (and reverts)
  • Call to a non-contract

I was not able to test the case of a function that returns data with this approach. It is quite challenging as I get the Transaction info and not the returned value, to eventually decode. Do you know how this can be achieved? Thanks!

contracts/utils/Address.sol Outdated Show resolved Hide resolved
test/token/ERC20/SafeERC20.test.js Show resolved Hide resolved
contracts/mocks/AddressImpl.sol Outdated Show resolved Hide resolved
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.

The code itself looks good.

contracts/utils/Address.sol Outdated Show resolved Hide resolved
contracts/utils/Address.sol Outdated Show resolved Hide resolved
@nventuro
Copy link
Contributor

nventuro commented Jun 9, 2020

By the way I asked the Solidity dev team on gitter if they think our checks are correct, and they gave us green light:

nventuro
hello! I am trying to replicate Solidity function call semantics using call, and wanted to double-check >I'm not missing anything. This is what I'm currently doing:

check using extcodehash that the recipient account has code, revert otherwise
perform the call
if success, abi.decode the returndata
if failure, check the returndata for a revert reason (lenght > 0). if available, revert with that, >otherwise revert with a generic reason

Is that all?

chriseth
@nventuro looks good!

@nventuro
Copy link
Contributor

@julianmrodri we're looking into publishing the first release candidate of v3.1 today, and want to include this helper in that release. If you don't mind, I'll go ahead and continue working on this branch so we can merge this PR. I'm letting you know so we don't both end up working on the same thing :)

@julianmrodri
Copy link
Contributor Author

@nventuro Sure please go ahead! Sorry not to be able to complete it before, some work duties came up quite some busy days.

@nventuro nventuro marked this pull request as ready for review June 10, 2020 23:56
@nventuro nventuro requested a review from frangio June 10, 2020 23:57
@nventuro
Copy link
Contributor

@julianmrodri no need to apologize! Your help is greatly appreciated :)

@nventuro
Copy link
Contributor

@julianmrodri
Copy link
Contributor Author

Wow you took this to the next level. Awesome!

contracts/utils/Address.sol Outdated Show resolved Hide resolved
contracts/utils/Address.sol Outdated Show resolved Hide resolved
contracts/utils/Address.sol Show resolved Hide resolved
Co-authored-by: Francisco Giordano <[email protected]>
frangio
frangio previously approved these changes Jun 11, 2020
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.

Ship it!

@@ -233,9 +233,13 @@ describe('Address', function () {
inputs: [],
}, []);

const tracker = await balance.tracker(this.contractRecipient.address);
Copy link
Contributor

Choose a reason for hiding this comment

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

😍

@julianmrodri
Copy link
Contributor Author

Congrats guys! Awesome job. Glad to be able to be part of this. 👍

@nventuro
Copy link
Contributor

Thanks a lot to you both!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add a .call wrapper with Solidity function call checks
3 participants