presigned token

This commit is contained in:
Ricardo Guilherme Schmidt 2018-01-24 02:51:49 +00:00
parent 14832d927f
commit d12683b9b4
4 changed files with 234 additions and 0 deletions

3
.gitignore vendored
View File

@ -30,3 +30,6 @@ coverage.json
# node
node_modules/
npm-debug.log
# ide
.vs/

View File

@ -0,0 +1,26 @@
pragma solidity ^0.4.11;
import "../token/MiniMeTokenPreSigned.sol";
import "../token/MiniMeTokenPreSignedFactory.sol";
/*
Copyright 2017, Jarrad Hope (Status Research & Development GmbH)
*/
contract SNTPreSigned is MiniMeTokenPreSigned {
// @dev SNT constructor just parametrizes the MiniMeIrrevocableVestedToken constructor
function SNTPreSigned(address _oldToken)
MiniMeToken(
new MiniMeTokenPreSignedFactory(),
_oldToken, // parent token
block.number, // snapshot block
"Status Network Token", // Token name
18, // Decimals
"SNT", // Symbol
true // Enable transfers
)
public
{
}
}

View File

@ -0,0 +1,160 @@
pragma solidity ^0.4.18;
import "./MiniMeToken.sol";
/**
* @title StatusConstitution
* @author Ricardo Guilherme Schmidt (Status Research & Development GmbH)
* @dev MiniMeToken that supports pre-signed methods transfer(address,uint256) and approveAndCall(address,uint256,bytes)
*/
contract MiniMeTokenPreSigned is MiniMeToken {
mapping (address => uint256) public nonce;
/**
* @notice Include a presigned `transfer(address,uint256)`
* @param _sigV Signature V
* @param _sigR Signature R
* @param _sigS Signature S
* @param _to The address of the recipient
* @param _value The amount of tokens to be transferred
* @param _gasPrice How much tokens willing to pay per gas
* @param _nonce Presigned transaction number.
*/
function transferPreSigned(
uint8 _sigV,
bytes32 _sigR,
bytes32 _sigS,
address _to,
uint256 _value,
uint256 _gasPrice,
uint256 _nonce
)
public
{
uint256 _gas = msg.gas;
//"a9059cbb": "transfer(address,uint256)",
bytes32 txHash = keccak256(byte(0x19), byte(0), address(this), bytes4(0xa9059cbb), _to, _value, _gasPrice, _nonce);
address recovered = ecrecover(txHash, _sigV, _sigR, _sigS);
require(recovered > 0x0);
require(nonce[recovered] == _nonce);
nonce[recovered]++;
require(doTransfer(recovered, _to, _value));
_gas = 21000 + (_gas - msg.gas);
if (_gasPrice > 0) {
require(doTransfer(recovered, msg.sender, _gasPrice * _gas));
}
}
/**
* @notice Include a presigned `approveAndCall(address,uint256,bytes)`
* @param _sigV Signature V
* @param _sigR Signature R
* @param _sigS Signature S
* @param _spender The address of the recipient
* @param _amount The amount of tokens to be transferred
* @param _extraData option data to send to contract
* @param _gasPrice How much tokens willing to pay per gas
* @param _nonce Presigned transaction number.
*/
function approveAndCallPreSigned(
uint8 _sigV,
bytes32 _sigR,
bytes32 _sigS,
address _spender,
uint256 _amount,
bytes _extraData,
uint256 _gasPrice,
uint256 _nonce
)
public
{
uint256 _gas = msg.gas;
require(transfersEnabled);
//"cae9ca51": "approveAndCall(address,uint256,bytes)"
bytes32 txHash = keccak256(byte(0x19), byte(0), address(this), bytes4(0xcae9ca51), _spender, _amount, _extraData, _gasPrice, _nonce);
address recovered = ecrecover(txHash, _sigV, _sigR, _sigS);
require(recovered > 0x0);
require(nonce[recovered] == _nonce);
nonce[recovered]++;
require((_amount == 0) || (allowed[recovered][_spender] == 0));
if (isContract(controller)) {
require(TokenController(controller).onApprove(recovered, _spender, _amount));
}
allowed[recovered][_spender] = _amount;
Approval(recovered, _spender, _amount);
ApproveAndCallFallBack(_spender).receiveApproval(
recovered,
_amount,
this,
_extraData
);
_gas = 21000 + (_gas - msg.gas);
if (_gasPrice > 0) {
require(doTransfer(recovered, msg.sender, _gasPrice*_gas));
}
}
/**
* @notice Include batches of presigned `approveAndCall(address,uint256,bytes)`
* @param _sigV Signature V
* @param _sigR Signature R
* @param _sigS Signature S
* @param _spender The address of the recipient
* @param _amount The amount of tokens to be transferred
* @param _extraData option data to send to contract
* @param _gasPrice How much tokens willing to pay per gas
* @param _nonce Presigned transaction number.
*/
function approveAndCallPreSigned(
uint8[] _sigV,
bytes32[] _sigR,
bytes32[] _sigS,
address[] _spender,
uint256[] _amount,
bytes[] _extraData,
uint256[] _gasPrice,
uint256[] _nonce
)
public
{
uint len = _sigR.length;
require(len == _sigS.length && len == _sigV.length);
for (uint i = 0; i < len; i++) {
approveAndCallPreSigned(_sigV[i], _sigR[i], _sigS[i], _spender[i], _amount[i], _extraData[i], _gasPrice[i], _nonce[i]);
}
}
/**
* @notice Include batches of presigned `transfer(address,uint256)`
* @param _sigV Signature V
* @param _sigR Signature R
* @param _sigS Signature S
* @param _to The address of the recipient
* @param _value The amount of tokens to be transferred
* @param _gasPrice How much tokens willing to pay per gas
* @param _nonce Presigned transaction number.
*/
function transferPreSigned(
uint8[] _sigV,
bytes32[] _sigR,
bytes32[] _sigS,
address[] _to,
uint256[] _value,
uint256[] _gasPrice,
uint256[] _nonce
)
public
{
uint len = _sigR.length;
require(len == _sigS.length && len == _sigV.length);
for (uint i = 0; i < len; i++) {
transferPreSigned(_sigV[i], _sigR[i], _sigS[i], _to[i], _value[i], _gasPrice[i], _nonce[i]);
}
}
}

View File

@ -0,0 +1,45 @@
pragma solidity ^0.4.11;
import "./MiniMeTokenPreSigned.sol";
////////////////
// MiniMeTokenFactory
////////////////
/// @dev This contract is used to generate clone contracts from a contract.
/// In solidity this is the way to create a contract from a contract of the
/// same class
contract MiniMeTokenPreSignedFactory {
/// @notice Update the DApp by creating a new token with new functionalities
/// the msg.sender becomes the controller of this clone token
/// @param _parentToken Address of the token being cloned
/// @param _snapshotBlock Block of the parent token that will
/// determine the initial distribution of the clone token
/// @param _tokenName Name of the new token
/// @param _decimalUnits Number of decimals of the new token
/// @param _tokenSymbol Token Symbol for the new token
/// @param _transfersEnabled If true, tokens will be able to be transferred
/// @return The address of the new token contract
function createCloneToken(
address _parentToken,
uint _snapshotBlock,
string _tokenName,
uint8 _decimalUnits,
string _tokenSymbol,
bool _transfersEnabled
) returns (MiniMeTokenPreSigned) {
MiniMeTokenPreSigned newToken = new MiniMeTokenPreSigned(
this,
_parentToken,
_snapshotBlock,
_tokenName,
_decimalUnits,
_tokenSymbol,
_transfersEnabled
);
newToken.changeController(msg.sender);
return newToken;
}
}