Transaction Hash:
Block:
5732480 at Jun-04-2018 07:34:49 PM +UTC
Transaction Fee:
0.000944656 ETH
$2.20
Gas Used:
59,041 Gas / 16 Gwei
Emitted Events:
| 224 |
Token.Transfer( _from=[Sender] 0x87be059c1e6c893934c5adcd5e39a0bef26f395d, _to=[Receiver] Exchange, _value=50000 )
|
| 225 |
Exchange.Deposit( token=Token, user=[Sender] 0x87be059c1e6c893934c5adcd5e39a0bef26f395d, amount=50000, balance=50000 )
|
Account State Difference:
| Address | Before | After | State Difference | ||
|---|---|---|---|---|---|
| 0x2a0c0DBE...44050c208 | (IDEX) | ||||
| 0x5554e04e...d329E1E30 | |||||
| 0x87Be059c...EF26f395D |
0.031895588093994784 Eth
Nonce: 25
|
0.030950932093994784 Eth
Nonce: 26
| 0.000944656 | ||
|
0xFA927F19...7ef77Bb26
Miner
| 5.531693390992302733 Eth | 5.532638046992302733 Eth | 0.000944656 |
Execution Trace
Exchange.depositToken( token=0x5554e04e76533E1d14c52f05beEF6c9d329E1E30, amount=50000 )
-
Token.transferFrom( _from=0x87Be059c1E6c893934C5aDCD5e39A0bEF26f395D, _to=0x2a0c0DBEcC7E4D658f48E01e3fA353F44050c208, _amount=50000 ) => ( success=True )
depositToken[Exchange (ln:97)]
safeAdd[Exchange (ln:98)]transferFrom[Exchange (ln:100)]Deposit[Exchange (ln:101)]
File 1 of 2: Exchange
File 2 of 2: Token
pragma solidity ^0.4.16;
contract Token {
bytes32 public standard;
bytes32 public name;
bytes32 public symbol;
uint256 public totalSupply;
uint8 public decimals;
bool public allowTransactions;
mapping (address => uint256) public balanceOf;
mapping (address => mapping (address => uint256)) public allowance;
function transfer(address _to, uint256 _value) returns (bool success);
function approveAndCall(address _spender, uint256 _value, bytes _extraData) returns (bool success);
function approve(address _spender, uint256 _value) returns (bool success);
function transferFrom(address _from, address _to, uint256 _value) returns (bool success);
}
contract Exchange {
function assert(bool assertion) {
if (!assertion) throw;
}
function safeMul(uint a, uint b) returns (uint) {
uint c = a * b;
assert(a == 0 || c / a == b);
return c;
}
function safeSub(uint a, uint b) returns (uint) {
assert(b <= a);
return a - b;
}
function safeAdd(uint a, uint b) returns (uint) {
uint c = a + b;
assert(c>=a && c>=b);
return c;
}
address public owner;
mapping (address => uint256) public invalidOrder;
event SetOwner(address indexed previousOwner, address indexed newOwner);
modifier onlyOwner {
assert(msg.sender == owner);
_;
}
function setOwner(address newOwner) onlyOwner {
SetOwner(owner, newOwner);
owner = newOwner;
}
function getOwner() returns (address out) {
return owner;
}
function invalidateOrdersBefore(address user, uint256 nonce) onlyAdmin {
if (nonce < invalidOrder[user]) throw;
invalidOrder[user] = nonce;
}
mapping (address => mapping (address => uint256)) public tokens; //mapping of token addresses to mapping of account balances
mapping (address => bool) public admins;
mapping (address => uint256) public lastActiveTransaction;
mapping (bytes32 => uint256) public orderFills;
address public feeAccount;
uint256 public inactivityReleasePeriod;
mapping (bytes32 => bool) public traded;
mapping (bytes32 => bool) public withdrawn;
event Order(address tokenBuy, uint256 amountBuy, address tokenSell, uint256 amountSell, uint256 expires, uint256 nonce, address user, uint8 v, bytes32 r, bytes32 s);
event Cancel(address tokenBuy, uint256 amountBuy, address tokenSell, uint256 amountSell, uint256 expires, uint256 nonce, address user, uint8 v, bytes32 r, bytes32 s);
event Trade(address tokenBuy, uint256 amountBuy, address tokenSell, uint256 amountSell, address get, address give);
event Deposit(address token, address user, uint256 amount, uint256 balance);
event Withdraw(address token, address user, uint256 amount, uint256 balance);
function setInactivityReleasePeriod(uint256 expiry) onlyAdmin returns (bool success) {
if (expiry > 1000000) throw;
inactivityReleasePeriod = expiry;
return true;
}
function Exchange(address feeAccount_) {
owner = msg.sender;
feeAccount = feeAccount_;
inactivityReleasePeriod = 100000;
}
function setAdmin(address admin, bool isAdmin) onlyOwner {
admins[admin] = isAdmin;
}
modifier onlyAdmin {
if (msg.sender != owner && !admins[msg.sender]) throw;
_;
}
function() external {
throw;
}
function depositToken(address token, uint256 amount) {
tokens[token][msg.sender] = safeAdd(tokens[token][msg.sender], amount);
lastActiveTransaction[msg.sender] = block.number;
if (!Token(token).transferFrom(msg.sender, this, amount)) throw;
Deposit(token, msg.sender, amount, tokens[token][msg.sender]);
}
function deposit() payable {
tokens[address(0)][msg.sender] = safeAdd(tokens[address(0)][msg.sender], msg.value);
lastActiveTransaction[msg.sender] = block.number;
Deposit(address(0), msg.sender, msg.value, tokens[address(0)][msg.sender]);
}
function withdraw(address token, uint256 amount) returns (bool success) {
if (safeSub(block.number, lastActiveTransaction[msg.sender]) < inactivityReleasePeriod) throw;
if (tokens[token][msg.sender] < amount) throw;
tokens[token][msg.sender] = safeSub(tokens[token][msg.sender], amount);
if (token == address(0)) {
if (!msg.sender.send(amount)) throw;
} else {
if (!Token(token).transfer(msg.sender, amount)) throw;
}
Withdraw(token, msg.sender, amount, tokens[token][msg.sender]);
}
function adminWithdraw(address token, uint256 amount, address user, uint256 nonce, uint8 v, bytes32 r, bytes32 s, uint256 feeWithdrawal) onlyAdmin returns (bool success) {
bytes32 hash = keccak256(this, token, amount, user, nonce);
if (withdrawn[hash]) throw;
withdrawn[hash] = true;
if (ecrecover(keccak256("\x19Ethereum Signed Message:\n32", hash), v, r, s) != user) throw;
if (feeWithdrawal > 50 finney) feeWithdrawal = 50 finney;
if (tokens[token][user] < amount) throw;
tokens[token][user] = safeSub(tokens[token][user], amount);
tokens[token][feeAccount] = safeAdd(tokens[token][feeAccount], safeMul(feeWithdrawal, amount) / 1 ether);
amount = safeMul((1 ether - feeWithdrawal), amount) / 1 ether;
if (token == address(0)) {
if (!user.send(amount)) throw;
} else {
if (!Token(token).transfer(user, amount)) throw;
}
lastActiveTransaction[user] = block.number;
Withdraw(token, user, amount, tokens[token][user]);
}
function balanceOf(address token, address user) constant returns (uint256) {
return tokens[token][user];
}
function trade(uint256[8] tradeValues, address[4] tradeAddresses, uint8[2] v, bytes32[4] rs) onlyAdmin returns (bool success) {
/* amount is in amountBuy terms */
/* tradeValues
[0] amountBuy
[1] amountSell
[2] expires
[3] nonce
[4] amount
[5] tradeNonce
[6] feeMake
[7] feeTake
tradeAddressses
[0] tokenBuy
[1] tokenSell
[2] maker
[3] taker
*/
if (invalidOrder[tradeAddresses[2]] > tradeValues[3]) throw;
bytes32 orderHash = keccak256(this, tradeAddresses[0], tradeValues[0], tradeAddresses[1], tradeValues[1], tradeValues[2], tradeValues[3], tradeAddresses[2]);
if (ecrecover(keccak256("\x19Ethereum Signed Message:\n32", orderHash), v[0], rs[0], rs[1]) != tradeAddresses[2]) throw;
bytes32 tradeHash = keccak256(orderHash, tradeValues[4], tradeAddresses[3], tradeValues[5]);
if (ecrecover(keccak256("\x19Ethereum Signed Message:\n32", tradeHash), v[1], rs[2], rs[3]) != tradeAddresses[3]) throw;
if (traded[tradeHash]) throw;
traded[tradeHash] = true;
if (tradeValues[6] > 100 finney) tradeValues[6] = 100 finney;
if (tradeValues[7] > 100 finney) tradeValues[7] = 100 finney;
if (safeAdd(orderFills[orderHash], tradeValues[4]) > tradeValues[0]) throw;
if (tokens[tradeAddresses[0]][tradeAddresses[3]] < tradeValues[4]) throw;
if (tokens[tradeAddresses[1]][tradeAddresses[2]] < (safeMul(tradeValues[1], tradeValues[4]) / tradeValues[0])) throw;
tokens[tradeAddresses[0]][tradeAddresses[3]] = safeSub(tokens[tradeAddresses[0]][tradeAddresses[3]], tradeValues[4]);
tokens[tradeAddresses[0]][tradeAddresses[2]] = safeAdd(tokens[tradeAddresses[0]][tradeAddresses[2]], safeMul(tradeValues[4], ((1 ether) - tradeValues[6])) / (1 ether));
tokens[tradeAddresses[0]][feeAccount] = safeAdd(tokens[tradeAddresses[0]][feeAccount], safeMul(tradeValues[4], tradeValues[6]) / (1 ether));
tokens[tradeAddresses[1]][tradeAddresses[2]] = safeSub(tokens[tradeAddresses[1]][tradeAddresses[2]], safeMul(tradeValues[1], tradeValues[4]) / tradeValues[0]);
tokens[tradeAddresses[1]][tradeAddresses[3]] = safeAdd(tokens[tradeAddresses[1]][tradeAddresses[3]], safeMul(safeMul(((1 ether) - tradeValues[7]), tradeValues[1]), tradeValues[4]) / tradeValues[0] / (1 ether));
tokens[tradeAddresses[1]][feeAccount] = safeAdd(tokens[tradeAddresses[1]][feeAccount], safeMul(safeMul(tradeValues[7], tradeValues[1]), tradeValues[4]) / tradeValues[0] / (1 ether));
orderFills[orderHash] = safeAdd(orderFills[orderHash], tradeValues[4]);
lastActiveTransaction[tradeAddresses[2]] = block.number;
lastActiveTransaction[tradeAddresses[3]] = block.number;
}
}File 2 of 2: Token
pragma solidity ^0.4.15;
contract Token {
mapping (address => uint256) public balanceOf;
mapping (uint256 => address) public addresses;
mapping (address => bool) public addressExists;
mapping (address => uint256) public addressIndex;
mapping(address => mapping (address => uint256)) allowed;
uint256 public numberOfAddress = 0;
string public physicalString;
string public cryptoString;
bool public isSecured;
string public name;
string public symbol;
uint256 public totalSupply;
bool public canMintBurn;
uint256 public txnTax;
uint256 public holdingTax;
//In Weeks, on Fridays
uint256 public holdingTaxInterval;
uint256 public lastHoldingTax;
uint256 public holdingTaxDecimals = 2;
bool public isPrivate;
address public owner;
function Token(string n, string a, uint256 totalSupplyToUse, bool isSecured, bool cMB, string physical, string crypto, uint256 txnTaxToUse, uint256 holdingTaxToUse, uint256 holdingTaxIntervalToUse, bool isPrivateToUse) {
name = n;
symbol = a;
totalSupply = totalSupplyToUse;
balanceOf[msg.sender] = totalSupplyToUse;
isSecured = isSecured;
physicalString = physical;
cryptoString = crypto;
canMintBurn = cMB;
owner = msg.sender;
txnTax = txnTaxToUse;
holdingTax = holdingTaxToUse;
holdingTaxInterval = holdingTaxIntervalToUse;
if(holdingTaxInterval!=0) {
lastHoldingTax = now;
while(getHour(lastHoldingTax)!=21) {
lastHoldingTax -= 1 hours;
}
while(getWeekday(lastHoldingTax)!=5) {
lastHoldingTax -= 1 days;
}
lastHoldingTax -= getMinute(lastHoldingTax) * (1 minutes) + getSecond(lastHoldingTax) * (1 seconds);
}
isPrivate = isPrivateToUse;
addAddress(owner);
}
function transfer(address _to, uint256 _value) payable returns (bool success) {
chargeHoldingTax();
if (balanceOf[msg.sender] < _value) return false;
if (balanceOf[_to] + _value < balanceOf[_to]) return false;
if (msg.sender != owner && _to != owner && txnTax != 0) {
if(!owner.send(txnTax)) {
return false;
}
}
if(isPrivate && msg.sender != owner && !addressExists[_to]) {
return false;
}
balanceOf[msg.sender] -= _value;
balanceOf[_to] += _value;
addAddress(_to);
Transfer(msg.sender, _to, _value);
return true;
}
function transferFrom(
address _from,
address _to,
uint256 _amount
) payable returns (bool success) {
if (_from != owner && _to != owner && txnTax != 0) {
if(!owner.send(txnTax)) {
return false;
}
}
if(isPrivate && _from != owner && !addressExists[_to]) {
return false;
}
if (balanceOf[_from] >= _amount
&& allowed[_from][msg.sender] >= _amount
&& _amount > 0
&& balanceOf[_to] + _amount > balanceOf[_to]) {
balanceOf[_from] -= _amount;
allowed[_from][msg.sender] -= _amount;
balanceOf[_to] += _amount;
Transfer(_from, _to, _amount);
return true;
} else {
return false;
}
}
function approve(address _spender, uint256 _amount) returns (bool success) {
allowed[msg.sender][_spender] = _amount;
Approval(msg.sender, _spender, _amount);
return true;
}
function allowance(address _owner, address _spender) constant returns (uint256 remaining) {
return allowed[_owner][_spender];
}
function changeTxnTax(uint256 _newValue) {
if(msg.sender != owner) throw;
txnTax = _newValue;
}
function mint(uint256 _value) {
if(canMintBurn && msg.sender == owner) {
if (balanceOf[msg.sender] + _value < balanceOf[msg.sender]) throw;
balanceOf[msg.sender] += _value;
totalSupply += _value;
Transfer(0, msg.sender, _value);
}
}
function burn(uint256 _value) {
if(canMintBurn && msg.sender == owner) {
if (balanceOf[msg.sender] < _value) throw;
balanceOf[msg.sender] -= _value;
totalSupply -= _value;
Transfer(msg.sender, 0, _value);
}
}
function chargeHoldingTax() {
if(holdingTaxInterval!=0) {
uint256 dateDif = now - lastHoldingTax;
bool changed = false;
while(dateDif >= holdingTaxInterval * (1 weeks)) {
changed=true;
dateDif -= holdingTaxInterval * (1 weeks);
for(uint256 i = 0;i<numberOfAddress;i++) {
if(addresses[i]!=owner) {
uint256 amtOfTaxToPay = ((balanceOf[addresses[i]]) * holdingTax) / (10**holdingTaxDecimals)/ (10**holdingTaxDecimals);
balanceOf[addresses[i]] -= amtOfTaxToPay;
balanceOf[owner] += amtOfTaxToPay;
}
}
}
if(changed) {
lastHoldingTax = now;
while(getHour(lastHoldingTax)!=21) {
lastHoldingTax -= 1 hours;
}
while(getWeekday(lastHoldingTax)!=5) {
lastHoldingTax -= 1 days;
}
lastHoldingTax -= getMinute(lastHoldingTax) * (1 minutes) + getSecond(lastHoldingTax) * (1 seconds);
}
}
}
function changeHoldingTax(uint256 _newValue) {
if(msg.sender != owner) throw;
holdingTax = _newValue;
}
function changeHoldingTaxInterval(uint256 _newValue) {
if(msg.sender != owner) throw;
holdingTaxInterval = _newValue;
}
function addAddress (address addr) private {
if(!addressExists[addr]) {
addressIndex[addr] = numberOfAddress;
addresses[numberOfAddress++] = addr;
addressExists[addr] = true;
}
}
function addAddressManual (address addr) {
if(msg.sender == owner && isPrivate) {
addAddress(addr);
} else {
throw;
}
}
function removeAddress (address addr) private {
if(addressExists[addr]) {
numberOfAddress--;
addresses[addressIndex[addr]] = 0x0;
addressExists[addr] = false;
}
}
function removeAddressManual (address addr) {
if(msg.sender == owner && isPrivate) {
removeAddress(addr);
} else {
throw;
}
}
function getWeekday(uint timestamp) returns (uint8) {
return uint8((timestamp / 86400 + 4) % 7);
}
function getHour(uint timestamp) returns (uint8) {
return uint8((timestamp / 60 / 60) % 24);
}
function getMinute(uint timestamp) returns (uint8) {
return uint8((timestamp / 60) % 60);
}
function getSecond(uint timestamp) returns (uint8) {
return uint8(timestamp % 60);
}
event Transfer(address indexed _from, address indexed _to, uint256 _value);
event Approval(address indexed _owner, address indexed _spender, uint256 _value);
}