-
Notifications
You must be signed in to change notification settings - Fork 13
/
AccountGasAbstract.sol
101 lines (92 loc) · 2.69 KB
/
AccountGasAbstract.sol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
pragma solidity >=0.5.0 <0.7.0;
import "./Account.sol";
import "../gasrelay/GasRelay.sol";
/**
* @title AccountGasAbstract
* @author Ricardo Guilherme Schmidt (Status Research & Development GmbH)
* @notice defines account gas abstract
*/
contract AccountGasAbstract is Account, GasRelay {
string internal constant ERR_INVALID_SIGNATURE = "Invalid signature";
modifier gasRelay(
bytes memory _execData,
uint256 _gasPrice,
uint256 _gasLimit,
address _gasToken,
address payable _gasRelayer,
bytes memory _signature
){
//query current gas available
uint startGas = gasleft();
//verify if signatures are valid and came from correct actor;
require(
isValidSignature(
executeGasRelayERC191Msg(
nonce,
_execData,
_gasPrice,
_gasLimit,
_gasToken,
_gasRelayer
),
_signature
) == MAGICVALUE,
ERR_INVALID_SIGNATURE
);
_;
//refund gas used using contract held ERC20 tokens or ETH
if (_gasPrice > 0) {
payGasRelayer(
startGas,
_gasPrice,
_gasToken,
_gasRelayer == address(0) ? block.coinbase : _gasRelayer
);
}
}
function executeGasRelay(
bytes calldata _execData,
uint256 _gasPrice,
uint256 _gasLimit,
address _gasToken,
address payable _gasRelay,
bytes calldata _signature
)
external
gasRelay(
_execData,
_gasPrice,
_gasLimit,
_gasToken,
_gasRelay,
_signature
)
{
address(this).call.gas(_gasLimit)(_execData);
}
function lastNonce() public view returns (uint256) {
return nonce;
}
/**
* @notice check gas limit and pays gas to relayer
* @param _startGas gasleft on call start
* @param _gasPrice price in `_gasToken` paid back to `_gasRelayer` per gas unit used
* @param _gasToken token being used for paying `_gasRelayer`
* @param _gasRelayer beneficiary of the payout
*/
function payGasRelayer(
uint256 _startGas,
uint256 _gasPrice,
address _gasToken,
address payable _gasRelayer
)
internal
{
uint256 _amount = (100000 + (_startGas - gasleft()) * _gasPrice);
if (_gasToken == address(0)) {
_gasRelayer.call.value(_amount)("");
} else {
ERC20Token(_gasToken).transfer(_gasRelayer, _amount);
}
}
}