For more information, see:
Smart contracts are programs that run on the blockchain, replacing human directors. Contracts may be written in several languages, one of which is Solidity.
Remix opens, as shown below. It's an online Solidity development platform.
Highlight all 306 lines of the PoWHCoin code and copy it into the Clipboard, as shown below.
In Remix, remove the "Ballot" code that is already there and paste in the PoWHCoin code, as shown below.
This will launch a simulated Ethereum blockchain to run the contract on. It also creates several accounts to use, each with a starting balance of 100 Ether.
The bottom right pane now shows more pink buttons for methods like "transfer" and "withdraw", as shown below.
In Remix, at the top right, enter a "Value" of 50 as shown below.
To the right of the value, select a unit of ether.
At the bottom right, click the pink fund button.
The center bottom pane shows a log item labelled "transact to PonziTokenV3", as shown below
In Remix, at the top right, click the "Accounts" box. The field value pops up, as shown below.
Your account now contains slightly less than 50 Ether, because you invested 50 Ether into the PonziTokenV3 contract, and paid a transaction fee, also called "gas".
Notice that there are other accounts on the list, which still contain 100 Ether, because they haven't invested any Ether yet.
Select the second account, which contains 100 Ether.
Enter a "Value" of 1 and select a unit of ether, as shown below.
At the bottom right, click the pink fund button.
The second account's balance falls to just below 99 Ether, and another log item labelled "transact to PonziTokenV3" appears, as shown below.
Click the Accounts box and move to account #3, which has a balance of 100 Ether, as shown below.
To copy the account number into the clipboard, click the tiny icon to the right of the box, as shown below.
Now click the "Accounts" box again and select Account #2, with a balance slightly less than 99 Ether. This is necessary to ensure that the Approve action is performed using account #2.
At the lower right, click the down-arrow to the right of the line containing the pink "approve" button.
Two parameters appear: "_spender" and "_value", as shown below.
Paste the copied address into the "_spender" field, and enter 1 into the "_value" field, as shown below.
In the "approve" section, click the pink transact button.
Click the blue balanceOfOld button.
The result is zero, as shown below, because we haven't yet transferred any of the contract's Ether into this account.
The hack is to transfer the Ether from Account #2 to the contract address instead, executing the transaction as Account #3.
The transaction is approved because it appears to be coming from Account #2, but it actually subtracts Ether from Account #3, which has a balance of zero, and rolls around to a huge positive value.
At the top right, verify that the "Accounts" box is showing Account #2, which has a balance slightly less than 99 Ether.
Click the tiny icon to the right of the box, to copy the account number into the clipboard, as shown below.
At the lower right, scroll down to the pink transferFrom button and click its down-arrow to expand it.
Paste the address from the clipboard into the _from field, as shown below.
On the right side, just above the pink (fallback) button, in the line labelled "PonziTokenV3 at 0x...", click the tiny icon to copy the address to the clipboard, as shown below.
At the lower right, in the transfer section, paste the address into the _to field. Add quotation marks before and after both the the _from and _to addresses, as shown in the image below.
Enter a _value of 1, as shown below.
At the top of the right pane, click the Accounts box and select Account #3, which contains approximately 100 Ether, as shown above.
At the lower right, in the transfer section, click the pink transact button.
The account now has a huge balance, starting with "115", as shown below.
This function makes sure that the transfer is no larger than the allowed value and calls the transferTokens function.
Scroll up to line 113 to see the transferTokens function, as shown below.
Line 114 makes sure that the balance in the _from account is sufficient for the withdrawal. We used Account #2 as the _from account, and it had a balance of 99 Eth, so this check passed.
Line 116 checks to see if we are sending coins to the contract itself, and we are, so this condition is true and it calls the sell function.
Scroll down to line 207 to see the sell function, as shown below.
The problem is in line 211. This deducts a coin from the msg.sender account, which is the account that originated the transaction, not necessarily the same as the _from account.
By sending the message from account #3, with a _from account of #2, we tricked this function into subtracting a coin from an empty account, resulting in an integer underflow.