100 ETH were assumed lost but could eventually be recovered. Here's what happened, how it became a happy ending and what's needed to prevent this from happening again.
Context
A user of Safe{Wallet} wanted to bridge 100 ETH from Mainnet to Base. But then they realized that they can't actually access the funds on the Base. The Safe on Base had a different set of signers than their original Safe, meaning they had no control over it. How can this happen?
Unlike EOAs (Externally Owned Accounts), smart accounts like Safe are governed by deployed smart contract code. It's technically possible to deploy a smart account with the same deployment config (same signers) on different chains at the same address (using counterfactual deployment). So normally bridging to a chain where the smart account is not deployed yet is merely an annoyance as the user first has to deploy the smart account before they can access the bridged funds.
But this case was different. The user used their @Safe smart account since 2020. The smart account version from back then (v1.1.1.) was not yet written with multichain in mind, so it was possible for anyone to deploy a smart account on a different chain with completely a different config at the same address. Something that has been changed since the v.1.2.0. version.
Rescue
Once the Safe team became aware of the incident, @tschubotz took immediate ownership. He examined the Safe on Base and noticed that the address had been deployed by an account that had preemptively deployed many other v1.1.1 Safes on Base.
Through further onchain analysis, the trail led to @protofire. As it turns out, the Protofire team was aware of this edge case for older Safes and white-hat deployed Safes to frontrun a malicious hacker taking advantage of it.
So just two hours after the incident was reported, there was hope that the funds could indeed be recovered. And few minutes later, a first test transaction and then a full transfer of the 100 ETH back to the user could be done.
This is commendable anticipation of @protofire, strong leadership from @tschubotz and fantastic support by the wider @Safe team to get the funds safely back to the user. 💪
Learnings
The root cause was the use of an older Safe version (v1.1.1), which didn’t account for multichain deployments. Since version v1.2.0, Safe includes protections that prevent conflicting deployments across chains by modifying how the CREATE2 salt is constructed.
To bridge, the user chose the native bridge integration which is essentially a @lifiprotocol widget but with some optimizations for smart accounts. For example, the bridging feature warns users explicitly if there is NO code at the destination chain, meaning that no smart contract was deployed there. However, there was no warning in place for there being different code deployed on the destination chain. This additional layer of protection has now been introduced to cover the edge-case for old v.1.1.1. accounts.
The deeper fix lies in improved keystore infrastructure (like keystore rollups) that can guarantee a consistent account config across chains. Until then, deployment behavior will remain difficult to reason about for developers and end-users.
Finally, we are still at a point where users are expected to do test transactions before moving bigger funds. This is not scalable and shouldn't be expected from users. There needs to be more innovation around hooks, guards, and other safety mechanisms that allow strong protections for users.
I'm glad this case could be resolved with a happy end and there is important learnings for wallet developers, especially ones using smart accounts. But it also clearly showed once again that a lot more work is ahead of us to truly make self-custody easy and secure for everyone.
We published an advisory for a bug in Plonky3's FRI verifier: https://t.co/1an5IUIycV
Thanks to Malte Leip (Zellic) for reporting the issue, and @AngusGruen for the fix.
Is anyone safe using DeFi?
A user on @Uniswap v3 was just sandwiched attacked out of $216k while simply trying to swap $221k USDC to USDT.
Mind you, this was a pool that had over $35m of USDC and USDT it.
This is insane.
How did it happen?
An MEV bot front-ran the tx by swapping all the USDC liquidity out.
After the transaction executed, they put back the liquidity.
The attacker tipped a block builder (bobTheBuilder) $200k and profited $8k from this transaction.
-----
A few ways to try to avoid this:
1. Reduce slippage tolerance on transactions
2. Don't use Uniswap. Use cowswap or another aggregator - which can provide better execution + prevent this malicious MEV
3. Use a custom RPC that doesn't expose your transactions publicly
-----
What is Uniswap's responsibility here?
We can't live in a world where a user executes a simple swap of $221k in a liquid stablecoin pool and gets rugged.
----
P.S. data team @the_defi_report is cooking. Going deep on MEV to share the economics of various chains from the ground up.
Might not be pretty.
If you want to stay on top of all the insights we're sharing, you can sign up below 👇
🧰 All your smart contract security tools are shit
...Or at least, according to a recent research study
After analyzing 516 bugs across 2021-2022, they discovered:
- How good our tools are
- How to categorize web3 bugs
- How to use this knowledge to win $102k in audit contests
it's not a sandwich attack
the victim lost his money in this swap https://t.co/b70gd5gayU
1. victim didn't set a reasonable slippage
2. the aggregator chose a dead Uniswap v2 contract
So @adam3us invented hashcash as a spam prevention mechanism.
Then satoshi utilized this in #bitcoin to solve double spending.
And now folks waste precious blockspace by spamming jpegs?!
Why creating the #lightningnetwork in the first place if the base layer allows this shit?!
Secure on-chain randomness is a topic that has been touched on a lot over the past few years.
In the latest blog, by @paradigm Engineering, @sina_eth_, @gakonst, and I explore and implement secure randomness on Ethereum using SNARKs and VDFs.
https://t.co/ixoN9NVTiI
Caulk is out! Caulk achieves zero-knowledge lookups and membership proofs up to 100x faster than Poseidon Merkle trees. Joint work with Mary Maller, @VitalikButerin, @Khovr, @13portocale and @CryptoSimkin 👇🏽