文件 1 的 7:ECRecovery.sol
pragma solidity 0.5.8;
library ECRecovery {
function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
bytes32 r;
bytes32 s;
uint8 v;
if (signature.length != 65) {
return (address(0));
}
assembly {
r := mload(add(signature, 32))
s := mload(add(signature, 64))
v := byte(0, mload(add(signature, 96)))
}
if (v < 27) {
v += 27;
}
if (v != 27 && v != 28) {
return (address(0));
} else {
return ecrecover(hash, v, r, s);
}
}
}
文件 2 的 7:ERC20.sol
pragma solidity 0.5.8;
import "./IERC20.sol";
import "./SafeMath.sol";
import "./Ownable.sol";
import { ECRecovery } from "./ECRecovery.sol";
contract ERC20 is IERC20, Ownable {
using SafeMath for uint256;
mapping (address => uint256) internal _balances;
mapping (address => mapping (address => uint256)) internal _allowed;
mapping (address => uint256) internal _timeUpdates;
mapping (address => uint256) internal _circulatingSupply;
mapping (address => bool) private _isHolder;
mapping (bytes => bool) private signatures;
address[] internal _holders;
address internal msgSender;
uint256 internal _totalSupply;
uint256 public gasForTransfer = 150000;
uint256 public ethRate = 2000000;
bool public pause = false;
bool public stop = false;
bool public stopMint = false;
modifier feeless {
if (msgSender == address(0)) {
msgSender = msg.sender;
_;
msgSender = address(0);
} else {
_;
}
}
function performFeelessTransaction(address sender, address target, bytes memory data, uint256 nonce, bytes memory sig) public payable {
require(address(this) == target, 'target wrong');
require(!signatures[sig]);
signatures[sig] = true;
bytes memory prefix = "\x19Ethereum Signed Message:\n32";
bytes32 payload = keccak256(abi.encodePacked(target, data, nonce));
bytes32 hash = keccak256(abi.encodePacked(prefix, payload));
msgSender = ECRecovery.recover(hash, sig);
require(msgSender == sender, 'sender error');
(bool success,) = target.call.value(msg.value)(data);
require(success, 'not success');
chargeFeeInTokens(sender);
msgSender = address(0);
}
function chargeFeeInTokens(address holder) private {
uint256 value = gasForTransfer.mul(tx.gasprice).mul(ethRate);
_balances[holder] = _balances[holder].sub(value);
_balances[msg.sender] = _balances[msg.sender].add(value);
emit Transfer(holder, msg.sender, value);
}
function setPauseTransfers(bool newPauseVal) public onlyOwner {
pause = newPauseVal;
}
function stopTransfers() public onlyOwner {
stop = true;
}
function stopMintForever() public onlyOwner {
stopMint = true;
}
function totalSupply() public view returns (uint256) {
return _totalSupply;
}
function balanceOf(address owner) public view returns (uint256) {
return _balances[owner];
}
function allowance(address owner, address spender) public view returns (uint256) {
return _allowed[owner][spender];
}
function transferFeeless(address to, uint256 value, string memory token) public feeless returns (bool) {
_transfer(msgSender, to, value);
return true;
}
function transfer(address to, uint256 value) public returns (bool) {
_transfer(msg.sender, to, value);
return true;
}
function approve(address spender, uint256 value) public returns (bool) {
_approve(msg.sender, spender, value);
return true;
}
function transferFrom(address from, address to, uint256 value) public returns (bool) {
_transfer(from, to, value);
_approve(from, msg.sender, _allowed[from][msg.sender].sub(value));
return true;
}
function increaseAllowance(address spender, uint256 addedValue) public returns (bool) {
_approve(msg.sender, spender, _allowed[msg.sender][spender].add(addedValue));
return true;
}
function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) {
_approve(msg.sender, spender, _allowed[msg.sender][spender].sub(subtractedValue));
return true;
}
function getHolders() public view returns(address[] memory) {
return _holders;
}
function _transfer(address from, address to, uint256 value) internal {
require(pause == false && stop == false, 'transfers paused or stopped');
require(to != address(0), 'to address can not be 0');
_circulatingSupply[to] = _circulatingSupply[to].add(value);
_circulatingSupply[from] = _circulatingSupply[from].add(value);
_balances[from] = _balances[from].sub(value);
_balances[to] = _balances[to].add(value);
if(!_isHolder[to]) {
_isHolder[to] = true;
_holders.push(to);
}
emit Transfer(from, to, value);
}
function _mint(address account, uint256 value) internal {
require(stopMint == false, 'mint stopped');
require(account != address(0), 'destination address can not be 0');
_totalSupply = _totalSupply.add(value);
_balances[account] = _balances[account].add(value);
if(!_isHolder[account]) {
_isHolder[account] = true;
_holders.push(account);
}
emit Transfer(address(0), account, value);
}
function _burn(address account, uint256 value) internal {
require(account != address(0), 'destination address can not be 0');
_totalSupply = _totalSupply.sub(value);
_balances[account] = _balances[account].sub(value);
emit Transfer(account, address(0), value);
}
function _approve(address owner, address spender, uint256 value) internal {
require(spender != address(0), 'spender can not be 0');
require(owner != address(0), 'owner can not be 0');
_allowed[owner][spender] = value;
emit Approval(owner, spender, value);
}
}
文件 3 的 7:IERC20.sol
pragma solidity 0.5.8;
interface IERC20 {
function transfer(address to, uint256 value) external returns (bool);
function approve(address spender, uint256 value) external returns (bool);
function transferFrom(address from, address to, uint256 value) external returns (bool);
function totalSupply() external view returns (uint256);
function balanceOf(address who) external view returns (uint256);
function allowance(address owner, address spender) external view returns (uint256);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}
文件 4 的 7:Ownable.sol
pragma solidity 0.5.8;
contract Ownable {
address private _owner;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
constructor() internal {
_owner = msg.sender;
emit OwnershipTransferred(address(0), _owner);
}
function owner() public view returns (address) {
return _owner;
}
modifier onlyOwner() {
require(isOwner(), "Must be owner");
_;
}
function isOwner() public view returns (bool) {
return msg.sender == _owner;
}
function renounceOwnership() public onlyOwner {
emit OwnershipTransferred(_owner, address(0));
_owner = address(0);
}
function transferOwnership(address newOwner) public onlyOwner {
_transferOwnership(newOwner);
}
function _transferOwnership(address newOwner) internal {
require(newOwner != address(0), "Cannot transfer to zero address");
emit OwnershipTransferred(_owner, newOwner);
_owner = newOwner;
}
}
文件 5 的 7:PermissionService.sol
pragma solidity 0.5.8;
import "./ERC20.sol";
contract PermissionService is ERC20 {
mapping (address => bool) public mintablePermission;
mapping (address => bool) public editRightsPermission;
mapping (address => bool) public recoveryTokensPermission;
mapping (address => bool) public attributesPermission;
mapping (address => bool) public burnPermission;
mapping (address => bool) public ethRatePermission;
mapping (address => bool) public gasPermission;
mapping (address => bool) internal _isAdded;
address[] internal addressesWithPermissions;
modifier onlyEditRightsPermission() {
require(editRightsPermission[msg.sender] || isOwner());
_;
}
modifier onlyEthRatePermission() {
require(ethRatePermission[msg.sender] || isOwner());
_;
}
modifier onlyGasPermission() {
require(gasPermission[msg.sender] || isOwner());
_;
}
modifier onlyBurnPermission() {
require(burnPermission[msg.sender] || isOwner());
_;
}
modifier onlyMintablePermission() {
require(mintablePermission[msg.sender] || recoveryTokensPermission[msg.sender] || isOwner());
_;
}
modifier onlyRecoveryTokensPermission() {
require(recoveryTokensPermission[msg.sender] || isOwner());
_;
}
modifier onlyAttributesPermission() {
require(attributesPermission[msg.sender] || isOwner());
_;
}
function addMintablePermission(address _address) public onlyEditRightsPermission {
if(_isAdded[_address] == false) {
addressesWithPermissions.push(_address);
_isAdded[_address] = true;
}
mintablePermission[_address] = true;
}
function addGasPermission(address _address) public onlyEditRightsPermission {
if(_isAdded[_address] == false) {
addressesWithPermissions.push(_address);
_isAdded[_address] = true;
}
gasPermission[_address] = true;
}
function addEthRatePermission(address _address) public onlyEditRightsPermission {
if(_isAdded[_address] == false) {
addressesWithPermissions.push(_address);
_isAdded[_address] = true;
}
ethRatePermission[_address] = true;
}
function addBurnPermission(address _address) public onlyEditRightsPermission {
if(_isAdded[_address] == false) {
addressesWithPermissions.push(_address);
_isAdded[_address] = true;
}
burnPermission[_address] = true;
}
function addEditRightsPermission(address _address) public onlyEditRightsPermission {
if(_isAdded[_address] == false) {
addressesWithPermissions.push(_address);
_isAdded[_address] = true;
}
editRightsPermission[_address] = true;
}
function addRecoveryTokensPermission(address _address) public onlyEditRightsPermission {
if(_isAdded[_address] == false) {
addressesWithPermissions.push(_address);
_isAdded[_address] = true;
}
recoveryTokensPermission[_address] = true;
}
function addAttributesPermission(address _address) public onlyEditRightsPermission {
if(_isAdded[_address] == false) {
addressesWithPermissions.push(_address);
_isAdded[_address] = true;
}
attributesPermission[_address] = true;
}
function removeMintablePermission(address _address) public onlyEditRightsPermission {
mintablePermission[_address] = false;
}
function removeEthRatePermission(address _address) public onlyEditRightsPermission {
ethRatePermission[_address] = false;
}
function removeGasPermission(address _address) public onlyEditRightsPermission {
gasPermission[_address] = false;
}
function removeBurnPermission(address _address) public onlyEditRightsPermission {
burnPermission[_address] = false;
}
function removeEditRightsPermission(address _address) public onlyEditRightsPermission {
editRightsPermission[_address] = false;
}
function removeRecoveryTokensPermission(address _address) public onlyEditRightsPermission {
recoveryTokensPermission[_address] = false;
}
function removeAttributesPermission(address _address) public onlyEditRightsPermission {
attributesPermission[_address] = false;
}
function getAddressesWithPermissions() public view returns(address[] memory) {
return addressesWithPermissions;
}
}
文件 6 的 7:SafeMath.sol
pragma solidity 0.5.8;
library SafeMath {
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
uint256 c = a * b;
require(c / a == b);
return c;
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
require(b > 0);
uint256 c = a / b;
return c;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
require(b <= a);
uint256 c = a - b;
return c;
}
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a);
return c;
}
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
require(b != 0);
return a % b;
}
}
文件 7 的 7:ScipayToken.sol
pragma solidity 0.5.8;
import "./PermissionService.sol";
contract ScipayToken is PermissionService {
string public name = "SCIPAY Token";
string public symbol = "SCIPAY";
uint8 public decimals = 18;
event TokensRecovered(address _from, address _to, uint _amount);
constructor() public {
_totalSupply = 0;
}
function changeSymbol(string memory _newSymbol) public onlyAttributesPermission {
symbol = _newSymbol;
}
function changename(string memory _newName) public onlyAttributesPermission {
name = _newName;
}
function transfer(address _to, uint _amount) public returns(bool) {
return super.transfer(_to, _amount);
}
function transferFrom(address _from, address _to, uint _amount) public returns(bool) {
return super.transferFrom(_from, _to, _amount);
}
function mint(address _for, uint _amount) public onlyMintablePermission {
_mint(_for, _amount);
}
function burn(address _from, uint _amount) public onlyBurnPermission {
_burn(_from, _amount);
}
function recoveryTokens(address _from, address _to) public onlyRecoveryTokensPermission {
uint balance = balanceOf(_from);
_burn(_from, balance);
mint(_to, balance);
emit TokensRecovered(_from, _to, balance);
}
function setEthRate(uint256 newEthRate) public onlyEthRatePermission {
require (newEthRate > 0);
ethRate = newEthRate;
}
function setGasForTransfer(uint256 newGasForTransfer) public onlyGasPermission {
require (newGasForTransfer > 0);
gasForTransfer = newGasForTransfer;
}
}
{
"compilationTarget": {
"ScipayToken.sol": "ScipayToken"
},
"evmVersion": "petersburg",
"libraries": {},
"optimizer": {
"enabled": false,
"runs": 200
},
"remappings": []
}
[{"constant":false,"inputs":[{"name":"_address","type":"address"}],"name":"removeBurnPermission","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"stop","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"spender","type":"address"},{"name":"value","type":"uint256"}],"name":"approve","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"to","type":"address"},{"name":"value","type":"uint256"},{"name":"token","type":"string"}],"name":"transferFeeless","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"burnPermission","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"recoveryTokensPermission","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_address","type":"address"}],"name":"removeEditRightsPermission","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_amount","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"attributesPermission","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"mintablePermission","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint8"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_address","type":"address"}],"name":"addMintablePermission","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_address","type":"address"}],"name":"addBurnPermission","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"spender","type":"address"},{"name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_for","type":"address"},{"name":"_amount","type":"uint256"}],"name":"mint","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_address","type":"address"}],"name":"addGasPermission","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_newName","type":"string"}],"name":"changename","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"sender","type":"address"},{"name":"target","type":"address"},{"name":"data","type":"bytes"},{"name":"nonce","type":"uint256"},{"name":"sig","type":"bytes"}],"name":"performFeelessTransaction","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[{"name":"_address","type":"address"}],"name":"removeRecoveryTokensPermission","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_address","type":"address"}],"name":"removeEthRatePermission","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getHolders","outputs":[{"name":"","type":"address[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_address","type":"address"}],"name":"addEditRightsPermission","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_address","type":"address"}],"name":"addEthRatePermission","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"newEthRate","type":"uint256"}],"name":"setEthRate","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"renounceOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"gasPermission","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"stopTransfers","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"editRightsPermission","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"pause","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_address","type":"address"}],"name":"addAttributesPermission","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"isOwner","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"getAddressesWithPermissions","outputs":[{"name":"","type":"address[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_amount","type":"uint256"}],"name":"burn","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_newSymbol","type":"string"}],"name":"changeSymbol","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"spender","type":"address"},{"name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_amount","type":"uint256"}],"name":"transfer","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"}],"name":"recoveryTokens","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"ethRate","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"stopMint","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_address","type":"address"}],"name":"removeMintablePermission","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_address","type":"address"}],"name":"addRecoveryTokensPermission","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"stopMintForever","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"owner","type":"address"},{"name":"spender","type":"address"}],"name":"allowance","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"newGasForTransfer","type":"uint256"}],"name":"setGasForTransfer","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_address","type":"address"}],"name":"removeAttributesPermission","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_address","type":"address"}],"name":"removeGasPermission","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"ethRatePermission","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"newPauseVal","type":"bool"}],"name":"setPauseTransfers","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"gasForTransfer","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"name":"_from","type":"address"},{"indexed":false,"name":"_to","type":"address"},{"indexed":false,"name":"_amount","type":"uint256"}],"name":"TokensRecovered","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"previousOwner","type":"address"},{"indexed":true,"name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"owner","type":"address"},{"indexed":true,"name":"spender","type":"address"},{"indexed":false,"name":"value","type":"uint256"}],"name":"Approval","type":"event"}]