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鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Provide function(s) that verify an address is an EOA #1850

Open
Austin-Williams opened this issue Jul 31, 2019 · 6 comments

Comments

@Austin-Williams
Copy link

commented Jul 31, 2019

馃 Motivation
It can be useful to verify that a given address is:

  1. For-sure an EOA
  2. For-sure an EOA that is not a one-time-use EOA

We could provide this functionality in the Address library.

馃摑 Details
I suggest adding two functions to the Address library.

The first would be: isEOA(address account, bytes32 hash, bytes memory signature). This would accept an arbitrary hash, verify the signature, use recover (from the ECDSA library) to recover the account of the signer, and return true only if the recovered address matched the account parameter. Thus, if isEOA returns true then we know for-sure that account is an EOA because it was able to sign a message. (Though if it returns false we get no information at all).

However, there are also important cases where being an EOA is not enough -- and we also want to verify that a given address is not a one-time-use EOA (such as those created using Nick Johnson's method). So for that I suggest the following general function:

isNonOneTimeUseEOA(address account, bytes32 hash1, bytes memory signature1, bytes32 hash2, bytes memory signature2). This would verify both signatures, verify that hash1 != hash2, use recover on both signatures, then return true only if the recovered addresses and the account parameter were all equal to each other. What this is doing is verifying that the account is able to sign two distinct messages -- ensuring that it cannot be a one-time-use EOA (since one-time-use EOAs can only ever create a single signature). Thus, if isNonOneTimeUseEOA returns true then we know for-sure that account is an EOA but not a one-time-use EOA. (Though if it returns false we get no information at all).

@nventuro nventuro added the contracts label Jul 31, 2019

@nventuro

This comment has been minimized.

Copy link
Member

commented Jul 31, 2019

Hey @Austin-Williams, thanks for this suggestion!

The first would be: isEOA(address account, bytes32 hash, bytes memory signature). This would accept an arbitrary hash, verify the signature, use recover (from the ECDSA library)

A long standing issue with recover is that receiving a hash may cause people to think that a hash and signature are proof enough, we should probably change this eventually so that the recover call hashes its input. See the warning on recover's docs.

However, there are also important cases where being an EOA is not enough -- and we also want to verify that a given address is not a one-time-use EOA (such as those created using Nick Johnson's method).

Could you expand a bit on which cases these are?

@Austin-Williams

This comment has been minimized.

Copy link
Author

commented Jul 31, 2019

A long standing issue with recover is that receiving a hash may cause people to think that a hash and signature are proof enough, we should probably change this eventually so that the recover call hashes its input. See the warning on recover's docs.

Oh this is a really good point! For these functions we could use ecrecover directly if we aren't ready to change recover.

However, there are also important cases where [...] we also want to verify that a given address is not a one-time-use EOA [...] Could you expand a bit on which cases these are?

Yes. Preventing the bypassing of timelock incentive mechanisms is an example where if the address you're storing (the beneficiary address) is a contract or a one-time-use EOA it can result in the timelock incentive mechanism being bypassed. So you want to be certain that the address you're storing is a non-one-time-use EOA.

A general, high-level description is: if you want to prevent ETH/tokens from being sent directly to a contract, then you also probably want to prevent the ETH/tokens from being sent directly to a one-time-use EOA that provably can only send its ETH/tokens directly to a contract. Sending ETH/tokens to such an EOA can be effectively the same as sending it directly to the contract.

@frangio

This comment has been minimized.

Copy link
Member

commented Aug 9, 2019

Sending ETH/tokens to such an EOA can be effectively the same as sending it directly to the contract.

It's a great point. One way of thinking about this is that a one-time-use EOA is essentially a counterfactual contract.

@Austin-Williams

This comment has been minimized.

Copy link
Author

commented Aug 15, 2019

That's a good way of putting it.

@crazyrabbitLTC

This comment has been minimized.

Copy link

commented Sep 19, 2019

As a question @Austin-Williams what is the purpose of preventing ETH/tokens from being sent directly to a contract? Is there an example case? I'm curious because I've been thinking more of a future where users interact with wallets that are contracts so they can be meta-transaction enabled, rather than using a 'real' wallet like Metamask. I assume this would preclude these types of users from using these kinds of wallets?
Of course, I guess maybe we could think of it in the opposite, like you want to be sure ETH/tokens can only go to contract addresses?

@Austin-Williams

This comment has been minimized.

Copy link
Author

commented Sep 19, 2019

@crazyrabbitLTC I generally agree that sending ETH from to/from contracts is a great thing.

There are very special cases when we'd want to prevent it. These are mostly cases where we are designing a mechanism in which we don't want the users to be able to make strategic commitments (aka strategic moves) that might undermine the mechanism.

A specific example is when creating token timelocks for incentive-alignment. If the beneficiary of the token timelock is able to make strategic commitments, then they are able to bypass the token timelock.

In practice, strategic commitments are often very difficult to achieve (in the blockchain setting) without the use of a contract to enforce the commitment. So if, as a mechanism designer, you can prevent the use of contracts (in very particular settings) you can sometimes effectively eliminate large classes of potentially malicious behavior.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
4 participants
You can鈥檛 perform that action at this time.