Smart Contract Security Newsletter #16 — CREATE2 FAQ
Sign up to get this newsletter every week: https://tinyletter.com/smart-contract-security/
Distilled News
This week was a little bit slow in the sense that there were no “major incidents”. Though there has been a lot of chatter about CREATE2
(EIP-1014) this week.
So, what is all this stuff about CREATE2?
I thought I’d try to distill that down a bit, and an FAQ format felt like the right way to do it.
What is CREATE2
?
It’s a new opcode for deploying smart contracts. Similar to CREATE
, when CREATE2
is called in a contract (which I’ll refer to as the ‘factory’) it will run some init_code
. Whatever that init_code
returns will be the code in the new contract. In Solidity, this init_code
is defined by a constructor()
function.
How is it different from CREATE
?
The important difference is in how the address of the new contract is determined.
With CREATE
the address is determined by the factory contract’s nonce
. Everytime CREATE
is called in the factory, it’s nonce
increases by 1.
With CREATE2
, the address is determined by an arbitrary salt
value, and the init_code
.
Why do we need it?
The big advantage of CREATE2
is that the destination address is not dependent on the exact state (ie. the nonce) of the factory when it’s called. This allows for the result of a transaction to be simulated off-chain, which is an important part of many state channel based approaches to scaling.
So what is everybody so worked up about?
Recalling two things I wrote above:
- Whatever that
init_code
returns will be the code in the new contract. - With
CREATE2
, the address is a function of an arbitrarysalt
value, and theinit_code
.
So here’s the key detail: if CREATE2
is run twice in the same factory contract, with the same salt
, and the sameinit_code
, it will result in a second contract being deployed to the same address as the first contract!
OK, so… then what happens?
If the first contract is still at the address when CREATE2
tries to put a new contract there, the operation will simply REVERT
; which is fine.
But a few other facts complicate the story:
- Another infamous opcode,
SELFDESTRUCT
, is also lurking within the EVM. - The same
init_code
can return different values at different times.
How could an attacker make use of this?
An example attack that this would enable goes like this:
- Using
CREATE2
, deploy a safe looking contract. - Convince some people to deposit their ETH, Tokens, Kittens, etc.
- Call
SELFDESTRUCT
on that safe looking contract, and it will be removed from state. - Using
CREATE2
again, replace it with a malicious contract that sends all the funds to you.
My god that’s horrible
Right!?
What can we do about it?
Even if a contract was deployed by CREATE2
, the attack would not be possible if it doesn’t contain a SELFDESTRUCT
, DELEGATECALL
, or CALLCODE
opcode.
That kind of analysis could technically be run by wallets and block explorers to warn users, but this is quite a burden to place on them.
(Interestingly, Etherscan shows a “reinit” warning on the Ropsten testnet (where CREATE2
is live), although if you’re seeing that warning it’s already too late. )
Why weren’t people talking about this earlier?
This to me is one of the more interesting things, ie. the pattern of bugs not being found, or possible issues not being discussed until the last minute.
The Constantinople fork was postponed with 48 hours notice before due to a potential vulnerability completely unrelated to CREATE2
. So, this public conversation very easily may not have happened before the change was made permanent.
The ENS launch was the same; two serious bugs were discovered the day of it’s launch.
What should we do to get more attention on these things?
Some advocate bug bounties, which worked recently for Gnosis’ dxDAO. But bounties often see very little activity, and because of the economics, bounty hunters tend to look broadly for easy to find bugs.
In order to ensure the security of protocol changes, both a deep and holistic review is required. The audit being done on ProgPOW is a good start in that direction.
What do I think about CREATE2
?
Well… scaling is essential, and state channels are extremely promising, so I want the improvements it brings. But I’m starting to think the side effects are excessively dangerous. A suggestion I find compelling was put forward by Nick Johnson:
I honestly think the simplest solution to all of this would have been to modify self destruct to leave an account’s nonce intact. Selfdestruct is already an ineffective way to encourage freeing state, and this would solve the issues.
More CREATE2
links:
Other Good Links
- Poison block explorer byte code: A rather clever attack devised by my teammate Daniel Luca
- Preventing Reentrancy attacks in smart contracts: Ideas for an async smart contract programming model (in javascript believe it or not)
- New Parity Ethereum update fixes several vulnerabilities: There were some more bugs. Update yer Paritys.
- smartcontractaudits.com: A listing of audit providers
- “Etherelime”: A new debugger
- Modern alternatives to PGP: warning, nothing whatsover to do with blockchains
Want to help make this newsletter better? Join the #maurelians-newsletter channel in the MythXdiscord chat.
Want more weekly goodness? Read my friends’ stuff!
Ben’s “What’s new in ETH 2.0”Evan’s “Week in Ethereum”
This newsletter is supported by ConsenSys Diligence, where I work. We can help with all things smart contract security; auditing, secure development guidance, and training.
We’re hiring!
Developer — Security Analysis Tools
Frontend and Dapp Engineer, MythX
Marketing and Brand Manager, MythX
Security Engineer and Auditor — Smart Contracts
Senior Technical Recruiter
Smart Contract Security Business Development Lead
Technical Product Manager, MythX