How lifting limitations of Ethereum prevents hacks by design – hacks that cost ERC20 token owners several millions so far. An example.
The most unexpected events sometimes lead to disastrous consequences. In the design of smart contracts, it hasn’t always taken confusing code structure or sloppy logic to cause major havoc. Sometimes, it takes only something as simple as arithmetic operators from elementary school: Addition, Subtraction and Multiplication.
Taking as examples
2²⁵⁶ - 1n
which are the smallest and largest numbers (unsigned integers) that can be represented in the Ethereum Virtual Machine (EVM).
Although they appear to be distant from each other from a numeric point of view, they are, from a developer’s perspective, far too close for comfort: Subtracting 1 from the former number or adding 1 to the latter results to
0–1 == 2²⁵⁶ - 1n
2²⁵⁶ - 1 + 1 == 0n
An integer overflow occurs – the numbers “wrap around”.
This has remained default behaviour in Ethereum due to limitations of the EVM. Developers are forced to establish extra checks to prevent this from becoming a problem – which hasn’t always gone well, as you will see below.
Why is This so Important?
In 2018 and subsequent years the so called ‘batchOverflow bug‘ in many of Ethereum Token Contracts allowed malicious actors to create tokens from thin air, thereby causing major damage to exchanges and token owners.
In a batchOverflow bug exploit, a hacker transfers tokens to multiple recipients – more tokens than the hacker actually owns – by calling the token contract’s transfer function in a seemingly unproblematic way.
To explain how that common exploit is abused and what Aeternity has established to prevent this by design, let’s reimplement the same exploitable problematic contract logic in Sophia, Aeternity’s Smart Contract Language. The critical line of code will be line 13.
If you are not a programmer and/or just want to know how the exploit works, skip to after the code.
What’s Happening Here?
To ensure the sender does not transfer more tokens than he owns, the number of recipients is multiplied with the value of tokens to be transferred to each of them.
By passing a large number into value, this multiplication can lead to the described integer overflow, returning a very small number. Now, to the security check in line 17, it appears as if one was trying to transfer only very few tokens, e.g. an amount the transaction sender could actually afford.
After this check is bypassed, the value is added to every recipient’s balance.
Et voilà – profit ! 💸
Why Can’t This Happen on Aeternity?
The Fast Æternity Transaction Engine (FATE) VM is type-safe and disallows unsigned integers to wrap around below 0 (read: subtracting 1 from your token balance of 0 does not make you a gazillionaire).
It also has no fixed upper bounds for numbers: 2²⁵⁶ – 1 is not the largest number possible – the only limits to arithmetic are transaction costs and, eventually, storage.
In the case of this example, the hacker (and anyone else) is free to attempt to send 2²⁵⁶ – 1 or more tokens to X people in one transaction. The token contract, however, will not be fooled and will execute itself (only) if the hacker actually owns the necessary amount.
No luck for hackers, less worries – and less to keep an eye on – for developers.