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 ERC1363 implementation #4631

Merged
merged 96 commits into from
Jan 24, 2024
Merged

Conversation

vittominacori
Copy link
Contributor

@vittominacori vittominacori commented Sep 27, 2023

This PR adds the ERC1363 implementation following the v5 guidelines.

It uses inheritdoc whenever is possible and custom errors following the ERC-6093 rationale.

Would like to replace #3525 and #3017 as they are outdated.

Fixes: #3736
Fixes LIB-1181

PR Checklist

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

@changeset-bot
Copy link

changeset-bot bot commented Sep 27, 2023

🦋 Changeset detected

Latest commit: 2c85474

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
openzeppelin-solidity Minor

Not sure what this means? Click here to learn what changesets are.

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

@vittominacori vittominacori mentioned this pull request Sep 27, 2023
3 tasks
@zicoz18
Copy link

zicoz18 commented Sep 29, 2023

NOT DIRECTLY RELATED TO THE PR:

I have been looking at some standards such as ERC777 and ERC1363. ERC777 used to be included in OpenZeppelin contract and it got removed. I was wondering why such standards that extend ERC20 to be able to add a call to transfers or approvals is not highly adopted. Since they are backwards compatible, why not use them on new tokens? I am considering to use them but want to learn the reason why others are not using it. Maybe related to complexity, extra work for integrations, security reasons (possible reentrancy in on tokensReceived for ERC777 and onTransferReceived for ERC1363) or maybe UX reasons? Is there any sources that discuss the trade-offs?

@Amxx
Copy link
Collaborator

Amxx commented Sep 29, 2023

I was wondering why such standards that extend ERC20 to be able to add a call to transfers or approvals is not highly adopted

For ERC777:
Partly because its a pain to work with (smart contracts can't receive them without first registring in the 1822 registry) and because they are notoriously dangerous. ERC777 opens a lot of reentrancy paths that are dangerous if not properly considered.

@Amxx
Copy link
Collaborator

Amxx commented Sep 29, 2023

Is there any sources that discuss the trade-offs?

This one obviously comes to mind: #2620
There are probably many others

@zicoz18
Copy link

zicoz18 commented Sep 29, 2023

This one obviously comes to mind: #2620 There are probably many others

Thanks a lot for the answers 🙏

ernestognw
ernestognw previously approved these changes Jan 23, 2024
Copy link
Member

@ernestognw ernestognw left a comment

Choose a reason for hiding this comment

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

LGTM 🚀

ernestognw
ernestognw previously approved these changes Jan 23, 2024
@ernestognw ernestognw requested a review from Amxx January 23, 2024 18:02
@Amxx Amxx enabled auto-merge (squash) January 24, 2024 08:32
@Amxx Amxx merged commit e5f02bc into OpenZeppelin:master Jan 24, 2024
19 checks passed
@vittominacori
Copy link
Contributor Author

I missed why it is saying that target MUST implement the interface but only that target SHOULD return interface id.

It reverts if target returns something different than the interface id.

(also transferFromAndCall and approveAndCall)

* Requirements:
*
* - The target has code (i.e. is a contract).
* - The target `to` must implement the {IERC1363Receiver} interface.
* - The target should return the {IERC1363Receiver} interface id.
* - The internal {transfer} must succeed (returned `true`).
*/
function transferAndCall(address to, uint256 value) public returns (bool) {
return transferAndCall(to, value, "");
}

@Amxx Amxx mentioned this pull request Jan 24, 2024
3 tasks
@vittominacori
Copy link
Contributor Author

@Amxx @ernestognw I'm not sure about checking ERC20 methods return values.

The ERC1363 does not explicitly say that the ERC20 methods MUST succeed.

It says:

Defines a token interface for ERC-20 tokens that supports executing recipient code after transfer or transferFrom, or spender code after approve.

Below it says:

#notice Transfer tokens from msg.sender to another address and then call onTransferReceived on receiver

Maybe logically ok to force checking that the ERC20 methods returned true as it says "Transfer tokens..." but IMO it is not required.


Also regarding ERC1363 returning false, the spec says that methods:

#return true unless throwing

So it is unnecessary to test ERC1363 against returning false as it is out of the standard.

@ernestognw
Copy link
Member

ernestognw commented Jan 24, 2024

@Amxx @ernestognw I'm not sure about checking ERC20 methods return values.
The ERC1363 does not explicitly say that the ERC20 methods MUST succeed.

Yeah but also it doesn't mention they have to be treated as a noop. We concluded that it's more dangerous to allow a noop because an attacker can force a transfer failure and still call the target. This is misleading and may compromise the assumption that the caller is trusted (or always is called after a successful transfer).

I also believed it shouldn't be required, but we strive for the most secure implementation out of the box, and I do think this is it.

Also regarding ERC1363 returning false, the spec says that methods:

#return true unless throwing

So it is unnecessary to test ERC1363 against returning false as it is out of the standard.

Yeah. However, that's not the case for approveAndCall.
I agree we shouldn't guarantee compatibility with non-standard ERC1363, but this is also a design decision based on the likelihood of making a mistake (by returning false) and the inconsistency between the return param definitions.

I think I'd be open to changing this. It's unclear to me if there's a potential issue arising, but I think reverting is the safest. Compliant tokens will work perfectly using the SafeERC20 functions

Copy link

@Morhef Morhef left a comment

Choose a reason for hiding this comment

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

Morhef

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature New contracts, functions, or helpers. implementation-of-final-erc
Projects
None yet
Development

Successfully merging this pull request may close these issues.

EIP-1363 support
6 participants