-
-
Save tarrencev/ddf8b3301e5fbde994909de5fd1f2644 to your computer and use it in GitHub Desktop.
Example #1 for "How to make a user friendly Ethereum dApp"
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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