replace repeated logic in a modifier, change const names, change event

This commit is contained in:
Ricardo Guilherme Schmidt 2018-05-08 20:12:32 -03:00
parent 6cbf61424a
commit ffb4fa6ef5

View File

@ -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)
approveAndCall( {
signHash, require(_baseToken != address(0)); //_baseToken should be something!
_baseToken, require(_to != address(this)); //no management with approveAndCall
_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);
}
}
ERC20Token(_baseToken).approve(_to, _value);
success = _to.call(_data);
} }
/** /**
* @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,
@ -430,25 +420,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
* @param _value amount ether in wei to sent to deployed address at its initialization * @param _value amount ether in wei to sent to deployed address at its initialization