After Action Review of the Exploit of a Layer2DAO Multisig on October 22, 2022

Layer2DAO
6 min readOct 30, 2022

On October 22, 2022, Layer2DAO suffered an exploit that gave an attacker control of 49,950,000 L2DAO tokens. The attacker proceeded to sell 18,710,323 L2DAO on the open market, depressing the token value by as much as 90%. Our team was able to recover the remaining 31,239,677 L2DAO through an OTC purchase from the attacker. This post outlines the details of the exploit and how we hope other teams can prevent similar attacks.

Optimism Token Expansion

In July of 2022 Layer2DAO was in the process of expanding its L2DAO token to its second Layer 2 network, Optimism. Our token is native to Arbitrum. We had set up partnerships with two bridge providers, Synapse and Multichain, and launched a canonical token contract on Optimism using Celer’s Open Canonical Token Bridge Standard. We already had set up a Gnosis Safe multisig on Optimism using the official Gnosis Safe UI and with the same signers as on Arbitrum.

Since we were launching with two bridge providers, we wanted to ensure there was enough token liquidity in each bridge in case things got out of balance (for example, someone bridges to Optimism using Bridge A, but back to Arbitrum using Bridge B). Therefore, we were planning on bridging 100,000,000 L2DAO (10% of the L2DAO total token supply) from the Arbitrum treasury multisig to the Optimism treasury multisig, with 50,000,000 L2DAO being sent via each bridge.

Bridging to Optimism and Multisig Setup

On July 16, 2022, we were ready to initiate the bridging process. We queued up the first transaction in Synapse as planned. We connected to our multisig via WalletConnect, initiated the bridge to Optimism, signed the transaction in Gnosis Safe and off we were. Before the first Tx even completed, it hit us that we had just made a mistake and bridged the tokens to a non-existent address on Optimism, since our Gnosis Safe on Optimism has a different address than on Arbitrum. As power L2 users, we have grown accustomed to bridging between L2s directly from our EOAs; we had fallen into the same routine when we attempted this bridge transaction. At the time Synapse did not have the option available in the UI to designate an alternate recipient address. We routinely bridge through L2s using EOAs, and we unintentionally sent this Tx to the same address, which was not the correct process.

At this time in July, it had only been a few weeks since the Optimism Foundation had sent 20 million OP tokens to a non-existent Optimism multisig address to Wintermute, and so we immediately started researching that incident to learn from it and address it, including how the hackers were able to exploit that address. We found documentation by the Gnosis Safe team on how to recreate a Gnosis Safe address on another network and immediately began executing on the steps to rectify this situation and create a Gnosis Safe multisig on Optimism using the same initialization parameters as on Arbitrum. It was our understanding that this would result in us having a multisig with the same address as on Arbitrum and the tokens would not be at risk.

Unfortunately, the official Gnosis Safe Optimism deployment uses a different singleton contract than the deployment on Arbitrum, meaning we were going to have to create our Optimism contract using a singleton contract that is not supported in the Gnosis UI. But we felt that safeguarding the funds in a multisig contract was the top priority; and so we did this, and felt that the matter was sufficiently resolved, we would address retrieving the funds at a later point in time.

We created the contract by calling createProxyWithNonce using the same singleton address as used on Arbitrum (0x3e5c63644e683549055b9be8653de26e0b4cd36e). At this point our understanding was that the wallet that created the multisig is set by default to be the owner. But since the implementation contract only existed on Arbitrum, the fallback method was hit and this meant: the Gnosis Safe contract was successfully created, but not initialized. This slight distinction was what ultimately allowed the attacker to call the function setup owner on the created but not initialized contract and carry out the attack.

The Exploit

On October 22, 2022, the exploiter ran a single transaction that called setup owner on the uninitialized multisig contract, created a temporary contract to transfer all L2DAO to, bridged 10,000,000 L2DAO to Arbitrum via Synapse, and transferred the remaining L2DAO to a new EOA. After this, the exploiter sold 18,000,000 L2DAO to OP tokens on Optimism and 610,323 L2DAO to ETH on Arbitrum, pushing down the price of L2DAO by 90%.

If the exploiter had sold all the stolen L2DAO tokens immediately, we could have licked our wounds and moved on. But since they were still holding 31,239,677 L2DAO tokens, we needed to find a way to get control of those tokens or they could have kept selling them over the coming days, weeks, or months, leaving the team and token holders of the DAO susceptible to random crashes of the token price, which would effectively have left the DAO in a perpetual vulnerable position, essentially disabling our DAO.

As a next step, we took a long shot and sent the exploiter’s wallet a message on both Arbitrum and Optimism:

Are you open to selling us your L2DAO tokens for ETH in an OTC trade? Exo from Layer2DAO

To which they responded:

You can send me a 1inch p2p offer to this address

After establishing communication with the exploiters, our next step was to figure out how much to offer the exploiter. The L2DAO token price had recovered to over $0.002 at that time (apes were buying the dip), but we also knew–based on analyzing the current liquidity at the time–that the exploiter wouldn’t be able to sell their remaining tokens anywhere close to that price. With this in mind, we decided to offer them just around $0.001/token, or 7.5 ETH for the 9,389,677 tokens on Arbitrum and 15 ETH for the 21,850,000 tokens on Optimism.

But this wasn’t our only plan. In case this negotiation headed south, we were also considering temporarily disabling the bridges between Optimism and Arbitrum to isolate the majority of stolen tokens on Optimism. Therefore, we decided to make the first offer on Arbitrum, followed by Optimism only if the exchange was successful on Arbitrum.

We sent the following message to the exploiter on Arbitrum and Optimism:

We sent you an offer on Arbitrum. Once you accept, we will create an offer on Optimism as well.

We set up the P2P offer on 1inch on Arbitrum (7.5 ETH for 9,389,677 L2DAO), sent the exploiter another message with the link to accept the offer, and hoped for the best. Fortunately, within minutes the exploiter accepted the offer and 9,389,677 million of our L2DAO tokens had been returned to us. We immediately set up the second P2P offer on 1inch on Optimism (15 ETH for 21,850,000 L2DAO) and sent the exploiter another message with a link to accept the offer. Fortunately they accepted that offer as well and at this point all our precious L2DAO tokens had been returned to us and the incident entirely resolved, with the damage being the harm to the token price and the loss of treasury assets paid to the exploiter.

Takeaways

One big takeaway from this exploit is that we as an ecosystem definitely need better documentation and support for Gnosis Safe with alternative singleton contracts. The documentation that does exist is limited, and it’s hard to ask for support since anyone who knows or finds the contract address could potentially front-run the recovery, therefore limiting the recovery efforts to only the most trusted circle. At the time of the recovery effort someone on the Gnosis Safe discord was hinting towards building a custom UI that would support custom singleton contracts. We were looking forward to that or better documentation to help us recover the funds from the multisig contract. Unfortunately we had to witness a team’s worst nightmare happen in front of our eyes as the contract wasn’t initialized correctly when we set it up, and the funds weren’t protected like we believed they were, which allowed the exploiter to eventually take control of and drain the contract.

In the end, this exploit cost us 22.5 ETH from our treasury and the token price took a big hit. While unfortunate, we are glad we were able to wrap up the exploit in a matter of hours, allowing us to focus on token price recovery and the path to moving forward.

--

--