0

I found a token, where the total supply is 200000000000000 (200,000,000,000,000) and the decimals are 8 so the total supply should be 2M.

But now there is a token holder that generated tokens apperently out of the air. The holder has more than 1,000,000,000,000,000,000,000,000,000,000 of the tokens. Also the holder is the owner. But in the contract there is no function to increase the total supply. Instead, the holder has used the transfer function to hack some tokens.

He made a transaction with this transfer function (input data):

Function: transfer(address _to, uint256 _value)

MethodID: 0xa9059cbb
[0]:0000000000000000000000007dd2af6c0a7434df91dd663323b12cbc71b28be4
[1]:fffffffffffffffffffffffffffffffffffffffffffffffffbc7f99c5447fffe

the event says:

Transfer 1,000,000,000,000,000,.... (a very long number) TOKEN NAME From FROM_ADDRESS to TO_ADDRESS.

The token holder did only have 2000 of the tokens at that time, so there has to be a bug in the transfer function.

And the transfer function looks like this: (I have added the comments as there are the things I do not understand):

function transfer(address _to, uint256 _value) returns (bool success) {
    require(balanceOf[msg.sender] >= _value);
    // The sender did not even have a small part of the amount he sent.
    // He had only about 2000
    // So, shouldn't the function stop here? Or does it not stop automaticly 
    // with a require?
    // My thought here is, there is missing something like "return false".

    require(balanceOf[_to] + _value >= balanceOf[_to]);
    // Same than above

    balanceOf[msg.sender] -= _value;
    balanceOf[_to] += _value;
    Transfer(msg.sender, _to, _value);
    return true;
}

I am not experienced in solidity programming yet so I hope that someone can help me. Can someone decode the input data and explain me what happened here?

1 Answer 1

1

It looks like the bugged (or malicous...) code is in burnSupply. Directly before the owner transferred all those tokens, he called burnSupply and burned -1. The owner had zero tokens, and there is no underflow protection on that contract, so this gave him the max possible number of tokens.

6
  • Thanks and great you found the contract! I forgot to add. The problem wasn't any negative value, instead, he just entered a too large number which resulted in giving back much tokens. The thing is here: etherscan.io/tx/… the value "fffffffffffffffffffffffffffffffffffffffffffffffffff8e502b672ffff" is: 115792089237316195423570985008687907853269984665640564039457582007913129639935 I did not understand yet why Solidity adds the amount instead of removing but all I know is that it is an "integer overflow".
    – dkb
    Commented Feb 7, 2018 at 16:28
  • No, it actually was the subtraction. The owner had 0 tokens, then burned 1 token, making their balance 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff tokens, e.g. 2^256-1 tokens.
    – natewelch_
    Commented Feb 7, 2018 at 18:51
  • Thanks for the information. So that means, if I have an uint256 of 0 and remove 1, that won't work because uint can't be negative and so it would instead add the highest number of uint256 possible?
    – dkb
    Commented Feb 8, 2018 at 16:21
  • it doesn't work because when you subtract 1 from a place where there is a 0, it borrows from the left, e.g. 100-1=99. When this happens in a computer, it does it all the way to the left until it can't borrow anymore, so it becomes all ones (which in hex is all f's).
    – natewelch_
    Commented Feb 8, 2018 at 17:10
  • That's maybe a bit too much complicated information for me. Could you maybe provide some information on how I could get deeper into this like a link or some keywords I can google for? Thank you very much!
    – dkb
    Commented Feb 8, 2018 at 17:12

Your Answer

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

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