3

Usually a token-transfer has a (ETH) value of zero and the amount is encoded in the input-data payload. Some projects even distinguish between normal and other transfers by checking for zero:

https://github.com/trezor/trezor-mcu/blob/master/firmware/ethereum.c#L341

The question is: is it enforced somewhere? Otherwise e.g. in the TREZOR example someone could hide a token-transfer by sending some ETH with it ..

3 Answers 3

4

The comment above saying "Yes, token-transfer always has a value of 0" is wrong.

The correct answer to the question is that--no--there is nothing that precludes a token transfer and an ether transfer from happening in the same transaction.

It is true to say that most ERC20 token smart contracts are coded to disallow it, but that is in no way the same thing as saying it's not allowed.

Distinguish between the smart contract code and the Ethereum protocol. In the protocol you can do anything you want relative to sending both 'data' and 'value' in the same transaction. A smart contract must be coded to disallow this. The fact that most token contracts do so, doesn't really have anything to do with it.

1

Yes, usually the token contract will reject a transfer with a non zero value.

For a contract method to receive ethers it should be marked as payable, but the transfer method does not have such modifier. Moreover most token contracts will reject any transfer made after the crowdsale is over.

1

Yes, token-transfer always has a value of 0 (as the value attribute is associated with Ether), but the data part will have some value when doing a token transfer. I have worked on this topic recently, I myself wanted to know the same. To understand it much better I had to filter some transactions and check myself how does an ETH transaction differ from token transfer. All the below transactions are taken from TESTNET:

ETH TRANSFER

Transaction Hash: 0x27c3fe1bc90723e5d7e0dbc3429e71faa967a623c8e4c49df0739283c17718e6

Transaction log:

> web3.eth.getTransaction("0x27c3fe1bc90723e5d7e0dbc3429e71faa967a623c8e4c49df0739283c17718e6");
{ blockHash: '0x06111bf75fb9108dc5596ddbb6e2e843ee13830987688a90df2ab0772815fa96',
  blockNumber: 1488295,
  from: '0x76e0bb92b6f8d431af2fe1bafd304eb832241619',
  gas: 21000,
  gasPrice: { [String: '31000000000'] s: 1, e: 10, c: [ 31000000000 ] },
  hash: '0x27c3fe1bc90723e5d7e0dbc3429e71faa967a623c8e4c49df0739283c17718e6',
  input: '0x',
  nonce: 261,
  to: '0xb1aa0ac057639e534a89b095853befc4d6d264cf',
  transactionIndex: 0,
  value: { [String: '1000000000000000000'] s: 1, e: 18, c: [ 10000 ] },
  v: '0x2a',
  r: '0x3b4202fda27b6fdfb6985e10ffcd7b5f9f2a64e31fc75d444d6a7684a75f3b',
  s: '0x5bb67429e6cae209f53ad5c1538d0c3d0035f12e92a569c0b2898512d9cdeae5' }

Transaction Receipt:

> web3.eth.getTransactionReceipt("0x27c3fe1bc90723e5d7e0dbc3429e71faa967a623c8e4c49df0739283c17718e6");
{ blockHash: '0x06111bf75fb9108dc5596ddbb6e2e843ee13830987688a90df2ab0772815fa96',
  blockNumber: 1488295,
  contractAddress: null,
  cumulativeGasUsed: 21000,
  from: '0x76e0bb92b6f8d431af2fe1bafd304eb832241619',
  gasUsed: 21000,
  logs: [],
  logsBloom: '0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
  root: '0x6a29376fb5c83a4617fecc1b95c1353f37711912128fd3b6bce9dde57b8130b3',
  to: '0xb1aa0ac057639e534a89b095853befc4d6d264cf',
  transactionHash: '0x27c3fe1bc90723e5d7e0dbc3429e71faa967a623c8e4c49df0739283c17718e6',
  transactionIndex: 0 }

If you carefully check the above logs, the value property in the Transaction Log has the value of 1000000000000000000 wei i.e. 1 Ether. and the Input is 0x

Similarly the Logs in the Transaction Receipt is an empty object. Which will not be empty when a token transfer happens.

TOKEN TRANSFER

Ropesten Transaction Details: 0x14632d129a6aac7365483a3000470ece443a19a73f242cba1f1944f78889a677

Transaction Log

    web3.eth.getTransaction("0x14632d129a6aac7365483a3000470ece443a19a73f242cba1f1944f78889a677");
{ blockHash: '0x34ee516310a59407712455ec87bd76046a1e68f5c631dc8e6b4bb903b8c92834',
          blockNumber: 1535104,
          from: '0x76e0bb92b6f8d431af2fe1bafd304eb832241619',
          gas: 223616,
          gasPrice: { [String: '22000000000'] s: 1, e: 10, c: [ 22000000000 ] },
          hash: '0x14632d129a6aac7365483a3000470ece443a19a73f242cba1f1944f78889a677',
          input: '0xa9059cbb0000000000000000000000002b3425ce986f9f0f599758f4fb33158ca671e83e0000000000000000000000000000000000000000000000000000000000000001',
          nonce: 267,
          to: '0x5c99dadde01ce61ab5b5536d566bf41ecd17e3a9',
          transactionIndex: 7,
          value: { [String: '0'] s: 1, e: 0, c: [ 0 ] },
          v: '0x1b',
          r: '0x4ad36e9eefd233abce864b3e53b86d1b937bcea83223564e4f56cc7defbcde3e',
          s: '0x22f256f9fe62187dc0e8942981ef52ae3643d04f50e00957c94e10b8da4e3116' }

If you check the above transaction Log, it clearly suggests that this transaction was a Token Transfer, as the below properties help us:

- Input: '0xa9059cbb0000000000000000000000002b3425ce986f9f0f599758f4fb33158ca671e83e0000000000000000000000000000000000000000000000000000000000000001'

0xa9059cbb is the hex for transfer. 0000000000000000000000002b3425ce986f9f0f599758f4fb33158ca671e83e is the address to which the token was sent with left padding upto 64 places 0000000000000000000000000000000000000000000000000000000000000001 is the number of tokens to be sent left padded upto 64 places.

value property is 0x0 (this shows no ether were sent)

Transaction Receipt

web3.eth.getTransactionReceipt("0x14632d129a6aac7365483a3000470ece443a19a73f242cba1f1944f78889a677");
{ blockHash: '0x34ee516310a59407712455ec87bd76046a1e68f5c631dc8e6b4bb903b8c92834',
  blockNumber: 1535104,
  contractAddress: null,
  cumulativeGasUsed: 352435,
  from: '0x76e0bb92b6f8d431af2fe1bafd304eb832241619',
  gasUsed: 36979,
  logs:
   [ { address: '0x5c99dadde01ce61ab5b5536d566bf41ecd17e3a9',
       topics: [Object],
       data: '0x0000000000000000000000000000000000000000000000000000000000000001',
       blockNumber: 1535104,
       transactionHash: '0x14632d129a6aac7365483a3000470ece443a19a73f242cba1f1944f78889a677',
       transactionIndex: 7,
       blockHash: '0x34ee516310a59407712455ec87bd76046a1e68f5c631dc8e6b4bb903b8c92834',
       logIndex: 6,
       removed: false } ],
  logsBloom: '0x00000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008080000000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000400000000000000000000000000000004000000000000000000000000000000400000000000000000001000000000000000000002000000000000000000000000000000000000000000000000000000002400000000000000000000000000000000000000000000000000000000000000',
  root: '0x9840ddaa4571522013623410420a11689fc44184d52d541d4f1067adcdde9e8c',
  to: '0x5c99dadde01ce61ab5b5536d566bf41ecd17e3a9',
  transactionHash: '0x14632d129a6aac7365483a3000470ece443a19a73f242cba1f1944f78889a677',
  transactionIndex: 7 }

As I said earlier, the logs property when a ETH trasnfer happens is empty but when a token transfer happens logs property has an object which helps in identifying to/from which address the token got transferred. the data property helps in knowing the amount of tokens transferred.

address:'0x5c99dadde01ce61ab5b5536d566bf41ecd17e3a9',
    topics:
     [ '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef',
       '0x00000000000000000000000076e0bb92b6f8d431af2fe1bafd304eb832241619',
       '0x0000000000000000000000002b3425ce986f9f0f599758f4fb33158ca671e83e' ],
    data: '0x0000000000000000000000000000000000000000000000000000000000000001',
    blockNumber: 1535104,
    transactionHash: '0x14632d129a6aac7365483a3000470ece443a19a73f242cba1f1944f78889a677',
    transactionIndex: 7,
    blockHash: '0x34ee516310a59407712455ec87bd76046a1e68f5c631dc8e6b4bb903b8c92834',
    logIndex: 6,
    removed: false } ]

If I remember it correctly,to distinguish much more clearly between transactions, you can try using the a logParser made using SolidityEvent Library which can be found inside web3.js. Here is the link to the same.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.