GasRelay.sol
1 pragma solidity >=0.5.0 <0.7.0; 2 3 /** 4 * @title GasRelay as EIP-1077 5 * @author Ricardo Guilherme Schmidt (Status Research & Development GmbH) 6 * @notice gas abstraction interface 7 */ 8 contract GasRelay { 9 10 bytes4 internal constant MSG_EXECUTE_GASRELAY_PREFIX = bytes4( 11 keccak256("executeGasRelay(uint256,bytes,uint256,uint256,address,address)") 12 ); 13 14 constructor() internal {} 15 16 /** 17 * @notice executes `_execData` with current `nonce()` and pays `msg.sender` the gas used in specified `_gasToken`. 18 * @param _execData execution data (anything) 19 * @param _gasPrice price in `_gasToken` paid back to `msg.sender` per gas unit used 20 * @param _gasLimit maximum gas of this transacton 21 * @param _gasToken token being used for paying `msg.sender`, if address(0), ether is used 22 * @param _signature rsv concatenated ethereum signed message signatures required 23 */ 24 function executeGasRelay( 25 bytes calldata _execData, 26 uint256 _gasPrice, 27 uint256 _gasLimit, 28 address _gasToken, 29 bytes calldata _signature 30 ) 31 external; 32 33 function lastNonce() public view returns (uint nonce); 34 35 /** 36 * @notice gets ERC191 signing Hash of execute gas relay message 37 * @param _nonce current account nonce 38 * @param _execData execution data (anything) 39 * @param _gasPrice price in `_gasToken` paid back to `_gasRelayer` per gas unit used 40 * @param _gasLimit maximum gas of this transacton 41 * @param _gasToken token being used for paying `_gasRelayer` 42 * @param _gasRelayer beneficiary of gas refund 43 * @return executeGasRelayERC191Hash the message to be signed 44 */ 45 function executeGasRelayERC191Msg( 46 uint256 _nonce, 47 bytes memory _execData, 48 uint256 _gasPrice, 49 uint256 _gasLimit, 50 address _gasToken, 51 address _gasRelayer 52 ) 53 public 54 view 55 returns (bytes memory) 56 { 57 return abi.encodePacked( 58 toERC191SignedMessage( 59 address(this), 60 executeGasRelayMsg( 61 _nonce, 62 _execData, 63 _gasPrice, 64 _gasLimit, 65 _gasToken, 66 _gasRelayer 67 ) 68 ) 69 ); 70 } 71 72 /** 73 * @notice get message for executeGasRelay function. 74 * @param _nonce current account nonce 75 * @param _execData execution data (anything) 76 * @param _gasPrice price in `_gasToken` paid back to `_gasRelayer` per gas unit used 77 * @param _gasLimit maximum gas of this transacton 78 * @param _gasToken token being used for paying `_gasRelayer` 79 * @param _gasRelayer beneficiary of gas refund 80 * @return executeGasRelayMsg the appended message 81 */ 82 function executeGasRelayMsg( 83 uint256 _nonce, 84 bytes memory _execData, 85 uint256 _gasPrice, 86 uint256 _gasLimit, 87 address _gasToken, 88 address _gasRelayer 89 ) 90 public 91 pure 92 returns (bytes memory) 93 { 94 return abi.encodePacked( 95 _getChainID(), 96 MSG_EXECUTE_GASRELAY_PREFIX, 97 _nonce, 98 _execData, 99 _gasPrice, 100 _gasLimit, 101 _gasToken, 102 _gasRelayer 103 ); 104 } 105 106 /** 107 * @notice get network identification where this contract is running 108 */ 109 function _getChainID() internal pure returns (uint256) { 110 uint256 id = 1; 111 assembly { 112 // id := chainid() 113 } 114 return id; 115 } 116 117 /** 118 * @dev Returns an ERC191 Signed Message, created from a `hash`. This 119 * replicates the behavior of the 120 * https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign[`eth_signTypedData`] 121 * JSON-RPC method. 122 * 123 * See {recover}. 124 */ 125 function toERC191SignedMessage(address _validator, bytes memory data) internal pure returns (bytes32) { 126 return keccak256(abi.encodePacked(byte(0x19), byte(0x0), _validator, data)); 127 } 128 129 }