Transaction Hash:
Block:
5539218 at May-01-2018 06:33:42 PM +UTC
Transaction Fee:
0.000216785 ETH
$0.39
Gas Used:
43,357 Gas / 5 Gwei
Emitted Events:
31 |
NexoToken.Transfer( from=[Sender] 0x3fcd22ce2564b55016fb62149ee3a22ee20ecb97, to=[Receiver] Exchange, value=35296675333378273434463 )
|
32 |
Exchange.Deposit( token=NexoToken, user=[Sender] 0x3fcd22ce2564b55016fb62149ee3a22ee20ecb97, amount=35296675333378273434463, balance=35296675333378273434463 )
|
Account State Difference:
Address | Before | After | State Difference | ||
---|---|---|---|---|---|
0x2a0c0DBE...44050c208 | (IDEX) | ||||
0x3FCD22Ce...Ee20eCb97 |
0.080362302 Eth
Nonce: 96
|
0.080145517 Eth
Nonce: 97
| 0.000216785 | ||
0xb2930B35...e543a0347
Miner
| (MiningPoolHub: Old Address) | 26,194.597802248705910548 Eth | 26,194.598019033705910548 Eth | 0.000216785 | |
0xB62132e3...d8d815206 |
Execution Trace
Exchange.depositToken( token=0xB62132e35a6c13ee1EE0f84dC5d40bad8d815206, amount=35296675333378273434463 )

-
NexoToken.transferFrom( _from=0x3FCD22Ce2564B55016Fb62149ee3A22Ee20eCb97, _to=0x2a0c0DBEcC7E4D658f48E01e3fA353F44050c208, _value=35296675333378273434463 ) => ( 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: NexoToken
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: NexoToken
pragma solidity 0.4.23; // // This source file is part of the current-contracts open source project // Copyright 2018 Zerion LLC // Licensed under Apache License v2.0 // // @title Abstract ERC20 token interface contract AbstractToken { function balanceOf(address owner) public view returns (uint256 balance); function transfer(address to, uint256 value) public returns (bool success); function transferFrom(address from, address to, uint256 value) public returns (bool success); function approve(address spender, uint256 value) public returns (bool success); function allowance(address owner, address spender) public view returns (uint256 remaining); event Transfer(address indexed from, address indexed to, uint256 value); event Approval(address indexed owner, address indexed spender, uint256 value); } contract Owned { address public owner = msg.sender; address public potentialOwner; modifier onlyOwner { require(msg.sender == owner); _; } modifier onlyPotentialOwner { require(msg.sender == potentialOwner); _; } event NewOwner(address old, address current); event NewPotentialOwner(address old, address potential); function setOwner(address _new) public onlyOwner { emit NewPotentialOwner(owner, _new); potentialOwner = _new; } function confirmOwnership() public onlyPotentialOwner { emit NewOwner(owner, potentialOwner); owner = potentialOwner; potentialOwner = address(0); } } // @title SafeMath contract - Math operations with safety checks. // @author OpenZeppelin: https://github.com/OpenZeppelin/zeppelin-solidity/blob/master/contracts/math/SafeMath.sol contract SafeMath { /** * @dev Multiplies two numbers, throws on overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { if (a == 0) { return 0; } uint256 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) { 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) { uint256 c = a + b; assert(c >= a); return c; } /** * @dev Raises `a` to the `b`th power, throws on overflow. */ function pow(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a ** b; assert(c >= a); return c; } } /// Implements ERC 20 Token standard: https://github.com/ethereum/EIPs/issues/20 contract StandardToken is AbstractToken, Owned, SafeMath { /* * Data structures */ mapping (address => uint256) internal balances; mapping (address => mapping (address => uint256)) internal allowed; uint256 public totalSupply; /* * Read and write storage functions */ /// @dev Transfers sender's tokens to a given address. Returns success. /// @param _to Address of token receiver. /// @param _value Number of tokens to transfer. function transfer(address _to, uint256 _value) public returns (bool success) { return _transfer(msg.sender, _to, _value); } /// @dev Allows allowed third party to transfer tokens from one address to another. Returns success. /// @param _from Address from where tokens are withdrawn. /// @param _to Address to where tokens are sent. /// @param _value Number of tokens to transfer. function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) { require(allowed[_from][msg.sender] >= _value); allowed[_from][msg.sender] -= _value; return _transfer(_from, _to, _value); } /// @dev Returns number of tokens owned by given address. /// @param _owner Address of token owner. function balanceOf(address _owner) public view returns (uint256 balance) { return balances[_owner]; } /// @dev Sets approved amount of tokens for spender. Returns success. /// @param _spender Address of allowed account. /// @param _value Number of approved tokens. function approve(address _spender, uint256 _value) public returns (bool success) { allowed[msg.sender][_spender] = _value; emit Approval(msg.sender, _spender, _value); return true; } /* * Read storage functions */ /// @dev Returns number of allowed tokens for given address. /// @param _owner Address of token owner. /// @param _spender Address of token spender. function allowance(address _owner, address _spender) public view returns (uint256 remaining) { return allowed[_owner][_spender]; } /** * @dev Private transfer, can only be called by this contract. * @param _from The address of the sender. * @param _to The address of the recipient. * @param _value The amount to send. * @return success True if the transfer was successful, or throws. */ function _transfer(address _from, address _to, uint256 _value) private returns (bool success) { require(_to != address(0)); require(balances[_from] >= _value); balances[_from] -= _value; balances[_to] = add(balances[_to], _value); emit Transfer(_from, _to, _value); return true; } } /// @title Token contract - Implements Standard ERC20 with additional features. /// @author Zerion - <[email protected]> contract Token is StandardToken { // Time of the contract creation uint256 public creationTime; function Token() public { /* solium-disable-next-line security/no-block-members */ creationTime = now; } /// @dev Owner can transfer out any accidentally sent ERC20 tokens function transferERC20Token(AbstractToken _token, address _to, uint256 _value) public onlyOwner returns (bool success) { require(_token.balanceOf(address(this)) >= _value); uint256 receiverBalance = _token.balanceOf(_to); require(_token.transfer(_to, _value)); uint256 receiverNewBalance = _token.balanceOf(_to); assert(receiverNewBalance == add(receiverBalance, _value)); return true; } /// @dev Increases approved amount of tokens for spender. Returns success. function increaseApproval(address _spender, uint256 _value) public returns (bool success) { allowed[msg.sender][_spender] = add(allowed[msg.sender][_spender], _value); emit Approval(msg.sender, _spender, allowed[msg.sender][_spender]); return true; } /// @dev Decreases approved amount of tokens for spender. Returns success. function decreaseApproval(address _spender, uint256 _value) public returns (bool success) { uint256 oldValue = allowed[msg.sender][_spender]; if (_value > oldValue) { allowed[msg.sender][_spender] = 0; } else { allowed[msg.sender][_spender] = sub(oldValue, _value); } emit Approval(msg.sender, _spender, allowed[msg.sender][_spender]); return true; } } // @title Token contract - Implements Standard ERC20 Token for NEXO project. /// @author Zerion - <[email protected]> contract NexoToken is Token { /// TOKEN META DATA string constant public name = 'Nexo'; string constant public symbol = 'NEXO'; uint8 constant public decimals = 18; /// ALOCATIONS // To calculate vesting periods we assume that 1 month is always equal to 30 days /*** Initial Investors' tokens ***/ // 525,000,000 (52.50%) tokens are distributed among initial investors // These tokens will be distributed without vesting address public investorsAllocation = address(0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF); uint256 public investorsTotal = 525000000e18; /*** Overdraft Reserves ***/ // 250,000,000 (25%) tokens will be eventually available for overdraft // These tokens will be distributed monthly with a 6 month cliff within a year // 41,666,666 tokens will be unlocked every month after the cliff // 4 tokens will be unlocked without vesting to ensure that total amount sums up to 250,000,000. address public overdraftAllocation = address(0x1111111111111111111111111111111111111111); uint256 public overdraftTotal = 250000000e18; uint256 public overdraftPeriodAmount = 41666666e18; uint256 public overdraftUnvested = 4e18; uint256 public overdraftCliff = 5 * 30 days; uint256 public overdraftPeriodLength = 30 days; uint8 public overdraftPeriodsNumber = 6; /*** Tokens reserved for Founders and Team ***/ // 112,500,000 (11.25%) tokens will be eventually available for the team // These tokens will be distributed every 3 month without a cliff within 4 years // 7,031,250 tokens will be unlocked every 3 month address public teamAllocation = address(0x2222222222222222222222222222222222222222); uint256 public teamTotal = 112500000e18; uint256 public teamPeriodAmount = 7031250e18; uint256 public teamUnvested = 0; uint256 public teamCliff = 0; uint256 public teamPeriodLength = 3 * 30 days; uint8 public teamPeriodsNumber = 16; /*** Tokens reserved for Community Building and Airdrop Campaigns ***/ // 60,000,000 (6%) tokens will be eventually available for the community // 10,000,002 tokens will be available instantly without vesting // 49,999,998 tokens will be distributed every 3 month without a cliff within 18 months // 8,333,333 tokens will be unlocked every 3 month address public communityAllocation = address(0x3333333333333333333333333333333333333333); uint256 public communityTotal = 60000000e18; uint256 public communityPeriodAmount = 8333333e18; uint256 public communityUnvested = 10000002e18; uint256 public communityCliff = 0; uint256 public communityPeriodLength = 3 * 30 days; uint8 public communityPeriodsNumber = 6; /*** Tokens reserved for Advisors, Legal and PR ***/ // 52,500,000 (5.25%) tokens will be eventually available for advisers // 25,000,008 tokens will be available instantly without vesting // 27 499 992 tokens will be distributed monthly without a cliff within 12 months // 2,291,666 tokens will be unlocked every month address public advisersAllocation = address(0x4444444444444444444444444444444444444444); uint256 public advisersTotal = 52500000e18; uint256 public advisersPeriodAmount = 2291666e18; uint256 public advisersUnvested = 25000008e18; uint256 public advisersCliff = 0; uint256 public advisersPeriodLength = 30 days; uint8 public advisersPeriodsNumber = 12; /// CONSTRUCTOR function NexoToken() public { // Overall, 1,000,000,000 tokens exist totalSupply = 1000000000e18; balances[investorsAllocation] = investorsTotal; balances[overdraftAllocation] = overdraftTotal; balances[teamAllocation] = teamTotal; balances[communityAllocation] = communityTotal; balances[advisersAllocation] = advisersTotal; // Unlock some tokens without vesting allowed[investorsAllocation][msg.sender] = investorsTotal; allowed[overdraftAllocation][msg.sender] = overdraftUnvested; allowed[communityAllocation][msg.sender] = communityUnvested; allowed[advisersAllocation][msg.sender] = advisersUnvested; } /// DISTRIBUTION function distributeInvestorsTokens(address _to, uint256 _amountWithDecimals) public onlyOwner { require(transferFrom(investorsAllocation, _to, _amountWithDecimals)); } /// VESTING function withdrawOverdraftTokens(address _to, uint256 _amountWithDecimals) public onlyOwner { allowed[overdraftAllocation][msg.sender] = allowance(overdraftAllocation, msg.sender); require(transferFrom(overdraftAllocation, _to, _amountWithDecimals)); } function withdrawTeamTokens(address _to, uint256 _amountWithDecimals) public onlyOwner { allowed[teamAllocation][msg.sender] = allowance(teamAllocation, msg.sender); require(transferFrom(teamAllocation, _to, _amountWithDecimals)); } function withdrawCommunityTokens(address _to, uint256 _amountWithDecimals) public onlyOwner { allowed[communityAllocation][msg.sender] = allowance(communityAllocation, msg.sender); require(transferFrom(communityAllocation, _to, _amountWithDecimals)); } function withdrawAdvisersTokens(address _to, uint256 _amountWithDecimals) public onlyOwner { allowed[advisersAllocation][msg.sender] = allowance(advisersAllocation, msg.sender); require(transferFrom(advisersAllocation, _to, _amountWithDecimals)); } /// @dev Overrides StandardToken.sol function function allowance(address _owner, address _spender) public view returns (uint256 remaining) { if (_spender != owner) { return allowed[_owner][_spender]; } uint256 unlockedTokens; uint256 spentTokens; if (_owner == overdraftAllocation) { unlockedTokens = _calculateUnlockedTokens( overdraftCliff, overdraftPeriodLength, overdraftPeriodAmount, overdraftPeriodsNumber, overdraftUnvested ); spentTokens = sub(overdraftTotal, balanceOf(overdraftAllocation)); } else if (_owner == teamAllocation) { unlockedTokens = _calculateUnlockedTokens( teamCliff, teamPeriodLength, teamPeriodAmount, teamPeriodsNumber, teamUnvested ); spentTokens = sub(teamTotal, balanceOf(teamAllocation)); } else if (_owner == communityAllocation) { unlockedTokens = _calculateUnlockedTokens( communityCliff, communityPeriodLength, communityPeriodAmount, communityPeriodsNumber, communityUnvested ); spentTokens = sub(communityTotal, balanceOf(communityAllocation)); } else if (_owner == advisersAllocation) { unlockedTokens = _calculateUnlockedTokens( advisersCliff, advisersPeriodLength, advisersPeriodAmount, advisersPeriodsNumber, advisersUnvested ); spentTokens = sub(advisersTotal, balanceOf(advisersAllocation)); } else { return allowed[_owner][_spender]; } return sub(unlockedTokens, spentTokens); } /// @dev Overrides Owned.sol function function confirmOwnership() public onlyPotentialOwner { // Forbid the old owner to distribute investors' tokens allowed[investorsAllocation][owner] = 0; // Allow the new owner to distribute investors' tokens allowed[investorsAllocation][msg.sender] = balanceOf(investorsAllocation); // Forbid the old owner to withdraw any tokens from the reserves allowed[overdraftAllocation][owner] = 0; allowed[teamAllocation][owner] = 0; allowed[communityAllocation][owner] = 0; allowed[advisersAllocation][owner] = 0; super.confirmOwnership(); } function _calculateUnlockedTokens( uint256 _cliff, uint256 _periodLength, uint256 _periodAmount, uint8 _periodsNumber, uint256 _unvestedAmount ) private view returns (uint256) { /* solium-disable-next-line security/no-block-members */ if (now < add(creationTime, _cliff)) { return _unvestedAmount; } /* solium-disable-next-line security/no-block-members */ uint256 periods = div(sub(now, add(creationTime, _cliff)), _periodLength); periods = periods > _periodsNumber ? _periodsNumber : periods; return add(_unvestedAmount, mul(periods, _periodAmount)); } }