-
Notifications
You must be signed in to change notification settings - Fork 21
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
Identity #10
Comments
Counterfactual deployment: 100% trustlessA fully trustless counterfactual deployment can be achieved by using a "trick" where we randomly choose the signature values of the deployment transaction, and then calculate the address that it needs to be sent from. This way, we prove to the relayer that we don't have the private key for the transaction (in fact no one has), but it's still a valid transaction that can be sent from a specific address. In more detail, this works as follows:
Proof of "not knowing the private key"We take a random number By doing this deterministic operation, we make it extremely difficult to create a private key for which the signature of FactoryAlways using a factory is a decent pattern, if it doesn't imply too much extra gas costs. The reason is that it's easy for the factory to also perform a registry role, if we need it. This can also make it much easier to integrate ENS. |
we should consider whether we can use WebCrypto/WebAuthentication for a more secure method of authenticating resources:
a TLDR is that webcrypto is not that useful cause it doesn't provide a way of protecting/storing private keys, and webauthentication is not ready yet even if it was, we might need ethereum/EIPs#28 (comment) |
To ensure the smoothest possible signup, we can introduce the concept of "limited"/"quick login" accounts. Create the Identity contract with one owner (which is a priv key, pwd encrypted and stored in the user's browser), and allow that identity to earn or spend up to X USD worth of crypto. In the application, we would ask the user whether they want to sign up "with a wallet" or in a quick way, but with limited earning/spending. Identity contracts will always be deployed with such an in-browser private key as the first owner, and:
|
We also need ot ensure the funds in the Identity contract are never fully withdrawn, otherwise it might get kind of bricked (the relayer wouldn't be able to relay if there's no funds to reward them) |
Actually, doing N/M multisig where the first key is the in-browser key is dangerous, since the in-browser key can be easily lost another way to do this in a simple way is just to assume the first key is the "unsafe" one, but still keep the 1/M policy for the other keys; this is very simple to do as well |
Functions on the multisig:
Each signed message should be executable only once. The way of how this will be achieved may vary - since with scheduled transactions, classic incremental nonce is not the right way. |
EDIT: relaying actual transactions can't work, cause (1) how much you're paying for the tx can't be signalled safely, (2) we need to do nonce hacks |
using the "first owner" assumption is not really ergonomic, so we will do a the first owner will be set to a full privilege, and when we add a second addr, we will call |
predefined (and scheduled) channel withdrawal should withdraw to the identity contract; it can be easily combined with another TX to withdraw to the withdrawal address |
transactions need to have value cause eth might've been sent to the SC before it's deployed |
No factoryWe don't need a factory - there's no point of keeping a registry, so there's no benefit to the factory+registry model originally planned. The factory would complicate deployment since contracts have their own sender nonce that we have to calculate from. Furthermore, it makes deployment impossible cause we hit the "unpredictable nonce" problem once again. We wanted the factory to help facilitate deployment with ETH, but that's still pretty easy: approach 1: using your own ETH wallet, calculate the identity contract address; send ETH to that address and then deploy the identity; then, through the identity, call into uniswap, swapping the ETH to a token (3 transactions) approach 2: using your own ETH wallet, first call into uniswap to obtain tokens, and then deploy the identity and send the tokens (3 transactions) approach 3: just do everything with ETH, no relayer |
this is done, so closing; implemented in |
Basic Gas Abstractions
Identity contract
Each user is represented by one instance of the Identity contract.
The Identity contract, by itself, is a simple 1/M multisig, constructed with an array of
owners
(addresses allowed to control it).It's interface is as follows:
constructor(address[] owners)
execute(Transaction tx, bytes signature)
: as long astx, txFeeToken, txFeeAmount
is signed, it will execute the transaction and sendtx.feeAmount
oftx.feeToken
tomsg.sender
(to redeem their gas spend)This contract, by itself, is self-sufficient and trustless. Even in the case where a relayer does not exist or is not present, the user may still invoke
execute
directly, paying the gas themselves.But a relayer may invoke
execute
, spending the needed gas, but takingtx.feeTokenAmount
Each
tx
should have atx.nonce
counted by the contract, to eliminate the possibility of double-spends.Since the
msg.sender
of any transaction done throughexecute
will be the contract, no changes need to be made in your protocol/dApp contracts: it's just like your user is being represented by a msig contract.Single relayer
Because of the trustless Identity contract, a single centralized relayer can be used without imposing any risks to the user and without assuming any trust.
This is possible because:
Getting paid in tokens
Each signed message that represents a transaction also contains
feeTokenAddr
andfeeTokenAmount
, that will be paid out to themsg.sender
Counterfactual deployment
The process of deploying the contract, withour requiring the user to hold any ETH, is as follows:
Note that this is vulnerable to front-running, since the user may sign another TX, deploying a contract that doesn't allocate the relayer's reward, and replace their previous TX; The SC address would still be the same because Ethereum only uses the sender address and nonce to determine it.
However, it is hard for the user to perform such an attack, because the relayer only funds the deploy wallet with sufficient eth to pay for the original transaction, and therefore the newer transaction can't have a higher fee.
An attack where the user would steal the ETH that's sent for deploying the contract is not practical, since that way the user would lose their own tokens that they sent to the SC address derived from nonce 0, which are presumably more valuable than the deploy fee ETH.
Please note that the relayer would only interact with SCs that they consider valid, which means that the hash of the contract bytecode must be in the relayer's whitelist.
Sign up with ETH
If the user prefers to interact with the system using ETH, we can, of course, skip the relayer altogether.
The user may send ETH to a factory contract, which will deploy an Identity contarct and swap the remainder of the sent ETH for a token that the user chooses (e.g. DAI).
The Identity is still needed to allow for the security benefits and the scheduling capabilities.
Transaction routines (and scheduling)
TODO
Two-factor auth
Two (or more) factor authentication can be implemented by requiring N/M signed messages from user addresses (
owners
) rather than just 1/M.This will achieve a classic two-factor authentication UX: the user requests to do something on their PC, and they're prompted to sign the same action on their phone.
EDIT: maybe we should consider this out of scope, adds too much complication
Receival (withdraw) address
The Identity contract may allow certain pre-set transactions to happen with only 1/M signatures, but any arbitrary transaction to happen with N/M.
This will allow the user to easily perform most actions, but any critical actions such as moving funds out of the Identity contract will require multiple signatures.
To improve the UX of the withdraw procedure, we can allow the user to set a "withdraw address", and have a pre-set transaction that withdraws to it that only requires 1/M signatures. That way, the user can easily authorize a withdraw to their preset "withdraw address", but changing it would require full two (or more) factor auth.
The text was updated successfully, but these errors were encountered: