Skip to content

Instantly share code, notes, and snippets.

@tarrencev
Forked from backus/EthedIn.sol
Last active May 23, 2018 20:31
Show Gist options
  • Save tarrencev/ddf8b3301e5fbde994909de5fd1f2644 to your computer and use it in GitHub Desktop.
Save tarrencev/ddf8b3301e5fbde994909de5fd1f2644 to your computer and use it in GitHub Desktop.
Example #1 for "How to make a user friendly Ethereum dApp"
// Transaction Delegation is a generic way to enable transactions to be signed by one ethereum account
// and be sent by a different account. Enabling improved UX patterns where users of an application
// do not need to pay for transaction gas and do not necessarily need to have any ether at all to
// interact with an application.
//
// To delegate a transaction, a user A creates a transaction and signs the hash keccak256(calldata, nonce).
// The calldata and signature v, r, s is then communicated to user B who will submit the transaction on
// their behalf. User B submits the transaction by calling `TransactionDelegate.delegatedTxn`.
//
// This contract requires elevated privledges to the target contract allowing it to submit transactions
// on anothers behalf
//
// The pattern is inspired by https://gist.github.com/backus/55b874940fe46f1e9847ff1b763d0424
//
// THIS HAS NOT BEEN TESTED AT ALL
// https://github.com/aragon/aragonOS/blob/dev/contracts/common/DelegateProxy.sol
import "@aragon/os/contracts/common/DelegateProxy.sol";
contract TransactionDelegate is DelegateProxy {
address public target;
// track nonces to prevent replay and ensure txn ordering
mapping (address => uint64) nonces;
constructor(address _target) public {
target = _target;
}
function delegatedTxn(bytes calldata, uint8 nonce, uint8 v, bytes32 r, bytes32 s) public {
// Recreate the hash the user signed
bytes32 digest = keccak256(calldata, nonce);
address signer = ecrecovery(digest, v, r, s);
// First 20 bytes of calldata should always be address transaction is being sent on behalf of
// functions should follow pattern like: doActionFor(address _for, ...)
address sender = calldata[:20]; // pseudo code
require(sender == signer);
require(nonce == nonces[sender]);
nonces[sender] = nonces[sender] + 1;
delegatedFwd(target, calldata);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment