Executable signed messages are definitely a step in the right direction, but I think we can further generalize this concept. I think a prototypical Ethereum user doesn’t really want to think about individual transactions at all - rather, they want to think about sets of authorized and unauthorized state transitions.
- I would like to transfer 1 Ether to my friend to pay for dinner, once, now.
- I would like to transfer 100 DAI to my son next Tuesday, only if his account balance is below 10 DAI, as allowance for dinner with his friends.
- I would like to authorize my phone to spend Ether from my main account, but only up to 2 Ether per week, in case it gets stolen.
- I would like to authorize CryptoKitties to transfer 0.1 Ether per month from my account for a “CryptoKitty-of-the-month” promotion, until I cancel this subscription.
- I would like to only allow transfers of more than 5 Ether if I authorize the transfer from both my laptop and my phone.
Of these, (1) can be done with an Ethereum transaction (or an executable signed message). (2), (3), (4), and (5) require writing custom contracts and complex key management (and are thus beyond the reach of ordinary users).
Not only do I want to separate the notion of transaction “signer” from transaction “deployer”, I want to separate the notion of “transaction” from “state transitions” - I want the ability to, with one signature, authorize an arbitrary, possibly infinite, set of well-specified state transitions.
This can be done by allowing a user to specify some function
v (for “validate”), which can authorize or reject transactions on the basis of chain state, transaction details, signee(s), and current time.
For each of these examples, this function would do roughly the following:
- Check the amount, signature, and a nonce/hash for replay protection.
- Check the timestamp, my son’s account balance, and a nonce/hash for replay protection.
- Check the signee (key from my phone), a nonce/hash for replay protection, and the running counter for the amount spent this week.
- Check the destination, amount, and a timestamp for subscription logic (incremented by “a month” each call, so CryptoKitties can charge me no more than once per month).
- Check the signees (keys from both laptop and phone).
I think we can expand the range of options accessible to the general userbase (with well-constructed application-layer GUI support) by allowing users to sign new versions of an arbitrary, settable transaction validation function (which can itself authorize executable signed messages).
A user’s account contract would then have the following function:
execute will need to do the following:
- Check that the user has signed
keccak256(validationBytecode, validationTimestamp), check that
validationTimestamp is strictly greater than any previously stored
validationTimestamp, and store
- Lazily deploy a new validation contract (only if there was no previous contract for this version of
validationBytecode, could even use a global registry).
DELEGATECALL into the validation contract, providing all the other parameters of
The validation contract can then check transaction amount, destination, signee(s), gas, nonce/timestamp, etc. before executing the transaction, and can confirm any desired invariants after executing a transaction (such as that the contract’s token balance changed by no more than a certain amount).
This model is quite generic; for example, it can replace all the existing ERC20/ERC721 “approve”-style logic, and has the advantage (over “approve”) of placing all the approval information in one place (no need to track all contracts you’ve ever approved), allowing custom approval logic (such as only allowing
transferFrom to be called by contract A with a destination of contract B), and allowing
transferFrom to be executed in the same transaction.
Definitely requires some fine-tuning, but hopefully the idea is clear enough, let me know what you think. May be better suited for a separate EIP or discussion elsewhere.