/ contracts / gasrelay / GasRelay.sol
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  }