question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. ItĀ collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

ERC777 operators should be internal not private

See original GitHub issue

🧐 Motivation

The current ERC777 code has a flaw that impacts security and usability.

Here is the code in question.

// This isn't ever read from - it's only used to respond to the defaultOperators query.
    address[] private _defaultOperatorsArray;

    // Immutable, but accounts may revoke them (tracked in __revokedDefaultOperators).
    mapping(address => bool) private _defaultOperators;

This design makes it impossible to extend the contract by adding or removing default operators and it appears that this is by design, but the thinking behind it is flawed and introduces a security problem.

šŸ“ Details

Operators especially default operators allow us to extend contracts in interesting and meaningful ways. However the use cases are limited because you either need to declare the operators upfront or convince the individual users to individually approve / reject operators on a case by case basis.

This is a safety issue as well. At present there is no way to blacklist an operator if it is later found to be misbehaving except for each user to reject them one by one.

Making _defaultOperatorsArray and mapping(address => bool) private _defaultOperators internal instead of private would allow for contracts which could add or remove default operators while still providing the user the ability to individually blacklist operators they do not want to interact with.

I realize the logic behind the current design is that users should not be forced to accept new default operators at any random time. Judging from the current design, the thinking appears to be that the users have the option to code review all operators prior to interacting with the ERC777 token.

Ostensibly that is true, but digging deeper it is easy to see many ways this could be abused.

The default operators list could be pre-populated at construction time with either addresses from the developer’s own wallet or contract addresses based on forward projecting future contract addresses using something like this https://ethereum.stackexchange.com/questions/24248/how-to-calculate-an-ethereum-contracts-address-during-its-creation-using-the-so

This moots the idea that the user would have complete information prior to interacting with an ERC777 contract and thus it is providing users with a false sense of security, while limiting actual security. This is because, the lack of ability to remove a default operator except on a user by user basis means that if an operator contract is found to be buggy or misbehaving one would need to expend a HUGE amount of effort to reach out to each user to individually blacklist said operator. A lot of damage could be done in the interim.

To wit, I would ask that rather than change the ERC777 standard, we make two small modifications to the existing ERC777.sol which allow contracts to extend ERC777 by simply taking these private vars and declaring them internal.

From there the contract creators can determine best how to add/remove and replace default operators and users will still maintain the ability to veto any operator they are uncomfortable with, but the devs can have an inbuilt process to deal with operators gone awry or adding new operators as opportunities to expand the use of the contract arise.

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Comments:6 (4 by maintainers)

github_iconTop GitHub Comments

1reaction
frangiocommented, Oct 16, 2019

probably wouldn’t even think to check beyond looking at the Etherscan abi front end.

I don’t see how this is a problem for ERC777s in particular, and not for ERC20s or any other contract. The same goes for vetting the bytecode of a contract: it’s already the case that only highly technical users can do it. And it’s already the case that some contracts may have external actors with superpowers, be it operators, minters, owners, etc., that those vetting a contract have to pay attention to.

I don’t agree with your points but I’d encourage you to bring it up in https://ethereum-magicians.org. I’m curious about other people’s opinions.

1reaction
frangiocommented, Oct 16, 2019

Hi @sshelton76. Thank you for your report.

We implemented default operators in this way because the ERC777 standard quite unambiguously says so:

The token MAY define default operators. A default operator is an implicitly authorized operator for all holders. AuthorizedOperator events MUST NOT be emitted when defining the default operators. The rules below apply to default operators:

  • The token contract MUST define default operators at creation time.
  • The default operators MUST be invariants. I.e., the token contract MUST NOT add or remove default operators ever.

Have you raised this concern with the authors of the standard?

I disagree with your following point though:

This moots the idea that the user would have complete information prior to interacting with an ERC777 contract and thus it is providing users with a false sense of security

Prior to interacting the user can definitely see that they have only partial information regarding default operators if any of them either have empty bytecode (except if they’ve selfdestructed) or even if the source code is not available. Based on this they can decide either not to interact with the token or to revoke these operators before doing so. I don’t see how any user can be particularly mislead here.

Let me know your thoughts.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Simple ERC777 token example - Guides and Tutorials
I created a simple ERC777 token inheriting from the OpenZeppelin ... smart contract merely sets a name, symbol and has no default operators....
Read more >
Deep Dive — OpenZeppelin's ERC777 Implementation |
Contract deployers may define default operators who can move tokens for all addresses. Notice that send is used in place of transfer andĀ ......
Read more >
How to build and use ERC-777 tokens - Solidity developer
Usually these have to be generated by a private key and the ecrecover function will retrieve ... With ERC-777 you also get functionality...
Read more >
ERC777: token recipient contract has no implementer for ...
ERC777 contract; Staking contract to hold ERC777 tokens. Then I can mint some ERC777 tokens to an user: await lpToken777.connect(owner).
Read more >
Solidity error message when executing smart contract
Can you please check my code and advise what was missed. // File: contracts\open-zeppelin-contracts\token\ERC777\ERC777.sol pragma solidity ^0.5Ā ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found