I was reading about the short address attack and decided to replicate and test the possible solutions.

What I know about short address attack is if you skip n characters of your address, you end up supplying 68-(n/2) bytes to your transfer function and the evm appends zeros to makes if 68 bytes. And the end result is your value changes by n<<8. This was just a high-level overview.

Now I trid to test the same with a test toke (with decimal places =2) . The transfer function of the contract goes by:

 function transfer(address _to, uint256 _value) {
        require (balanceOf[msg.sender] > _value) ;
        require (balanceOf[_to] + _value > balanceOf[_to]);
        balanceOf[msg.sender] -= _value;
        balanceOf[_to] += _value;
        Transfer(msg.sender, _to, _value);                                  

I used remix connected to my private test-net to check for this attack.

I had an address 0x7ecd024742458287b9cd97015ff265d04a316f20. I called the transfer function of contract with arguments:

transfer("0x7ecd024742458287b9cd97015ff265d04a316f2", 1);

As per my understanding, I was expecting the supplied address will get 256 coins (if short address attack is replicated). But instead I got the error:

transact to browser/TestShortAddAttack.sol:MyToken.transfer errored: Gas required exceeds block gas limit: 6000000. An important gas estimation might also be the sign of a problem in the contract code. Please check loops and be sure you did not sent value to a non payable function (that's also the reason of strong gas estimation).

Why is the transaction consuming this much gas? Is this issue has been taken care by evm or we need to implement the check (Checking length of msg.data)?

  • I know you are an experienced user, but maybe out of gas message is happening because of a throw. Have you tried with the correct address? I mean, with the 0 at the end? – Luiz Soares Dec 1 '17 at 11:04
  • With 0 at the end, the address will be of 20 bytes and I won't be able to replicate the issue. For replicating this issue, I need to supply address with length less than 20 bytes. – Prashant Prabhakar Singh Dec 1 '17 at 11:08
  • Probably you will need to create the transaction message to ensure it is shorter, remix may have some code that validates and ensure addresses are 20 bytes. – Ismael Dec 1 '17 at 16:28
  • Hmm.. this may be possible. let me try the same with geth. – Prashant Prabhakar Singh Dec 2 '17 at 7:36

I tried to replicate as well. I, however, did not get the error you did, but neither did I get a perfect replica of the attack. I have an implementation the safemath library, but elseway as yours.

function transfer(address _to, uint _amount) public returns (bool success){
    balances[msg.sender] = balances[msg.sender].sub(_amount);
    balances[_to] = balances[_to].add(_amount);
    return true;

I tried using the address:


If I run the transfer as I normally would


I would get


as the input of the signed transaction. If I instead used the shortened address


I would get


Padding the input with a zero, but as the header of the address, and not behind as intended. This would simply transfer the funds to an address to which I do not have access.

Did you find a way to replicate the attack?

  • The problem is usually client side, if you use a library that does argument padding it will fix the problem before it reaches the contract. To demostrate the issue you should use a hardcoded message, for example by removing by hand two zeros 0x40c10f1900000000000000000000000e9f341c1b12912b1594afa3885c873c91ec66920000000000000000000000000000000000000000000000000000000000000064. – Ismael Feb 16 '18 at 18:04
  • I used geth directly, but I guess it should be done trough rawtransaction instead. Both problems was not being able to reproduce the attack so i thought it would be ok. – L Herskind Feb 16 '18 at 19:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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