Noop, Not my Safe
If you’re like me, you get a kick out of deploying Safe multisigs deterministically to vanity addresses and across multiple networks.
But how safe is this practice?
We all remember when Wintermute lost 20M OP because an attacker replicated their Safe address on Optimism with malicious owners. Lesson learned: nobody deploys multichain Safes from the factory with the CREATE
opcode anymore— CREATE2
is the way to go. And since my deployments depend on an initializer containing my owner addresses, nobody can steal my Safe on new networks, right?
Wrong.
Today, I stumbled upon a way to “steal” a Safe address even when the owner deployed with CREATE2
and a proper initializer containing owners. Thus, Safe users should not rely on their ability to control a particular Safe address on new networks.
(Note: This was responsibly disclosed to the Safe team, and they confirmed it was a known issue, fixed in v1.4.1.)
How Normal Safe Deployments Work
Safe follows the EIP-1167 minimal proxy pattern. The proxy deployments come from a factory that requires the following data:
- A list of owners
- A threshold
- Other optional data
This data is hashed into the CREATE2
salt, ensuring deterministic deployment across chains. Normally, deployment looks like this:
Safe deployment happy path.
But what if the Safe implementation contract doesn’t exist on the network yet?
How an Attacker Steals Your Safe
Let’s say you deploy on a new chain, Sonic, which at the time of observation doesn’t yet have a Safe implementation contract. Here’s what happens:
- The proxy factory deploys your Safe proxy.
- The proxy calls
setup()
, but since the implementation contract doesn’t exist yet, the delegate call does not revert, but nothing is written to storage. - The proxy is now deployed at its expected deterministic address, but it’s uninitialized.
- An attacker deploys the implementation contract, then calls
setup()
themselves—setting their own owners and threshold.
Safe address theft.
Boom. They now control your Safe address before you even get the chance to initialize it.
How to Prevent This
Good news—this attack is mitigated in several ways:
- Safe v1.4.1+ fixes this issue by explicitly checking for code at the implementation address before deployment.
- OP chains are safe because they preinstall Safe implementations, blocking attackers from front-running deployments.