mirror of
https://github.com/status-im/snt-gas-relay.git
synced 2025-02-17 08:26:46 +00:00
replace repeated logic in a modifier, change const names, change event
This commit is contained in:
parent
6cbf61424a
commit
ffb4fa6ef5
@ -11,13 +11,68 @@ import "../token/ERC20Token.sol";
|
|||||||
*/
|
*/
|
||||||
contract IdentityGasRelay is Identity, MessageSigned {
|
contract IdentityGasRelay is Identity, MessageSigned {
|
||||||
|
|
||||||
bytes4 public constant CALL_PREFIX = bytes4(keccak256("callGasRelay(address,uint256,bytes32,uint256,uint256,address)"));
|
bytes4 public constant MSG_CALL_PREFIX = bytes4(keccak256("callGasRelay(address,uint256,bytes32,uint256,uint256,address)"));
|
||||||
bytes4 public constant DEPLOY_PREFIX = bytes4(keccak256("deployGasRelay(uint256,bytes32,uint256,uint256,address)"));
|
bytes4 public constant MSG_DEPLOY_PREFIX = bytes4(keccak256("deployGasRelay(uint256,bytes32,uint256,uint256,address)"));
|
||||||
bytes4 public constant APPROVEANDCALL_PREFIX = bytes4(keccak256("approveAndCallGasRelay(address,address,uint256,bytes32,uint256,uint256)"));
|
bytes4 public constant MSG_APPROVEANDCALL_PREFIX = bytes4(keccak256("approveAndCallGasRelay(address,address,uint256,bytes32,uint256,uint256)"));
|
||||||
|
|
||||||
event ExecutedGasRelayed(bytes32 signHash, bool success);
|
event ExecutedGasRelayed(bytes32 messageHash);
|
||||||
event ContractDeployed(address deployedAddress);
|
event ContractDeployed(address deployedAddress);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param _messageHash that is signed
|
||||||
|
* @param _required key purpose for this type of call
|
||||||
|
* @param _nonce current identity nonce
|
||||||
|
* @param _gasPrice price in SNT paid back to msg.sender for each gas unit used
|
||||||
|
* @param _gasLimit minimal gasLimit required to execute this call
|
||||||
|
* @param _gasToken token being used for paying `msg.sender`
|
||||||
|
* @param _messageSignatures rsv concatenated ethereum signed message signatures required
|
||||||
|
*/
|
||||||
|
modifier gasRelayed (
|
||||||
|
bytes32 _messageHash,
|
||||||
|
uint256 _requiredPurpose,
|
||||||
|
uint _nonce,
|
||||||
|
uint _gasPrice,
|
||||||
|
uint _gasLimit,
|
||||||
|
address _gasToken,
|
||||||
|
bytes _messageSignatures
|
||||||
|
) {
|
||||||
|
//query current gas available
|
||||||
|
uint startGas = gasleft();
|
||||||
|
|
||||||
|
//verify transaction parameters
|
||||||
|
require(startGas >= _gasLimit);
|
||||||
|
require(_nonce == nonce);
|
||||||
|
|
||||||
|
//verify if signatures are valid and came from correct actors;
|
||||||
|
verifySignatures(
|
||||||
|
_requiredPurpose,
|
||||||
|
_messageHash,
|
||||||
|
_messageSignatures
|
||||||
|
);
|
||||||
|
|
||||||
|
//increase nonce
|
||||||
|
nonce++;
|
||||||
|
|
||||||
|
//executes transaction
|
||||||
|
_;
|
||||||
|
|
||||||
|
//signal execution to event listeners
|
||||||
|
emit ExecutedGasRelayed(
|
||||||
|
_messageHash
|
||||||
|
);
|
||||||
|
|
||||||
|
//refund gas used using contract held ERC20 tokens or ETH
|
||||||
|
if (_gasPrice > 0) {
|
||||||
|
uint256 _amount = 21000 + (startGas - gasleft());
|
||||||
|
_amount = _amount * _gasPrice;
|
||||||
|
if (_gasToken == address(0)) {
|
||||||
|
address(msg.sender).transfer(_amount);
|
||||||
|
} else {
|
||||||
|
ERC20Token(_gasToken).transfer(msg.sender, _amount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @notice include ethereum signed callHash in return of gas proportional amount multiplied by `_gasPrice` of `_gasToken`
|
* @notice include ethereum signed callHash in return of gas proportional amount multiplied by `_gasPrice` of `_gasToken`
|
||||||
* allows identity of being controlled without requiring ether in key balace
|
* allows identity of being controlled without requiring ether in key balace
|
||||||
@ -41,13 +96,7 @@ contract IdentityGasRelay is Identity, MessageSigned {
|
|||||||
bytes _messageSignatures
|
bytes _messageSignatures
|
||||||
)
|
)
|
||||||
external
|
external
|
||||||
{
|
gasRelayed(
|
||||||
uint startGas = gasleft();
|
|
||||||
//verify transaction parameters
|
|
||||||
require(startGas >= _gasLimit);
|
|
||||||
require(_nonce == nonce);
|
|
||||||
// calculates signHash
|
|
||||||
bytes32 signHash = getSignHash(
|
|
||||||
callGasRelayHash(
|
callGasRelayHash(
|
||||||
_to,
|
_to,
|
||||||
_value,
|
_value,
|
||||||
@ -56,34 +105,17 @@ contract IdentityGasRelay is Identity, MessageSigned {
|
|||||||
_gasPrice,
|
_gasPrice,
|
||||||
_gasLimit,
|
_gasLimit,
|
||||||
_gasToken
|
_gasToken
|
||||||
)
|
),
|
||||||
);
|
|
||||||
|
|
||||||
//verify if signatures are valid and came from correct actors;
|
|
||||||
verifySignatures(
|
|
||||||
_to == address(this) ? MANAGEMENT_KEY : ACTION_KEY,
|
_to == address(this) ? MANAGEMENT_KEY : ACTION_KEY,
|
||||||
signHash,
|
_nonce,
|
||||||
|
_gasPrice,
|
||||||
|
_gasLimit,
|
||||||
|
_gasToken,
|
||||||
_messageSignatures
|
_messageSignatures
|
||||||
);
|
)
|
||||||
|
returns (bool success)
|
||||||
//executes transaction
|
{
|
||||||
nonce++;
|
success = _to.call.value(_value)(_data);
|
||||||
bool success = _to.call.value(_value)(_data);
|
|
||||||
emit ExecutedGasRelayed(
|
|
||||||
signHash,
|
|
||||||
success
|
|
||||||
);
|
|
||||||
|
|
||||||
//refund gas used using contract held ERC20 tokens or ETH
|
|
||||||
if (_gasPrice > 0) {
|
|
||||||
uint256 _amount = 21000 + (startGas - gasleft());
|
|
||||||
_amount = _amount * _gasPrice;
|
|
||||||
if (_gasToken == address(0)) {
|
|
||||||
address(msg.sender).transfer(_amount);
|
|
||||||
} else {
|
|
||||||
ERC20Token(_gasToken).transfer(msg.sender, _amount);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -108,14 +140,7 @@ contract IdentityGasRelay is Identity, MessageSigned {
|
|||||||
bytes _messageSignatures
|
bytes _messageSignatures
|
||||||
)
|
)
|
||||||
external
|
external
|
||||||
returns(address deployedAddress)
|
gasRelayed(
|
||||||
{
|
|
||||||
uint startGas = gasleft();
|
|
||||||
//verify transaction parameters
|
|
||||||
require(startGas >= _gasLimit);
|
|
||||||
require(_nonce == nonce);
|
|
||||||
// calculates signHash
|
|
||||||
bytes32 signHash = getSignHash(
|
|
||||||
deployGasRelayHash(
|
deployGasRelayHash(
|
||||||
_value,
|
_value,
|
||||||
keccak256(_data),
|
keccak256(_data),
|
||||||
@ -123,32 +148,18 @@ contract IdentityGasRelay is Identity, MessageSigned {
|
|||||||
_gasPrice,
|
_gasPrice,
|
||||||
_gasLimit,
|
_gasLimit,
|
||||||
_gasToken
|
_gasToken
|
||||||
)
|
),
|
||||||
);
|
|
||||||
|
|
||||||
//verify if signatures are valid and came from correct actors;
|
|
||||||
verifySignatures(
|
|
||||||
ACTION_KEY,
|
ACTION_KEY,
|
||||||
signHash,
|
_nonce,
|
||||||
|
_gasPrice,
|
||||||
|
_gasLimit,
|
||||||
|
_gasToken,
|
||||||
_messageSignatures
|
_messageSignatures
|
||||||
);
|
)
|
||||||
|
returns(address deployedAddress)
|
||||||
//executes transaction
|
{
|
||||||
nonce++;
|
|
||||||
deployedAddress = doCreate(_value, _data);
|
deployedAddress = doCreate(_value, _data);
|
||||||
emit ContractDeployed(deployedAddress);
|
emit ContractDeployed(deployedAddress);
|
||||||
|
|
||||||
//refund gas used using contract held ERC20 tokens or ETH
|
|
||||||
if (_gasPrice > 0) {
|
|
||||||
uint256 _amount = 21000 + (startGas - gasleft());
|
|
||||||
_amount = _amount * _gasPrice;
|
|
||||||
if (_gasToken == address(0)) {
|
|
||||||
address(msg.sender).transfer(_amount);
|
|
||||||
} else {
|
|
||||||
ERC20Token(_gasToken).transfer(msg.sender, _amount);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -179,16 +190,7 @@ contract IdentityGasRelay is Identity, MessageSigned {
|
|||||||
bytes _messageSignatures
|
bytes _messageSignatures
|
||||||
)
|
)
|
||||||
external
|
external
|
||||||
{
|
gasRelayed(
|
||||||
uint startGas = gasleft();
|
|
||||||
//verify transaction parameters
|
|
||||||
require(startGas >= _gasLimit);
|
|
||||||
require(_nonce == nonce);
|
|
||||||
require(_baseToken != address(0)); //_baseToken should be something!
|
|
||||||
require(_to != address(this)); //no management with approveAndCall
|
|
||||||
|
|
||||||
// calculates signHash
|
|
||||||
bytes32 signHash = getSignHash(
|
|
||||||
approveAndCallGasRelayHash(
|
approveAndCallGasRelayHash(
|
||||||
_baseToken,
|
_baseToken,
|
||||||
_to,
|
_to,
|
||||||
@ -198,59 +200,47 @@ contract IdentityGasRelay is Identity, MessageSigned {
|
|||||||
_gasPrice,
|
_gasPrice,
|
||||||
_gasLimit,
|
_gasLimit,
|
||||||
_gasToken
|
_gasToken
|
||||||
)
|
),
|
||||||
);
|
ACTION_KEY,
|
||||||
|
_nonce,
|
||||||
//verify if signatures are valid and came from correct actors;
|
_gasPrice,
|
||||||
verifySignatures(
|
_gasLimit,
|
||||||
ACTION_KEY, //no management with approveAndCall
|
_gasToken,
|
||||||
signHash,
|
|
||||||
_messageSignatures
|
_messageSignatures
|
||||||
);
|
)
|
||||||
|
returns(bool success)
|
||||||
|
{
|
||||||
|
require(_baseToken != address(0)); //_baseToken should be something!
|
||||||
|
require(_to != address(this)); //no management with approveAndCall
|
||||||
|
|
||||||
approveAndCall(
|
ERC20Token(_baseToken).approve(_to, _value);
|
||||||
signHash,
|
success = _to.call(_data);
|
||||||
_baseToken,
|
|
||||||
_to,
|
|
||||||
_value,
|
|
||||||
_data
|
|
||||||
);
|
|
||||||
|
|
||||||
//refund gas used using contract held ERC20 tokens or ETH
|
|
||||||
if (_gasPrice > 0) {
|
|
||||||
uint256 _amount = 21000 + (startGas - gasleft());
|
|
||||||
_amount = _amount * _gasPrice;
|
|
||||||
if (_gasToken == address(0)) {
|
|
||||||
address(msg.sender).transfer(_amount);
|
|
||||||
} else {
|
|
||||||
ERC20Token(_gasToken).transfer(msg.sender, _amount);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @notice reverts if signatures are not valid for the signed hash and required key type.
|
* @notice reverts if signatures are not valid for the signed hash and required key type.
|
||||||
* @param _requiredKey key required to call, if _to from payload is the identity itself, is `MANAGEMENT_KEY`, else `ACTION_KEY`
|
* @param _requiredKey key required to call, if _to from payload is the identity itself, is `MANAGEMENT_KEY`, else `ACTION_KEY`
|
||||||
* @param _signHash ethereum signable callGasRelayHash message provided for the payload
|
* @param _messageHash message hash provided for the payload
|
||||||
* @param _messageSignatures ethereum signed `_signHash` messages
|
* @param _messageSignatures ethereum signed `getSignHash(_messageHash)` message
|
||||||
* @return true case valid
|
* @return true case valid
|
||||||
*/
|
*/
|
||||||
function verifySignatures(
|
function verifySignatures(
|
||||||
uint256 _requiredKey,
|
uint256 _requiredKey,
|
||||||
bytes32 _signHash,
|
bytes32 _messageHash,
|
||||||
bytes _messageSignatures
|
bytes _messageSignatures
|
||||||
)
|
)
|
||||||
public
|
public
|
||||||
view
|
view
|
||||||
returns(bool)
|
returns(bool)
|
||||||
{
|
{
|
||||||
|
// calculates signHash
|
||||||
|
bytes32 signHash = getSignHash(_messageHash);
|
||||||
uint _amountSignatures = _messageSignatures.length / 65;
|
uint _amountSignatures = _messageSignatures.length / 65;
|
||||||
require(_amountSignatures == purposeThreshold[_requiredKey]);
|
require(_amountSignatures == purposeThreshold[_requiredKey]);
|
||||||
bytes32 _lastKey = 0;
|
bytes32 _lastKey = 0;
|
||||||
for (uint256 i = 0; i < _amountSignatures; i++) {
|
for (uint256 i = 0; i < _amountSignatures; i++) {
|
||||||
bytes32 _currentKey = recoverKey(
|
bytes32 _currentKey = recoverKey(
|
||||||
_signHash,
|
signHash,
|
||||||
_messageSignatures,
|
_messageSignatures,
|
||||||
i
|
i
|
||||||
);
|
);
|
||||||
@ -288,7 +278,7 @@ contract IdentityGasRelay is Identity, MessageSigned {
|
|||||||
{
|
{
|
||||||
_callGasRelayHash = keccak256(
|
_callGasRelayHash = keccak256(
|
||||||
address(this),
|
address(this),
|
||||||
CALL_PREFIX,
|
MSG_CALL_PREFIX,
|
||||||
_to,
|
_to,
|
||||||
_value,
|
_value,
|
||||||
_dataHash,
|
_dataHash,
|
||||||
@ -323,7 +313,7 @@ contract IdentityGasRelay is Identity, MessageSigned {
|
|||||||
{
|
{
|
||||||
_callGasRelayHash = keccak256(
|
_callGasRelayHash = keccak256(
|
||||||
address(this),
|
address(this),
|
||||||
DEPLOY_PREFIX,
|
MSG_DEPLOY_PREFIX,
|
||||||
_value,
|
_value,
|
||||||
_dataHash,
|
_dataHash,
|
||||||
_nonce,
|
_nonce,
|
||||||
@ -361,7 +351,7 @@ contract IdentityGasRelay is Identity, MessageSigned {
|
|||||||
{
|
{
|
||||||
_callGasRelayHash = keccak256(
|
_callGasRelayHash = keccak256(
|
||||||
address(this),
|
address(this),
|
||||||
APPROVEANDCALL_PREFIX,
|
MSG_APPROVEANDCALL_PREFIX,
|
||||||
_baseToken,
|
_baseToken,
|
||||||
_to,
|
_to,
|
||||||
_value,
|
_value,
|
||||||
@ -429,25 +419,6 @@ contract IdentityGasRelay is Identity, MessageSigned {
|
|||||||
|
|
||||||
require(v == 27 || v == 28);
|
require(v == 27 || v == 28);
|
||||||
}
|
}
|
||||||
|
|
||||||
function approveAndCall(
|
|
||||||
bytes32 _signHash,
|
|
||||||
address _token,
|
|
||||||
address _to,
|
|
||||||
uint256 _value,
|
|
||||||
bytes _data
|
|
||||||
)
|
|
||||||
private
|
|
||||||
{
|
|
||||||
//executes transaction
|
|
||||||
nonce++;
|
|
||||||
ERC20Token(_token).approve(_to, _value);
|
|
||||||
emit ExecutedGasRelayed(
|
|
||||||
_signHash,
|
|
||||||
_to.call(_data)
|
|
||||||
);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @notice creates new contract based on input `_code` and transfer `_value` ETH to this instance
|
* @notice creates new contract based on input `_code` and transfer `_value` ETH to this instance
|
||||||
|
Loading…
x
Reference in New Issue
Block a user