# Technical Spec: Lido<>Cosmos bridge *Authored by Kai Tyurin* This doc describes possible technical specification for a bridge-agnostic model of managing Lido staked Eth on Cosmos chains. The aim of the spec is to solve issues of liquidity fragmentation and reduce any bridge-related issues, such as vendor lock and possible vulnerabilities. It mostly addresses this section of the previously made stETH bridging spec: https://hackmd.io/@lido/BJGOoX2hF#Ethereum-state-communication-channel # Overview ``` ┌───────────────────┐ ┌─────────────────┐ ┌───────────────┐ │ Ethereum │ │ Neutron │ │Cosmos chain 1 │ │ │ │ │ │ ┌─────┐ │ │ ┌─────┐ ┌────┐ │ │ ┌─────┐ │ ┌───┼─────►│Users│ │ │ │Users│ │Lido│ │ │ │Users│ │ │ │ └─────┘ │ │ └──▲──┘ │DAO │ │ │ └─▲───┘ │ │ │ │ │ │ └─┬──┘ │ │ │ │ │ └───────────────┘ │ │ │ │ │ │ │ │ │ │ │ │ │ ┌────▼────┐ │ │ ┌───────────────┐ │ ┌──▼────┐ │ │ │ │Lido │ IBC│ │ │Cosmos chain 2 │ │ │Lido │ │ │ │ │Satellite│◄────┼───┼─┐ │ ┌─────┐ │ │ │Mission◄──┘ │ │ └────▲────┘ │ │ └─┼─────►│Users│ │ │ │Control│ │ │ │ │ │ │ └─────┘ │ │ └─▲─────┘ │ │ └───────┐ │ │ │ │ │ │ │ │ │ │ │ └───────────────┘ │ │ ┌─────────┐ │ │ ┌─────────┐ │ │ │ │ ├─►│Bridge │◄─┼──────┤►│Bridge ├──┤ │ │ ┌───────────────┐ │ │ │adapter 1│ │ │ │adapter 1│ │ │ │ │Cosmos chain 3 │ │ │ └─────────┘ │ │ └─────────┘ │ │ │ │ ┌─────┐ │ │ │ │ │ │ │ └───┼─────►│Users│ │ │ │ ┌─────────┐ │ │ ┌─────────┐ │ │ │ └─────┘ │ │ ├─►│Bridge │◄─┼──────┤►│Bridge ├──┤ │ │ │ │ │ │adapter 2│ │ │ │adapter 2│ │ │ └───────────────┘ │ │ └─────────┘ │ │ └─────────┘ │ │ │ │ │ │ │ │ │ │ ┌─────────┐ │ │ ┌─────────┐ │ │ │ └─►│Bridge │◄─┼──────┤►│Bridge ├──┘ │ │ │adapter 3│ │ │ │adapter 3│ │ │ └─────────┘ │ │ └─────────┘ │ │ │ │ │ └───────────────────┘ └─────────────────┘ ``` ## High-level components The whole thing consists of several main parts: 1. Mission control [settled on Ethereum] 1. holds locked wstETH on the Ethereum side 2. allows Lido DAO to manage Satellite on the Neutron side 3. communicates with bridge adapters in order to transfer messages through the bridges 2. Satellite [settled on Neutron] 1. mints wstETH on Neutron 2. handles possible Eth-staking-on-Cosmos logic 3. handles possible rebase of stETH-on-Cosmos 3. Bridge adapters 1. implement all the bridge-specific behavior ## Modular system Each component consists of several modules: 1. Mission control: 1. Common module 2. Receiver module 3. Sender module Satellite: 1. Common module 2. Receiver module 3. Sender module Any bridge adapter: 1. Common adapter interface module 2. Bridge-specific sender module 3. Bridge-specific receiver module By messages (handled by Sender and Receiver) we mean the day-to-day messages mostly issued by users. These messages are bi-directional since tokens can be transferred in both directions thus both Mission control and Satellite need to have both modules. Regular messages are to be executed as fast as possible. <aside> ❗ For more sensitive messages, such as the Satellite upgrade, a special handler can be implemented. Such a handler can have additional timelock/ability to overrule the message or some other hardening. Still, it’s out of the scope of MVP and can be defined further. </aside> ## Modules specifications ### Common Storage | storage name | type | who can access | description | | --- | --- | --- | --- | | bridge_adapters | [<address, name>] | bridge_adapters_update [write] | list of bridge adapters to work with | | owner | address | owner_update [write] | address that is able to manage the contract | Methods | method name | who can call | inputs | description | | --- | --- | --- | --- | | bridge_adapters_update | owner | [to_add] [to_delete] | adds or removes bridge adapters | | owner_update | owner | new_owner | updates owner | ### Receiver Storage | storage name | type | who can access | description | | --- | --- | --- | --- | | threshold | int | update_threshold [write] execute_message [read] | number of bridges that should approve the message to consider it | | receive_messages | id → <hash → <message (optional), votes>, time, status> | add_message [read/write] execute_message [read/write] | messages to process | Methods | method name | who can call | inputs | description | | --- | --- | --- | --- | | add_message | bridge adapters | id hash data [optional] | if message doesn’t exist, creates it if message exists and executed, all changes are ignored if message exists timeout is expired, it’s recreated for existing/created message adds a new hash to the map or adds a voting for existing one | | execute_message | permissionless | id hash data [optional] | if message exists for given id/hash and bridge votes for it more than threshold, validates and executes the message | | update_threshold | owner | new_threshold | sets new threshold | **Why such a complex messages structure? Why have `hash → <message (optional), votes>` map instead of just `hash, message (optional), votes` structure?** We assume a bridge might misbehave. During misbehaving it’s able to create spam hashes for different message ids and thus dos txs from being transferred. By having a single hash we’d need to have a logic of deciding which one is correct. Having a map of them we’re always able to execute the correct message regardless of spam made by any misbehaving bridge. **Why have a timeout?** Without timeout during the bridge hack an attacker is able to make a “reserve for a future”, e.g., transfer transaction of a huge amount of tokens to the smart contract that will divide the sent tokens between this attacker and any future one. Such a smart contract will be a proposal of collusion, and without any built-in expiration for a message it needs to be explicitly removed. </aside> ### Sender Storage | storage name | type | who can access | description | | --- | --- | --- | --- | | send_messages | id → <msg, hash> | create_transfer [write] send_transfer [read] | create_transfer puts messages there | Methods | method name | who can call | inputs | description | | --- | --- | --- | --- | | create_transfer | permissionless | asset to transfer gas payment compensation recipient | creates send_message and calls send transfer for it | | send_transfer | permissionless | send_message id gas payment compensation list of bridges [optional?] | sends messages to corresponding bridge adapters | | crete_general_msg | owner | general message gas payment compensation | creates send_message with an arbitrary message content | **Why do we need a separate permissionless send_tranfer method? Why not do everything by a single method?** For recovering the tx in case of bridge hack/outage/bug ### Common adapter interface Storage | storage name | type | who can access | description | | --- | --- | --- | --- | | owner | address | update_owner [write] send_message [read] | Mission control or Satellite address | Methods | method name | who can call | inputs | description | | --- | --- | --- | --- | | send_message | owner | message gas payment compensation | sends message to the adapter on the other side | | update_owner | owner | new_owner | updates the owner | # Full bridge outage Two important things should be of our attention: 1. in practice, we’re talking about only two bridges: Wormhole and Axelar 2. the threshold shouldn’t be less than 2 since in this case single bridge being hacked compromises the whole system It creates the risk of one of the bridges being down for a long time and completely blocking the system of operations. There’re several possible scenarios preventing that: 1. onboarding “minor” bridges: Gravity/Sifchain/… 1. no additional security risk since the system is resistant to a single bridge hack 2. the third bridge might be disabled by default and activated only when it’s needed 3. this also can be used to smoothly handle temporary outages 2. making pseudo-bridge managed by multisig (this multisig will behave as a bridge and will be able to approve the necessary messages when it’s needed) <aside> ⚠️ it creates the risk of collusion between this multisig and a bridge attacker </aside> 3. making pseudo-bridge controlled by Neutron DAO/SubDAO — same as previous but more decentralized # Bridge adapters design This is TBD yet. Still, as it was already mentioned, de facto we’re talking about two bridges: Axelar and Wormhole. ## Axelar Satellite bridge by Axelar has the native support of general messages passing which makes the integration very straightforward. https://docs.axelar.dev/dev/general-message-passing/overview ## Wormhole At the moment, Wormhole functionality is much less. In Cosmos, Wormhole is deployed on 3 chains: 1. Injective 2. Terra v2 3. Terra Classic <aside> ❗ Regardless of the recipient being on one of those chains, Lido Satellite settled on Neutron still being able to get those messages via Interchain Queries and send them via Interchain Accounts </aside> <aside> ❗ This also can be treated as an opportunity allowing to diversify Wormhole bridging through different Cosmos chains, even when direct transfers on Neutron become possible </aside> Unfortunately, currently, even NFT transfers aren’t supported for Cosmos chains. The other drawback is that the transaction is needed to be explicitly claimed on the other side of the chain via issuing a special transaction. However, as already described [in the existing research](https://hackmd.io/@lido/BJGOoX2hF#Option-2-the-lethSTATE-signaling-token), it’s doable to overcome these issues with a special token workaround. Because Lido StarLadder has a modular architecture, it will be possible to smoothly migrate the system to a new adapter if new features are provided. ## Other bridges For any other bridge existing now or going to be deployed in the future, it’ll be possible to write an adapter for. # Roadmap The proposed model can be implemented iteratively. v1.0: wstETH bridging with a single bridge. v1.1: adding one more bridge v1.2: adding a third bridge for more reliability v2.0: adding staking directly on the v3.0: adding rebasing stETH bridging # Benefits and drawbacks Benefits: 1. Avoiding liquidity fragmentation 2. No bridge vendor-lock 3. Smooth work even one of the bridges outage 4. More control over assets 5. Bridge-related security risks are reduced Drawbacks: 1. Double price for bridge transfers 2. Additional smart-contract risk 3. Probably pretty complicated off-chain infrastructure