-
Notifications
You must be signed in to change notification settings - Fork 5.3k
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
EIP 820: Pseudo-introspection using a registry contract. #820
Comments
I was a fan of EIP-672 (with the minor changes I made to preserve normal reverse resolution), but I really like this, it's a lot simpler. I wonder if The above (at least for the manager role) could be abstracted away into the registry, so that |
Should there be a standard, or at least a recommendation, for interface names? The example interface name Stating that interface names should be lower-case, and those that come from an EIP should be of the format eipx e.g. |
I am working on the competing ERC-165. We are suffering from one very specific problem: how to deal with these crazy DELEGATECALL contracts that may implement an interface today and stop implementing tomorrow. This EIP certainly is a solution to that. |
I don't understand your deployment strategy to a specified address. Is this already documented, could you please link to that. |
@fulldecent There's some source code linked here: |
There is no need to choose a special name for the manager's interface. Simply set the hash directly. function managerHash() public pure returns(bytes32) {
return 0xffffffff;
} Here is an implementation passing all test cases: jbaylina/ERC820#3 (MY FORK DOES NOT UPDATE THE README AND NEW CONTRACT HASH, IMPORTANT STEPS INDEED.) |
Now here's a crazy idea. What if 165 did the same thing is this but just removed the |
@hyperfekt Thank you, and is there anything more that explains the calculations? |
Pinging @Arachnid, since he came up with that technique. |
Proposal for naming interfaces. Interface nameYour interface name is hashed and sent to If it's an approved EIPThe interface is named like If it's part of an approved EIPThe interface is named like If it's a draft EIP / on standards trackThe interface is named Part of a draft? Somebody posted a draft interface in a GitHub commentRemember, comments are editable (retaining the same URL) and history is not retained. To be clear, EIP-820 doesn't help you much, you're really just playing around at this point. Name it like Part of a comment? A functionYou want to advertise support for an external Solidity function, but the details of the function are unspecified. The interface is named like Something elseThis scheme is extensible. If you want to make up your own interface name and raise awareness to get other people to implement it and then check for those implementations, great! Have fun, but please do not conflict with the reserved designations above. |
What happens if I make a token contract, and then maliciously set the erc20 implementer to the Golem token contract. Will contracts using my token now unexpectedly call |
@fulldecent Regarding the name, i like the interfaces to have readable names: erc20-Token |
@fulldecent Updated the proposal with your proposed changes without the drafts... |
@recmo The manager of the golemContract would be the only one to change the implementation for his address. And in the case of the token interface, this does not apply. |
The issue regarding drafts is, for example with 721, there are now 7+ unversioned and incompatible interfaces for ERC-721. If cryptokitties launched with "I support 721" then somebody using 721 interefaces will be disappointed when CK doesn't do it the way that is standardized. |
@jbaylina Let me illustrate the security issue with a more explicit example. Consider the following hypothetical exchange that contract SomeExchange is EIP820 {
function settleTokens(address token, address from, address to, uint amount)
internal
{
ERC20 erc20 = ERC20(interfaceAddr(token, "erc20-Token"));
erc20.transferFrom(from, to, ammount);
}
} This is how EIP820 is intended to be used, correct? We will attack this exchange. First, I deploy a reasonable token contract that implements EIP820: contract ReasonableToken is Ownable, ERC20, EIP820 {
function ReasonableToken()
public
{
setInterfaceImplementation("erc20-Token", this);
delegateManagement(owner());
}
// ...
} Looks reasonable, right? Now I get people to trade this token on the exchange. When the conditions are right, I make the following transaction (pseudo-code): const reasonableToken = ReasonableToken(0x0123.....);
const zrxToken = ERC20(0xe41d2489571d322189246dafa5ebde1f4699f498);
const iir = InterfaceImplementationRegistry(0xa80366843213DFBE44307c7c4Ce4BcfC7A6437E5);
iir.setInterfaceImplementer(reasonableToken, keccak256("erc20-Token"), zrxToken); This transaction succeed, because I'm a manager of the ReasonableToken interfaces. After this, all settlements that where supposed to be made in ReasonableToken, are now made in ZRXToken! I set things up right, and now receive valuable ZRX token from people thinking they are selling me cheaper ReasonableToken. The use of ERC20 is just an example, this would work on any interface. This works, because in Note that my use of delegation/manager was only to obscure the attack a bit more. A similar attack can be done without it. How to fix it: contract EIP820Implementer {
function implementsFor() public returns (address);
} function setInterfaceImplementer(address addr, bytes32 iHash, address implementer) public canManage(addr) {
require(EIP820Implementer(implementer).implementsFor() == addr);
interfaces[addr][iHash] = implementer;
InterfaceImplementerSet(addr, iHash, implementer);
} For extra safety it should also verify that it intends to implement the requested interface. Alternative: |
Ah... no. There is no contract that needs to inherit from ERC-820. ERC-820 is not an interface. It is just a specific contract on the blockchain. |
@fulldecent I'm using EIP820.sol, which to me looks like it's intended to be inherited from. (I think you might confuse it with InterfaceImplementationRegistry.sol, which is the singleton registery that has its address hardcoded in the EIP820.sol. The naming is a bit unfortunate.). I can rewrite the attack to work without inheritance, if you like. (I also updated my previous comment to be a bit more clear about this). |
Yes, the attack is valid. Good fix. |
@recmo @fulldecent Updated the proposal with your suggestion. Please review. |
https://github.com/jbaylina/eip820/blob/master/contracts/ExampleImplementer.sol#L5
If I unlock the fallback function and provide some default behavior, then it would break those checks because of strange behavior by design in solidity if a method does not exist it will instead execute the fallback function, and if the fallback function does not raise an exception it will return 1 causing the check to pass. The only solution that comes to my mind is to use some magic numbers. Maybe we should return uint which should be more than 0. |
@rstormsf I have heard this before too, but do you know of the canonical source which explains this further. I would just like to double check before we go thinking we solved the problem. contract ExampleImplementer {
function canImplementInterfaceForAddress(address addr, bytes32 interfaceHash) view public returns(uint8) {
return 42;
}
} |
@fulldecent @rstormsf Just added compatibility with EIP165 and the magic return. Please review. |
@jacquesd The PR is jbaylina/ERC820#18 on the ERC820 repo. |
@fulldecent thanks, during a final reading of the standard I noticed some comments were inaccurate. I updated them both in the ERC820 and the EIPs repo and this means the address and IV changed again. Unfortunately there seems to be an issue with the EIPs bot not merging my changes. 🙁 I'm also happy to extend the last call by a couple days to compensate for the technical issues and the give you time to look at those comments. Hopefully, this should take very little time as it's just a few comments, the bulk of the changes is updating the address and deployment transaction (whose bytecode is the same, only the metadata hash changes). |
Damn, I couldn't get one commit in there, could I... Can you please confirm:
|
This has passed the last call review date as per https://github.com/ethereum/EIPs/blob/master/EIPS/eip-820.md - can this now be moved to final? |
@fulldecent I can confirm that:
But don't trust, verify (again). I'm sorry about the commit, however any commit you can put there is appreciated. I think a lot of the code around the registry can be cleaned up and improved. If you want, (or anyone really, jbaylina/ERC777AcceptAny is also in need of an update (see with @jbaylina for details). @mcdee thanks for your comment. The date |
The review end date has passed without further changes, comments or suggestion. Hence I would like to move 820 to a final status. For this I would need some assistance for @Arachnid or @Souptacular to merge #1612. I'd also like to thank everyone who contributed and helped with ERC820, (including in no particular order): @fulldecent @mcdee @jaycenhorton @recmo @hyperfekt @wighawag @thegostep @Arachnid @Souptacular and everyone I forget. |
@jacquesd 0xjac, thanks a lot. Are all merges done ? could you move 820 to final status or did you find improvements ? Warm regards |
@BlueRoss No, I did not find improvements and I did not get further feedback. I was silent for the last 2 weeks for personal reasons but I am now allocating some time again to finalize this. There is already a PR to finalize 820 at #1612. I will answer @Arachnid last comment which I missed and update the PR. |
This last call ends in two days. C'mon people, nothing to say? |
@fulldecent apparently not... Maybe everything was said during the previous last calls. In any case, since there are no changes and the last call period has ended. I would like to move ERC820 to Final. Please see #1677. |
I was trying to use this with Solidity 0.5, and discovered what may be an incompatibility between the EIP165-compatible code here and the new Solidity compiler. |
ABORT. Confirming that we should update this. There is a PR open on ERC-165 that we should accept. I lost the link and still searching for it. |
@fulldecent It's talking about this bug #1640 In short, the Solidity >= 5 compiler forces all methods to validate that the input is valid (4 bytes + N Parameters * 32 bytes).
That call would never make a success when interacting with a contract compiled with Solidity >= 5, because there is no way of declaring a method that accepts an input of 8 bytes. Replacing the call with an input of 36 bytes would fix the bug. |
Now that the EIP has been updated to |
@thorvald @Agusx1211 thank you for spotting and explaining that. It is indeed a bit late but it is nonetheless important. To avoid confusion the following procedure will be followed:
@thorvald @Agusx1211 @fulldecent (and anyone else who is interested, maybe @mcdee?) I would kindly ask you to take a look at the changes to the registry. You can have a look online, or in case that link does not work, the two files are:
I will start the procedure and update the EIPS this weekend. Any feedback is appreciated. @alsco77 The address at https://github.com/jbaylina/ERC820 the final one for ERC820, however from what is mentioned above, ERC820 will be superseded by ERC820a and the address will change. |
Thank you for moving this along. Can you please paste a new diff link, that one is broken. I don't know if Regarding the process, yes, looks great. I would recommend a few days buffer for 777. Just because I have seen some EIPs leave "two week review" slightly after two weeks. In the future I might advocate against dependent EIPs running last call in parallel. But this instance seems to be particularly lower risk. |
If the altered contract is going to have a different designation I'd rather it had its own number than a suffix. |
I'm happy with a new number too. I see little mention of 820 in the wild and using a new number is not likely to lead to confusion. Now, 777, that number is more important and it is unaffected by this change. |
@fulldecent The diff link has been updated and you can find it here too. Hopefully it should work this time... For the ERC777 last call there will be a buffer. I don't know of how much, that depends on how fast I can wrap up ERC777. But my comment was merely there to indicate that it will not take 2 weeks for ERC820 and another 2 weeks after for ERC777 but the last calls will be partially stacked. @fulldecent @mcdee Regarding the 820a number, I disagree with a change of number. First we are not creating a new EIP, just fixing an incompatibility introduced by Solidity. Some people actually have been talking (at least to me) about 820. Having two EIPS numbers might be confusing as to where to look and which one to use. Secondly, changing the number means quite a few changes across the EIP text and the code base for no gain other than having a new number. As @fulldecent mentioned we are moving this along and changing the number gain now everywhere will add days of work. |
Now that Constantinople is happening, is there any appetite to change the 820 deployment mechanism to the more robust eip-1014 format? |
There has been no activity on this issue for two months. It will be closed in a week if no further activity occurs. If you would like to move this EIP forward, please respond to any outstanding feedback or add a comment indicating that you have addressed all required feedback and are ready for a review. |
This issue was closed due to inactivity. If you are still pursuing it, feel free to reopen it and respond to any feedback or request a review in a comment. |
Please, see: https://github.com/ethereum/EIPs/blob/master/EIPS/eip-820.md for further discussion.
Preamble
Simple Summary
This standard defines a universal registry smart contract where any address (contract or regular account) can register which interface it implements and which smart contract is responsible for its implementation.
This standard keeps backwards compatibility with EIP-165
Abstract
This standard attempts to define a registry where smart contracts and regular accounts can publish which functionalities they implement.
The rest of the world can query this registry to ask if a specific address implements a given interface and which smart contract handles its implementation.
This registry can be deployed on any chain and will share the exact same address.
Interfaces where the last 28 bytes are
0
are considered EIP-165 interfaces, and this registrywill forward the call to the contract to see if they implement that interface.
This contract will act also as an EIP-165 cache in order to safe gas.
Motivation
There has been different approaches to define pseudo-introspection in the Ethereum. The first is EIP-165 which has the problem that it is not available for regular accounts to use. The second approach is EIP-672 which uses reverseENS. Using reverseENS, has two issues. First, it is unnecessarily complex, and second, ENS is still a centralized contract controlled by a multisig. This multisig, theoretically would be able to modify the system.
This standard is much simpler than EIP-672 and it is absolutely decentralized.
This standard also solves the problem of having different addresses for different chains.
Specification
The smart contract
Raw transaction for deploying the smart contract on any chain
You can see the string of
a
s at the end of the transaction. This is thes
of the signature, meaning that its a deterministic by hand forced signature.Deployment method
This contract is going to be deployed using the Nick's Method.
This method works as follows:
v
,r
,s
of the transaction signature to the following values:v: 27
r: 0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798
s: 0x0aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
This nice
s
value is a random number generated deterministically by a human.This operation can be done in any chain, guaranteed that the contract address is going to always be the same and nobody will be able to mess up that address with a different contract.
Special registry deployment account
This account is generated by reverse engineering it from it's signature for the transaction, in this way no one knows the private key, but it is known that it's the valid signer of the deployment transaction.
Deployed contract
The contract will have this address for every chain it is deployed to.
Interface name
Your interface name is hashed and sent to
getInterfaceImplementer()
. If you are writing a standard, it is best practice to explicitly state the interface name and link to this published EIP-820 so that other people don't have to come here to look up these rules.If it's an approved EIP
The interface is named like
ERC###XXXXX
. The meaning of this interface is defined in the EIP specified. And XXX should be the name of the interface camelCase.Examples:
sha3("ERC20Token")
sha3("ERC777Token")
sha3("ERC777TokensReceiver")
sha3("ERC777TokensSender")
EIP-165 compatible interfaces
Interfaces where the last 28bytes are 0, then this will be considered an EIP-165 interface.
Private user defined interface
This scheme is extensible. If you want to make up your own interface name and raise awareness to get other people to implement it and then check for those implementations, great! Have fun, but please do not conflict with the reserved designations above.
Backwards Compatibility
This standard is backwards compatible with EIP-165, as both methods can be implemented without conflicting one each other.
Test Cases
Please, check the repository https://github.com/jbaylina/eip820 for the full test suit.
Implementation
The implementation can be found in this repo: https://github.com/jbaylina/eip820
Copyright
Copyright and related rights waived via CC0.
The text was updated successfully, but these errors were encountered: