Built on our earlier efforts in analyzing EOS tokens, we have developed an automated system to scan and analyze Ethereum-based (ERC-20) token transfers. Specifically, our system will automatically send out alerts if any suspicious transactions (e.g., involving unreasonably large tokens) occur.
They’ve found a couple of beauties, which they’ve branded “BatchOverflow” and “ProxyOverflow.” These affect multiple ERC-20 tokens — which are the basis for almost all ICOs.
The root cause is that smart contract coders just copy each other’s code a lot, because who needs formal methods when you can cut’n’paste’n’bodge.
On Sunday 22 April, PeckShield detected two transfers of 2255 — or, in hexadecimal, 0x8000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 — BeautyChain (BEC) tokens.
If you add these two numbers, you get 2256, a 257-bit number — or, since we’re working in Solidity, which has 256-bit integers, you get an overflow, and the counter cycles back around to 0.
This occurs in a function called batchTransfer() — a version of which is used in quite a lot of ERC-20 token contracts, because smart contract programmers copy code from each other lots and lots:
In line 257, amount is cnt times _value — and if _value is a huge number, this can easily overflow. This then passes the sanity checks in lines 258 and 259.
Finally, in lines 262 to 265, the balances of the two receivers will have the very large _value added to them.
batchTransfer() is not part of the ERC-20 standard, but it’s widely used — so, despite the CVE (CVE-2018-10299) specifying only BeautyChain, PeckShield found over a dozen tokens vulnerable to this exploit.
The CVE report for ProxyFlow (CVE-2018-10376) specifies only one ERC-20 token, SmartMesh (SMT) — but it affects multiple tokens.
PeckShield first detected the ProxyOverflow exploit in MESH, when someone transferred 6.5×1076 tokens — or 0x8fff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff in hexadecimal — with a transfer fee of 0x7000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0001.
If you add these values, you get 2256 — which overflows and the counter cycles back to 0 again!
Here’s the code this was exploiting:
_fee and _value are both set by the sender. If you put in values that add to more than 256 bits, the result wraps around. In this case, it adds to 0. This bypasses the sanity check in line 206. The huge number of tokens in _value are transferred to the attacker in line 214, and a huge _fee goes to msg.sender in line 217.
This pattern is found in lots of ERC-20 tokens! PeckShield lists MESH, UGToken, SMT, SMART, MTC, FirstCoin, GG Token, CNY Token and CNYTokenPlus.
OKex first suspended trading just on BeautyChain, but has now suspended all ERC-20 tokens, as has Huobi Pro. A pile of other exchanges are still allowing trading — and there’s still decentralised exchanges such as EtherDelta, which can trade any ERC-20 token.
SmartMesh will be destroying the counterfeit tokens — remember that the underlying Ethereum blockchain may be (somewhat) decentralised, but ERC-20 tokens themselves can be under absolute central control — and BeautyChain are looking into what they can do here. There’s no word as yet from the other tokens.
Fixing these bugs will require redeploying the contracts — assuming they have been coded to be upgradable. The usual method is per the Ethereum white paper:
Although code is theoretically immutable, one can easily get around this and have de-facto mutability by having chunks of the code in separate contracts, and having the address of which contracts to call stored in the modifiable storage.
Even then, it can be a massive pain in the backside — and isn’t a panacea, as Parity discovered.
Smart contracts, stupid humans
The value proposition of “immutability” is that nobody can mess with your contract once it’s been deployed. But this is another way of saying “bugs can’t be fixed, ever.”
The first really famous smart contract, The DAO in 2016, crashed and burned when it turned out to have a security hole that couldn’t be fixed in time and it got hacked.
(Smart contract security hits a worst case scenario — everyone can see your financial code and poke it for security holes, but you can’t quickly deploy fixes.)
The eventual fix for The DAO hack demonstrates the other problem with smart contracts: the “immutable” system containing the smart contract was suddenly considered changeable the moment the big boys risked losing money.
But humans are really bad at coding without error. Programs that can’t be fixed once they’re deployed need formal methods, functional programming and preferably a non-Turing-complete language. You need to program like NASA programming spacecraft.
And you can even deploy fully-audited code that you’ve mathematically proven is correct — and then a bug in a lower layer means you have a security hole anyway. And this has already happened.
Remember that not even Gavin Wood — the Ph.D computer scientist who wrote the Ethereum protocol specification — could write a smart contract safely enough not to lose hundreds of millions of dollars of his startup’s ICO funds in the Parity wallet disaster last November. What makes you sufficiently sure that you can?
Some of us called out the Solidity overflow issues a long time ago.
This is me back in July 17, 2017. pic.twitter.com/3799yJTR4b
— Emin Gün Sirer (@el33th4xor) April 25, 2018
— Buttcoin (@ButtCoin) April 26, 2018
Your subscriptions keep this site going. Sign up today!