A registry for generating future-deployed smart contract accounts owned by users on external services
createAccount interface is susceptible to front-running. Registration of this kind should have commit and reveal steps like ENS so that others cannot grief you or otherwise claim your property before you.
I built a similar system. It lives at
0x000000000000c57cf0a1f923d44527e703f1ad70. Here is its ABI:
// ABI: // 0x06fdde03 name() // 0x1b8b921d call(address,bytes) // 0x5a628525 reveal(address,bytes32) // 0x6352211e ownerOf(uint256) // 0x7672b6a7 setCode(address,address) // 0x95d89b41 symbol() // 0xba45b0b8 transfer(address,address) // 0xc87b56dd tokenURI(uint256) // 0xe75179a4 reserve(address) // 0xf75f9f7b dispute(address) // EVENTS: // 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef // Transfer(address,address,uint256)
I decided not to fully implement ERC-721 but a better system might.
Re front-running, in the EIP:
However, if the malicious actor attempted to alter the `owner` parameter in the calldata, the Account Registry Instance would find the signature to be invalid, and revert the transaction.
This isn’t true. A front-runner can generate their own signature to make it valid. Your method is security-by-obscurity, and only works while the system has no value to anyone. If it became important enough someone could circumvent your signature system. To fix it you would need to more tightly bind the salt to the owner, such that other accounts could not use the same salt at all. But even better would be commit-reveal, like ENS.
I think there’s a misunderstanding of the spec. A front runner CANNOT generate a signature. The signature can ONLY be generated by a specified signer for the registry. How could a front runner generate a valid signature which passes validation?
The spec may be unclear here. We do show this in the implementation.
Here’s the codebase, which hopefully makes it more clear:
eww it’s worse than I thought. The implementation example uses
Ownable to manage
signer and this centralizes registration while also making it vulnerable via the owner. A better system would allow open registration.
The purpose of this is different than what you’re probably intending.
The purpose of this is for ‘centralized’ registrars to associate non-web3 identifying accounts to salts.
Think emails → a future account.
The purpose is an alternative to fireblocks or coinbase wallet connect, where a registrar can provide web3 receive wallets to web2 users.
You’re probably thinking of a web3 system where ppl can claim future counterfactual accounts (if I’m understanding you correctly), which is actually not the intent of what this is supposed to provide.
A protocol such as that does not require standardization.
The only standardization proposal is the interface to retrieve and create accounts with a common signing pattern.
Why? So that web3 wallets could also have a mechanism to provide access to web3 auth for web2 wallets. We were initially looking to extend this proposal to include a way to do web3 auth as well, but trying to see if ERC-6492 could be adapted to achieve this or whether we would have to include an extension in this proposal as well.
We wanted this out there to spur discussion on how this type of account could be integrated into other existing web3 auth standards.
So, as written, you’re right, there doesn’t need to be a standard for the concept of claim/account creation. But the proposal is definitely not in it’s final form and we want to include some counterfactual wallet signature validation support.
Also, in theory, a signer verifier could be a smart contract that is not centrally controlled, with its own permissioning scheme.
So, upon further thinking about using ERC-6492.
It wouldn’t make sense for the spec to be extended to delegate signature validation to a factory (or a registry in this case) because there would be no way to prove a given factory/registry could create an account without the multicall simulation, which brings us back to square one.
Perhaps the solution is to modify this spec to separate out the act of account creation (such that anyone could deploy a smart contract wallet that has no assigned permission controls) and account control assignment, which would allow ERC-6492 to be supported.
However, this would mean the EIP being extended to define a basic account interface and definition around ‘ownership’.
IIUC, a user relies on an external service to validate and create the account.
It seems wrong to move funds to an address I think I own, that an external entity can decide to create with a different owner.
This right here. If the external service gets to decide the private key associated with the account, then it isn’t really your account. It might eventually become your account when you do get your keys deployed, but until then it is the external service’s account.
Might be better to approach this from the other direction, where a user can declare that a certain address belongs to them on the external service? You can pretty much do that today though: just stick your address in your, for example, twitter bio.
This is actually what we’re trying to accomplish. The idea is that this is will be used by traditional web applications to back arbitrary user information with on-chain data without requiring the user to own or link their own wallet.
Imagine a social media service that wants to mint public user posts as NFTs to a user’s Ethereum address. The service can provide web3 natives the option to link their own wallet, but they can use ROAs for their non-crypto native audience.
It is true that the external service that owns the registry instance has control over ROA addresses that have not been claimed. Prior to a user claiming an account instance, an ROA is no different from a traditional custodial wallet. The key difference between this proposal and traditional custodial wallet implementations is that the user can later take full ownership of the address, and the on-chain history and identity associated with that address. If the service was to attempt to provide this functionality with traditional custodial wallets (where the service holds private keys for an EOA linked to the user), the user cannot trust that a service has wiped those keys from its datastore upon export. Users would ultimately need to batch transfer everything from the wallet for security purposes, and lose the provenance associated with that wallet.
Perhaps this is something to emphasize more clearly in the proposal. The main use case for ROAs is to enable non-crypto native audiences to build on-chain identities before creating an EOA and transacting on-chain.
While I believe this is an admirable goal, giving every user an address that they don’t control is a huge rugpull risk. Today if Twitter decides to appropriate your username/account, they can do so, but it’s limited to your social media account. If Twitter had given their users crypto addresses, now they can steal any tokens in addition to their social media account.
Taking off my editor hat for a moment, standardizing such a mechanism gives it a certain amount of credibility, and this is something that is very much unaligned with how I see Ethereum. We shouldn’t be building standards that give more power to centralized services.
A centralized signing authority is only one thing that this could allow for, however, it does not mean that you can’t have a decentralized signing authority.
The main reason for this EIP proposal is to provide a framework for a signer to be able to complete the reserved owner claim process. How that signer is controlled (centralized or decentralized) is not contemplated.
The value here is the ability to onboard users (in web2 land or any other non-web3 ecosystem) onto Ethereum without the need to front gas costs or network fees.
Consider a signer which acts as a cross chain oracle as a potential implementer of this (e.g. bringing Bitcoin or Solana users into the ecosystem as asset recipients first).
Would you consider the use of oracles ‘central services’ as well?
We’ve updated the spec to define how signing would work, and how an ROA could be used to do read only and web2 operations on dapps via eip-6492