Sequence Wallet - Introducing Light State Sync and full merkle wallets

June 21 2023

Sequence v2 - Introducing Light State Sync and Full Merkle Wallets

The Sequence Wallet has just undergone a substantial infrastructure upgrade, bringing numerous improvements and advancements to the Sequence protocol. This update guarantees a more robust and user-friendly experience for developers integrating Sequence into their projects and individuals utilizing the Sequence Wallet in the web3 realm.

For those who would like to know more about this update without delving into the technical details, today we also released an announcement introducing all the expected benefits developers and end users should expect.

But, to cater to the curiosity and needs of our developer community, we  also put together this technical update, which features a step-by-step explanation of how the new Sequence Wallet is able to ensure speed and cross-chain syncing without incurring significant gas costs or compromising security. 

State Sync, The Missing Piece

The Ethereum ecosystem is experiencing a broader push for replacing Externally Owned Accounts (EOA) wallets with more advanced smart contract wallets. This technology brings powerful features to users, such as social recovery, key rotation, batch transactions, gasless transactions, and more.

Significant progress has been made in improving ecosystem compatibility with these types of wallets. For instance, EIP-4337 provides a universal relayer that can be used by most wallets, EIP-1271 enables smart contract wallets to sign messages, and EIP-6492 allows these wallets to sign messages even when not deployed.

We are in the golden age of Layer 2 solutions (L2s) for Ethereum, with a wide buffet of offerings including Arbitrum, Optimism, Polygon zkEVM, and many more. However, this plethora of options is a double-edged sword, leading to a new predicament: information from one L2 is not easily transferable to another L2.

This results in fragmentation, which affects almost all projects that want to operate on multiple chains. Users expect their wallets to work across various chains, and smart contract wallets are no exception.

The Wallet Address

The first issue is the wallet address. With EOAs, you can rest assured that your wallet address will be the same on all EVM networks. However, with smart contract wallets, this may not be the case.

Fortunately, we can make use of EIP-2470 to ensure that our wallet will be initially created with the same address on all truly EVM-compatible networks.

Wallet Keys Lifecycle

One of the biggest strengths of smart contract wallets is the ability to change the underlying keys by adding, removing, rotating, etc. This can be done for various reasons; social recovery is a common example. This flexibility is what makes smart contract wallets special.

However, there is a catch. When you create your smart contract wallet, it has a common state across all networks, which is good. But as soon as you make a change on one network, that property no longer holds true; your networks are out of sync.

Image description: A user adds a new signer “C”, but this action only takes effect on Arbitrum.

--

Let’s imagine that “C” represents the user opening a new session on a new device or a company adding a new employee to their multisig. This behavior leads to challenging scenarios that are confusing for the user and almost impossible for the interface (UX) to handle gracefully.

The user would still need to maintain access to signers A & B because, without them, they cannot perform transactions on Polygon or Ethereum using signer “C”; it doesn’t exist there yet.

Why Not Use a Bridge to Sync the State?

This has been proposed several times, but there are issues with this approach. The primary concern is practicality; most bridges take several minutes to send information back and forth. This makes them impractical for use cases where “C” might need to be used immediately; imagine opening a session and having to wait 15 minutes for the action to propagate to Polygon.

Another concern with bridges is security. Bridging is difficult, and it’s not uncommon for bridges to use multisigs on one end (or fallback to them). While this approach may be suitable for asset swapping, wallets are a long-term commitment. Designing a wallet that could be fully compromised by a bridge multisig is not an acceptable risk.

Light Wallet Sync

Light wallet sync is the approach that we found to work best in addressing this issue. It employs proto-state channels to disseminate information on all networks simultaneously.

We can achieve this efficiently because our wallets are smart contract wallets. We can create a custom message schema that isn’t dependent on the network’s chainId, allowing a single signature to be used on any network.

We can then sign a special payload, which acts as a sort of “delegation of control” to a new set of signers. This allows users to sign a message, instead of sending a transaction, every time they want to make a change to their wallet configuration. The last set of signers on the chain can later be used to sign any regular payload, be it a transaction or a message.

Image description: The user “presigns” a payload adding key C, then signs a new payload replacing key B with D. The on-chain state remains A and B, but the user can now sign using A, C, or D.

--

These pre-signed payloads are valid on all networks simultaneously, including networks that don’t yet exist at the time of signing. This means that a user who creates a wallet today and adds or removes signers over the next two years can still use these added signers on a network that might be launched in 2025.

The next time a user operates on any of the chains, another transaction can tag along for the ride (smart contract wallets support batching!), updating the on-chain state to match the latest “pre-signed” state. This way, the chain gets updated, and signer B can no longer be used.

Image description: The user makes a transaction on Arbitrum, and Sequence uses the opportunity to update the on-chain state there. The pre-signed payloads are no longer needed.

--

What about compatibility?

In Sequence, we allow these chained signatures to be concatenated. The entire resulting chain fits neatly inside the signature field.

This approach offers several advantages. It makes the implementation transparent to third parties. A dapp doesn’t need to know that the signature returned by Sequence is, in fact, internally delegating control multiple times before signing. They simply see a slightly longer set of bytes.

Another advantage of implementing it this way is that the feature seamlessly integrates with EIP-1271, EIP-4337, EIP-5719, and EIP-6492.

But what does it look like?

Let’s take a closer look with an example of a “chained” Sequence signature.

0x030000ea000500000004020314327739c49f93a04c38623b54a4a75b49e6f646000062010001000000000001482fa2ca36fb44cf7aadeb0d5edb2058460a0e128ab8b1a25046b238077bc204536eb5fda70161b84a4c9aa90a7ea0ce2972eaebdb2237532d890b1c8d6cae251c020101b1f69536d293ee3764ce9881894a68029666a8510303000000000000000000000003c5b0a31f0bc8826cfa50ca7ff9ef8c9575b455cd04000044000299db45fa81db22da69760a8bd50cd7e05942d3cfbe2a7958964ff82ddee6ab6417694d85fba90531538345149694f75cc2706a682a8c841ea8f103b578f71aa71c020000bb02000500000003010314327739c49f93a04c38623b54a4a75b49e6f6460003542ea3eadd73da47d8d21ef396b16de52a4a06966d38543e27f99451060f65200ff1156ae2e0d65b3e8744d69c605df7d0626c2170ded9106f6086cf83fac5661b02010249347ff9f42abbec20688c29dfd46b89833be98b0002aff316fdbebdecd551e44907d1d31ab8c9b1f90233e9a240e7cc997ec16f503136a31cd75bb25e95478abd15873feb01cb686e2adaa5dd3058fa66f22446fa901b020000dc020005000000000102434cafcb9284bcbf43e7ca0474332da42b1ec511020314327739c49f93a04c38623b54a4a75b49e6f64600006202000100000000000193103acf7b5de30967049e72c072b480bc94998d5db85901ecabaffcc18b8bf900b0a5d176ac0c60f87f3db2f235c4afc977972c4b9273b1111765412bf568131b020101b1f69536d293ee3764ce9881894a68029666a851030003ddbd5d2cfbce11ff281d20cff6e1a3d62e4c2b724c6169674adc5e47143dfcc32ecb3b06c7a79228b219b2824c799117bf24d79664ed19ab9f526778a36403b21c02

At first glance, it looks like some sort of payload - slightly too lengthy to be a signature. But let’s break it down and add a bit of color for clarity.

Image description: Color-coded chained Sequence signature, where yellow, green, and cyan display the different members of the chain.

--

The first byte (purple) is the identifier; we use it to inform the smart contract wallet that this is a “chained” signature. Since chaining signatures isn’t always necessary, it’s crucial to be explicit when it’s required.

The First Part

The yellow section is our “primary” signature. It’s a regular Sequence signature for the payload we want to sign (in this case, a transaction). However, if we tried to use this signature as is, it wouldn’t be valid because the on-chain state doesn’t match this set of signers.

Our latest wallet state, and thus the one that the yellow signature uses, is defined by the Merkle root:

0x1e612d0c4396ad9e49a1569bd8a885c30320f013a90f8c6e80e75d92d084a323

However, our on-chain state contains this Merkle root instead:

0x4172c860b24519291d9eb8299aa5411c2543642b3ff4a744f1bea461537e327e

Intermediate Delegation

Luckily, we pre-signed a payload authorizing 0x1e61...4a323 (green) the last time the user logged into the wallet, so we can use it to validate our primary signature.

Yet, we signed this payload using another state:

0x783da14a11a75fdca7905526f6bbed28dfe4f40c22a13d8e7a5e6245e960a4a7

This doesn’t match the on-chain Merkle root either.

Initial Delegation

Fortunately, we signed an authorization for 0x783d...a4a7 using 0x4172...e327e (cyan), which finally links our chain to the current on-chain state.

Wrapping Up

This signature serves as an example demonstrating how we can use the chain:

0x4172...e327e -> 0x783d...a4a7 -> 0x1e61...4a323

as a means to sign messages using the 0x1e61...4a323 state, even when that state doesn’t exist on-chain yet.

All of this information can be encoded into a single field, making it transparent to any EIP that deals with account abstraction.

Feel free to check out this signature in action.

What's the tradeoff?

There is always a catch or a tradeoff. This feature entirely guarantees that the user should be able to make use of the new signers that are added to the wallet, but it doesn’t provide such strong guarantees when removing signers.

If the user removes a signer, let’s say “B”, then such a signer can still be used unless a transaction is sent for every one of the chains where “B” was added.

This limitation is somewhat mitigated by the fact that the user will most likely hold assets on networks that are regularly used. Consequently, the day-to-day operations of the wallet on these chains should have the side effect of keeping the configuration updated on-chain as well.

Additionally, we can ask the user about the level of urgency for removing a given signer. If the user believes that signer “B” is compromised, we can always fall back to the previous behavior and send the update on-chain across all networks.

Data Availability

The system leans heavily on off-chain data, and like any system dependent on off-chain data, it requires this data to be consistently available for seamless functioning. If the data were to be lost, the wallet might lose access to its latest state, or even worse, become non-functional.

Currently, we employ a mixed approach to tackle this issue:

  1. The wallet client is designed to store a copy of all relevant data for a given wallet. Since a wallet only needs to store its own share of the data, this ensures that all users should have access to their own copy at all times.

  2. We also retain a copy of all data on our servers. This provision enables users to regain access to their wallets in case their copy is lost or corrupted.

It’s important to note that this data is not sensitive in nature. The reason it doesn’t exist on-chain is to reduce the gas costs of the wallet. The data itself does not grant any privileges, and users are free to create as many backups as they desire.

Full Merkle Wallets

You might be curious about the term Merkle root mentioned above. Also, this article refers to syncing state; what does that imply?

It is crucial to understand that when we discuss “state” in the context of a Sequence wallet, we are actually referring to the wallet’s configuration, which includes details such as the signers, their weights, and the wallet’s weight threshold.

The Basic Approach

Many wallets employ a simple pattern where they store all information directly in the wallet contract’s storage. This method allows for the following steps when you need to sign a transaction or a message:

  1. Send a list of signatures.

  2. Retrieve each signer’s weight.

  3. Compare the total weight with the wallet threshold.

  4. Accept the signature if it meets or exceeds the threshold.

While this approach is functional, it has significant downsides. Expensive to Use

This system necessitates numerous SLOAD operations every time you need to validate a signature. To be precise, the minimum required will be N + 1 (where N is the number of signers that are required).

Expensive to Update

This issue is not only present during signature validation but also when setting up the wallet and updating the set of signers. For example, if your wallet has an X/8 signers configuration, you will need to write to at least 9 storage slots when creating the wallet. If you want to redefine the set of signers, you now need to clear the 9 slots and define N new ones.

This is already inefficient and is further compounded by the fact that reading from and writing to storage will become more costly over time.

Synchronization Challenges

Having an unpredictable number of parameters that need to be synchronized inevitably complicates the syncing process.

It’s not just that your payload becomes dynamic, but you may also need to perform an uncertain number of storage updates across all networks if the wallet becomes compromised and the keys need to be rotated. This could quickly escalate into exorbitant costs.


This method of implementing wallet state has its limitations, but it can be practical for certain applications. However, it negates some advantages of using smart contract wallets.

Using Merkle Trees

A more efficient way to manage this information on-chain is often referred to as the “stateless” approach. It’s not entirely stateless; the state is still there, but it is not stored in its entirety in the contract storage.

Instead, we construct a Merkle tree using the information we need. Whenever we need to read data, we provide the data along with a proof.

Image description: An example Sequence configuration with 3 signers. The yellow highlights the data required to be embedded when signing a message using Signer A.

--

This approach offers several advantages, the most notable being that the data needed to validate a signature is capped to O(log n) when using a single signer. This means the complexity of the wallet configuration can increase without sacrificing usability.

Another significant benefit is that deploying and updating a wallet with any kind of configuration has a fixed cost. We only need to store 32 bytes, regardless of the number of signers, or their layout.

Extending the Merkle Model

This efficient schema for storing wallet state enables us to build additional functionalities that would be prohibitively expensive if we had to store everything in contract storage.

Nested Configuration Groups

By adding another type of leaf, we can replicate this pattern internally, allowing the wallet to adopt configurations that would not be feasible in traditional setups.

We refer to this type of leaf as “nested trees”. It contains an internal Merkle tree root, threshold, and external weight. If the internal threshold is met, the external weight is applied to the parent signature.

Image description: Sequence wallet configuration with 4 signers, distributed in two groups. Group red and purple act as independent sets of signers. A signature from each group is needed for validity, but two signatures from the same group won’t suffice.

--

Such configurations are beneficial in scenarios where multiple entities need to manage a shared wallet. These entities might themselves be complex (such as departments or different companies), necessitating greater expressiveness than a single key can offer.

It should be noted that while this setup can be emulated using classic multi-signature wallets and combining them (using multisigs as signers for other multisigs), it would be less efficient and more challenging to manage across multiple networks.

Static Signatures

In some cases, a wallet may need to approve a payload without having to re-sign it every time the set of signers changes.

For this purpose, we can add a static signature leaf to the configuration. This is a special piece of data that informs the wallet contract that a signature for such a payload should always be considered valid.

Image description: Sequence wallet configuration with 2 statically signed payloads, one is an Opensea order and the other is a governance vote.

--

This allows a wallet to sign multiple payloads and ensure their validity for as long as necessary, without having to re-sign each payload every time the signers change.

This is especially useful in applications like NFT marketplaces, where sell orders are often handled as signed payloads that only interact with the blockchain when a buyer completes the order, or in governance processes that need to validate signatures off-chain.

This feature integrates seamlessly with Merkle tree configurations, allowing an unlimited number of statically defined signatures to be written into a wallet while keeping the cost fixed.

EIP-5719 can be used to update the Merkle proof “signature” every time there is a change in the set of signers.

What’s to Come

As the EVM ecosystem evolves, we are working hard to ensure developers are always best equipped to build new and exciting web3 experiences with minimal technical hurdles.

We are pleased with the progress we have made so far. The Sequence Wallet now supports different forms of key management with ease, even when dealing with multiple chains. The expressiveness of the Merkle configuration allows us to implement these in a highly efficient manner.

There is still more ground to cover and aspects to improve. We are working on adding a decentralized option to address data availability issues. Leveraging existing technologies such as IPFS or Arweave would represent a significant advancement in the decentralization of this data.

Additionally, we are developing incremental updates for Light State Sync. By utilizing oracles with reduced trust, we believe we can mitigate the risks posed by malicious actors exploiting intermediary states for attacks.

In the meantime, if you wish to see the Sequence Wallet in action, create one on sequence.app! Our contracts are open source and can be all found in our contracts repository.

You are also welcome to explore all the features and benefits of our all-in-one web3 developer platform, built with developers and end users in mind. No matter whether you are a web3 native or someone curious to know what the future will look like, our stack covers your web3 development needs and ensures your users will keep receiving the optimal experience they deserve. 


Sequence is the leading all-in-one development platform for integrating web3 into games. Onboard, monetize, grow, and retain players with Sequence’s award-winning technology. From collectibles and ownable rewards to fully on-chain experiences, Sequence’s easy-to-integrate platform solves blockchain complexities, so developers can focus on creative execution and delivering amazing player experiences. Trusted by hundreds of games and thousands of developers. Sequence is backed by Take-Two Interactive, Ubisoft, Xsolla, Bitkraft, Brevan Howard, Coinbase, Polygon, and more. To learn more, please visit: https://sequence.xyz/


Written by

Agustin Aguilar

Director of Blockchain Research at Sequence

Stay up to date with Sequence

We'll keep you informed about the latest and best in web3 game development.

Stop fretting web3. Just build.

Create now with the Sequence Builder or with our developer docs. Want to learn more? Chat with a product expert or join our Discord community.