Transaction Hash:
Block:
6354524 at Sep-18-2018 12:59:14 PM +UTC
Transaction Fee:
0.000370044 ETH
$0.73
Gas Used:
41,116 Gas / 9 Gwei
Emitted Events:
| 78 |
NeoWorldCash.Transfer( from=[Sender] 0x7a7dfbfa7c8e69810a34d2ce7af3b522daf673d8, to=0x6578e890fCc3A5B6edE03256c728bc211915C827, tokens=800000000000000000000000 )
|
| 79 |
NeoWorldCash.Transfer( from=[Sender] 0x7a7dfbfa7c8e69810a34d2ce7af3b522daf673d8, to=0x6578e890fCc3A5B6edE03256c728bc211915C827, value=800000000000000000000000, data=0x )
|
Account State Difference:
| Address | Before | After | State Difference | ||
|---|---|---|---|---|---|
| 0x4b94c856...206383b75 | |||||
|
0x5A0b54D5...D3E029c4c
Miner
| (Spark Pool) | 3,438.125377417725410858 Eth | 3,438.125747461725410858 Eth | 0.000370044 | |
| 0x7a7dfBFa...2DAF673D8 |
0.485127569236397319 Eth
Nonce: 141
|
0.484757525236397319 Eth
Nonce: 142
| 0.000370044 |
Execution Trace
NeoWorldCash.transfer( _to=0x6578e890fCc3A5B6edE03256c728bc211915C827, _value=800000000000000000000000 ) => ( True )
transfer[NeoWorldCash (ln:223)]
isContract[NeoWorldCash (ln:225)]transferToContract[NeoWorldCash (ln:226)]sub[NeoWorldCash (ln:262)]balanceOf[NeoWorldCash (ln:262)]add[NeoWorldCash (ln:263)]balanceOf[NeoWorldCash (ln:263)]tokenFallback[NeoWorldCash (ln:265)]Transfer[NeoWorldCash (ln:266)]Transfer[NeoWorldCash (ln:267)]
transferToAddress[NeoWorldCash (ln:229)]sub[NeoWorldCash (ln:253)]balanceOf[NeoWorldCash (ln:253)]add[NeoWorldCash (ln:254)]balanceOf[NeoWorldCash (ln:254)]Transfer[NeoWorldCash (ln:255)]Transfer[NeoWorldCash (ln:256)]
pragma solidity 0.4.21;
// ----------------------------------------------------------------------------
// Owned contract
// ----------------------------------------------------------------------------
contract Ownable {
address public owner;
address public newOwner;
event OwnershipTransferred(address indexed _from, address indexed _to);
function Ownable() public {
owner = msg.sender;
}
modifier onlyOwner {
require(msg.sender == owner);
_;
}
function transferOwnership(address _newOwner) public onlyOwner {
newOwner = _newOwner;
}
function acceptOwnership() public {
require(msg.sender == newOwner);
emit OwnershipTransferred(owner, newOwner);
owner = newOwner;
newOwner = address(0);
}
}
contract Pausable is Ownable {
event Pause();
event Unpause();
bool public paused = false;
/**
* @dev modifier to allow actions only when the contract IS paused
*/
modifier whenNotPaused() {
require(!paused);
_;
}
/**
* @dev modifier to allow actions only when the contract IS NOT paused
*/
modifier whenPaused {
require(paused);
_;
}
/**
* @dev called by the owner to pause, triggers stopped state
*/
function pause() onlyOwner whenNotPaused public returns (bool) {
paused = true;
emit Pause();
return true;
}
/**
* @dev called by the owner to unpause, returns to normal state
*/
function unpause() onlyOwner whenPaused public returns (bool) {
paused = false;
emit Unpause();
return true;
}
}
/**
* @title SafeMath
* @dev Math operations with safety checks that throw on error
*/
library SafeMath {
/**
* @dev Multiplies two numbers, throws on overflow.
*/
function mul(uint256 a, uint256 b) internal pure returns (uint256 c) {
if (a == 0) {
return 0;
}
c = a * b;
assert(c / a == b);
return c;
}
/**
* @dev Integer division of two numbers, truncating the quotient.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
// assert(b > 0); // Solidity automatically throws when dividing by 0
// uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return a / b;
}
/**
* @dev Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend).
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
assert(b <= a);
return a - b;
}
/**
* @dev Adds two numbers, throws on overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256 c) {
c = a + b;
assert(c >= a);
return c;
}
}
library ContractLib {
//assemble the given address bytecode. If bytecode exists then the _addr is a contract.
function isContract(address _addr) internal view returns (bool) {
uint length;
assembly {
//retrieve the size of the code on target address, this needs assembly
length := extcodesize(_addr)
}
return (length>0);
}
}
/*
* Contract that is working with ERC223 tokens
*/
contract ContractReceiver {
function tokenFallback(address _from, uint _value, bytes _data) public pure;
}
// ----------------------------------------------------------------------------
// ERC Token Standard #20 Interface
// https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20-token-standard.md
// ----------------------------------------------------------------------------
contract ERC20Interface {
function totalSupply() public constant returns (uint);
function balanceOf(address tokenOwner) public constant returns (uint);
function allowance(address tokenOwner, address spender) public constant returns (uint);
function transfer(address to, uint tokens) public returns (bool);
function approve(address spender, uint tokens) public returns (bool);
function transferFrom(address from, address to, uint tokens) public returns (bool);
function name() public constant returns (string);
function symbol() public constant returns (string);
function decimals() public constant returns (uint8);
event Transfer(address indexed from, address indexed to, uint tokens);
event Approval(address indexed tokenOwner, address indexed spender, uint tokens);
}
/**
* ERC223 token by Dexaran
*
* https://github.com/Dexaran/ERC223-token-standard
*/
/* New ERC223 contract interface */
contract ERC223 is ERC20Interface {
function transfer(address to, uint value, bytes data) public returns (bool);
event Transfer(address indexed from, address indexed to, uint tokens);
event Transfer(address indexed from, address indexed to, uint value, bytes data);
}
contract NeoWorldCash is ERC223, Pausable {
using SafeMath for uint256;
using ContractLib for address;
mapping(address => uint) balances;
mapping(address => mapping(address => uint)) allowed;
string public name;
string public symbol;
uint8 public decimals;
uint256 public totalSupply;
event Burn(address indexed from, uint256 value);
// ------------------------------------------------------------------------
// Constructor
// ------------------------------------------------------------------------
function NeoWorldCash() public {
symbol = "NASH";
name = "NEOWORLD CASH";
decimals = 18;
totalSupply = 100000000000 * 10**uint(decimals);
balances[msg.sender] = totalSupply;
emit Transfer(address(0), msg.sender, totalSupply);
}
// Function to access name of token .
function name() public constant returns (string) {
return name;
}
// Function to access symbol of token .
function symbol() public constant returns (string) {
return symbol;
}
// Function to access decimals of token .
function decimals() public constant returns (uint8) {
return decimals;
}
// Function to access total supply of tokens .
function totalSupply() public constant returns (uint256) {
return totalSupply;
}
// Function that is called when a user or another contract wants to transfer funds .
function transfer(address _to, uint _value, bytes _data) public whenNotPaused returns (bool) {
require(_to != 0x0);
if(_to.isContract()) {
return transferToContract(_to, _value, _data);
}
else {
return transferToAddress(_to, _value, _data);
}
}
// Standard function transfer similar to ERC20 transfer with no _data .
// Added due to backwards compatibility reasons .
function transfer(address _to, uint _value) public whenNotPaused returns (bool) {
//standard function transfer similar to ERC20 transfer with no _data
//added due to backwards compatibility reasons
require(_to != 0x0);
bytes memory empty;
if(_to.isContract()) {
return transferToContract(_to, _value, empty);
}
else {
return transferToAddress(_to, _value, empty);
}
}
//function that is called when transaction target is an address
function transferToAddress(address _to, uint _value, bytes _data) private returns (bool) {
balances[msg.sender] = balanceOf(msg.sender).sub(_value);
balances[_to] = balanceOf(_to).add(_value);
emit Transfer(msg.sender, _to, _value);
emit Transfer(msg.sender, _to, _value, _data);
return true;
}
//function that is called when transaction target is a contract
function transferToContract(address _to, uint _value, bytes _data) private returns (bool success) {
balances[msg.sender] = balanceOf(msg.sender).sub(_value);
balances[_to] = balanceOf(_to).add(_value);
ContractReceiver receiver = ContractReceiver(_to);
receiver.tokenFallback(msg.sender, _value, _data);
emit Transfer(msg.sender, _to, _value);
emit Transfer(msg.sender, _to, _value, _data);
return true;
}
function balanceOf(address _owner) public constant returns (uint) {
return balances[_owner];
}
function burn(uint256 _value) public whenNotPaused returns (bool) {
require (_value > 0);
require (balanceOf(msg.sender) >= _value); // Check if the sender has enough
balances[msg.sender] = balanceOf(msg.sender).sub(_value); // Subtract from the sender
totalSupply = totalSupply.sub(_value); // Updates totalSupply
emit Burn(msg.sender, _value);
return true;
}
// ------------------------------------------------------------------------
// Token owner can approve for `spender` to transferFrom(...) `tokens`
// from the token owner's account
//
// https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20-token-standard.md
// recommends that there are no checks for the approval double-spend attack
// as this should be implemented in user interfaces
// ------------------------------------------------------------------------
function approve(address spender, uint tokens) public whenNotPaused returns (bool) {
allowed[msg.sender][spender] = tokens;
emit Approval(msg.sender, spender, tokens);
return true;
}
function increaseApproval (address _spender, uint _addedValue) public whenNotPaused
returns (bool success) {
allowed[msg.sender][_spender] = allowed[msg.sender][_spender].add(_addedValue);
emit Approval(msg.sender, _spender, allowed[msg.sender][_spender]);
return true;
}
function decreaseApproval (address _spender, uint _subtractedValue) public whenNotPaused
returns (bool success) {
uint oldValue = allowed[msg.sender][_spender];
if (_subtractedValue > oldValue) {
allowed[msg.sender][_spender] = 0;
} else {
allowed[msg.sender][_spender] = oldValue.sub(_subtractedValue);
}
emit Approval(msg.sender, _spender, allowed[msg.sender][_spender]);
return true;
}
// ------------------------------------------------------------------------
// Transfer `tokens` from the `from` account to the `to` account
//
// The calling account must already have sufficient tokens approve(...)-d
// for spending from the `from` account and
// - From account must have sufficient balance to transfer
// - Spender must have sufficient allowance to transfer
// - 0 value transfers are allowed
// ------------------------------------------------------------------------
function transferFrom(address from, address to, uint tokens) public whenNotPaused returns (bool) {
allowed[from][msg.sender] = allowed[from][msg.sender].sub(tokens);
balances[from] = balances[from].sub(tokens);
balances[to] = balances[to].add(tokens);
emit Transfer(from, to, tokens);
return true;
}
// ------------------------------------------------------------------------
// Returns the amount of tokens approved by the owner that can be
// transferred to the spender's account
// ------------------------------------------------------------------------
function allowance(address tokenOwner, address spender) public constant returns (uint) {
return allowed[tokenOwner][spender];
}
// ------------------------------------------------------------------------
// Don't accept ETH
// ------------------------------------------------------------------------
function () public payable {
revert();
}
// ------------------------------------------------------------------------
// Owner can transfer out any accidentally sent ERC20 tokens
// ------------------------------------------------------------------------
function transferAnyERC20Token(address tokenAddress, uint tokens) public onlyOwner returns (bool) {
return ERC20Interface(tokenAddress).transfer(owner, tokens);
}
/* RO Token 预售 */
/*
预售的操作流程:
1. 发行需要的新的ERC20 Token
2. 将此Token的预售份额转入本合约地址
3. 设定预售时间和价格
4. 用户可以用过 joinPreSale 函数参加预售,卖完,逾期或者主动结束为止
5. 管理员把预售的到的Nash转出
MISC:因为必须制作预售页面通过MetaMask调用函数所以不存在交易所地址转账的问题。
MISC:外部项目无法自行使用本预售功能
*/
address[] supportedERC20Token;
mapping (address => bool) tokenSupported;
mapping (address => uint256) prices;
mapping (address => uint256) starttime;
mapping (address => uint256) endtime;
uint256 maxTokenCountPerTrans = 10000;
uint256 nashInPool;
event AddSupportedToken(
address _address,
uint256 _price,
uint256 _startTime,
uint256 _endTime);
event RemoveSupportedToken(
address _address
);
function addSupportedToken(
address _address,
uint256 _price,
uint256 _startTime,
uint256 _endTime
) public onlyOwner returns (bool) {
require(_address != 0x0);
require(_address.isContract());
require(_startTime < _endTime);
require(_price > 0);
require(_endTime > block.timestamp);
for (uint256 i = 0; i < supportedERC20Token.length; i++) {
require(supportedERC20Token[i] != _address);
}
supportedERC20Token.push(_address);
tokenSupported[_address] = true;
prices[_address] = _price;
starttime[_address] = _startTime;
endtime[_address] = _endTime;
emit AddSupportedToken(_address, _price, _startTime, _endTime);
return true;
}
function removeSupportedToken(address _address) public onlyOwner returns (bool) {
require(_address != 0x0);
uint256 length = supportedERC20Token.length;
for (uint256 i = 0; i < length; i++) {
if (supportedERC20Token[i] == _address) {
if (i != length - 1) {
supportedERC20Token[i] = supportedERC20Token[length - 1];
}
delete supportedERC20Token[length-1];
supportedERC20Token.length--;
prices[_address] = 0;
starttime[_address] = 0;
endtime[_address] = 0;
tokenSupported[_address] = false;
emit RemoveSupportedToken(_address);
break;
}
}
return true;
}
modifier canBuy(address _address) {
require(tokenSupported[_address]);
require(block.timestamp > starttime[_address]);
require(block.timestamp < endtime[_address]);
_;
}
function joinPreSale(address _tokenAddress, uint256 _tokenCount) public canBuy(_tokenAddress) returns (bool) {
require(prices[_tokenAddress] > 0);
uint256 total = _tokenCount.mul(prices[_tokenAddress]); // will not overflow here since the price will not be high
balances[msg.sender] = balances[msg.sender].sub(total);
nashInPool = nashInPool.add(total);
require(ERC20Interface(_tokenAddress).transfer(msg.sender, _tokenCount));
emit Transfer(msg.sender, this, total);
return true;
}
function transferNashOut(address _to, uint256 count) public onlyOwner returns(bool) {
require(_to != 0x0);
nashInPool = nashInPool.sub(count);
balances[_to] = balances[_to].add(count);
emit Transfer(this, _to, count);
return true;
}
function getSupportedTokens() public view returns (address[]) {
return supportedERC20Token;
}
function getTokenStatus(address _tokenAddress) public view returns (uint256 _starttime, uint256 _endtime, uint256 _price) {
_starttime = starttime[_tokenAddress];
_endtime = endtime[_tokenAddress];
_price = prices[_tokenAddress];
}
/* end of 预售逻辑 */
/* 锁币逻辑 */
// 此功能仅供项目组账号使用,使用后锁住自己的币且不能修改
mapping(address => uint256) lockedBalanceTotal;
mapping(address => uint256) lockedStartTime;
mapping(address => uint256) unlockPeriod;
mapping(address => uint256) unlockNumberOfCycles;
mapping(address => uint256) lockedBalanceRemains;
mapping(address => uint256) cyclesUnlocked;
mapping(address => bool) addressAllowToLock;
event Locked (address _address, uint256 _count, uint256 _starttime, uint256 _unlockPeriodInSeconds, uint256 _unlockNumberOfCycles);
event Unlocked (address _address, uint256 _count);
function allowToLock(address _address) public onlyOwner {
require(_address != 0x0);
addressAllowToLock[_address] = true;
}
function disallowToLock(address _address) public onlyOwner {
require(_address != 0x0);
addressAllowToLock[_address] = false;
}
function lock(uint256 _count, uint256 _starttime, uint256 _unlockPeriodInSeconds, uint256 _unlockNumberOfCycles) public returns (bool) {
require(addressAllowToLock[msg.sender]);
require(lockedStartTime[msg.sender] == 0);
require(0 < _unlockNumberOfCycles && _unlockNumberOfCycles <= 10);
require(_unlockPeriodInSeconds > 0);
require(_count > 10000);
require(_starttime > 0);
balances[msg.sender] = balances[msg.sender].sub(_count);
lockedBalanceTotal[msg.sender] = _count;
lockedStartTime[msg.sender] = _starttime;
unlockPeriod[msg.sender] = _unlockPeriodInSeconds;
unlockNumberOfCycles[msg.sender] = _unlockNumberOfCycles;
lockedBalanceRemains[msg.sender] = lockedBalanceTotal[msg.sender];
emit Locked (msg.sender, _count, _starttime, _unlockPeriodInSeconds, _unlockNumberOfCycles);
return true;
}
function tryUnlock() public returns (bool) {
require(lockedBalanceRemains[msg.sender] > 0);
uint256 cycle = (block.timestamp.sub(lockedStartTime[msg.sender])) / unlockPeriod[msg.sender];
require(cycle > cyclesUnlocked[msg.sender]);
if (cycle > unlockNumberOfCycles[msg.sender]) {
cycle = unlockNumberOfCycles[msg.sender];
}
uint256 amount = lockedBalanceTotal[msg.sender].mul(cycle - cyclesUnlocked[msg.sender]) / unlockNumberOfCycles[msg.sender] ;
lockedBalanceRemains[msg.sender] = lockedBalanceRemains[msg.sender].sub(amount);
balances[msg.sender] = balances[msg.sender].add(amount);
if (cycle == unlockNumberOfCycles[msg.sender]) {
// cleanup
lockedBalanceTotal[msg.sender] = 0;
lockedStartTime[msg.sender] = 0;
unlockPeriod[msg.sender] = 0;
unlockNumberOfCycles[msg.sender] = 0;
cyclesUnlocked[msg.sender] = 0;
if (lockedBalanceRemains[msg.sender] > 0) {
balances[msg.sender] = balances[msg.sender].add(lockedBalanceRemains[msg.sender]);
lockedBalanceRemains[msg.sender] = 0;
}
}
else {
cyclesUnlocked[msg.sender] = cycle;
}
emit Unlocked(msg.sender, amount);
return true;
}
function getLockStatus(address _address) public view returns (
uint256 _lockTotal,
uint256 _starttime,
uint256 _unlockPeriodInSeconds,
uint256 _unlockNumberOfCycles,
uint256 _lockedBalanceRemains,
uint256 _cyclesUnlocked
) {
_lockTotal = lockedBalanceTotal[_address];
_starttime = lockedStartTime[_address];
_unlockPeriodInSeconds = unlockPeriod[_address];
_unlockNumberOfCycles = unlockNumberOfCycles[_address];
_lockedBalanceRemains = lockedBalanceRemains[_address];
_cyclesUnlocked = cyclesUnlocked[_address];
}
}