From 345268bc9b1b8495ff48561c3c4436e2f2b7076c Mon Sep 17 00:00:00 2001 From: JafarAz Date: Thu, 17 Aug 2023 21:00:42 -0300 Subject: [PATCH 1/2] some-moar --- code/xcvm/SPEC.md | 657 ------------------ code/xcvm/otp.md | 204 ------ docs/docs/intro.md | 61 +- .../networks/picasso-parachain-overview.md | 35 +- docs/docs/networks/picasso/crowdloan.md | 2 +- docs/docs/networks/picasso/pica-use-cases.md | 2 +- docs/docusaurus.config.js | 6 +- docs/sidebars.js | 3 +- 8 files changed, 24 insertions(+), 946 deletions(-) delete mode 100644 code/xcvm/SPEC.md delete mode 100644 code/xcvm/otp.md diff --git a/code/xcvm/SPEC.md b/code/xcvm/SPEC.md deleted file mode 100644 index c3813998d0d..00000000000 --- a/code/xcvm/SPEC.md +++ /dev/null @@ -1,657 +0,0 @@ -``` -Composable Finance -Karel L. Kubat, Hussein Ait Lahcen -2022-11-01 -``` - -# Abstract - -Cross-chain Virtual Machine (XCVM) is a specification outlining an application-level messaging protocol between state machines and other execution environments. It allows for a more sophisticated mechanism for cross-chain communication compared to message passing, by defining an interpreter-based communication interface between chains. - -- Turing-Complete Interactions: Complicated business logic can be dynamically dispatched to other chains, without the need for developers to deploy contracts on the destination chain. - -# 1. Overview - -## 1.1. Document Structure - - -* XCVM is a DTCC-like protocol for blockchains. - - - Section 2.1. describes on-chain versioning. - - - Section 2.2. describes the instruction set. - - - Section 2.3. describes general asset amount handling. - - - Section 2.4. specifies the abstract virtual machine. - - - Section 2.5. outlines the execution semantics of a program. - -* Encoding programs is primarily done using protobufs. - -* Fees are charged at different stages, for bridging and execution. - -* Asset Registries provide ways to deal with ERC20, CW20, or native assets across chains. - -* Further work outlines planned extensions to the specification. - - - Section 6.1. elaborates on NFTs. - - - Section 6.2. provides a model for abstracting ownership and identities. - -* Security considerations to be made by users and implementors. - -## 1.2. Terms and Definitions - -The keywords "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [RFC 2119](https://www.rfc-editor.org/rfc/rfc2119). - -Commonly used terms in this document are described below. - -`Transaction`: A (reversible) operation on a chain. - -`Transfer`: Changing the ownership of an asset (token, NFT, etc) from one account to another. - -`Identity`: An entity that has an address. Note that identities may not have a public/private key, as they can be contracts. - -`Cross Chain Transfer`: The bridging of funds between two chains. - -`Cross Chain Transaction`: Two or more transactions on two or more chains. Note that a cross-chain transaction is not `transactional`. - -`XCVM Transaction`: A cross-chain transaction defined as XCVM instructions, being handled by interpreters. Technically an XCVM transaction can be single chain only, although the use case for that seems non-existent. - -`Message Passing`: Sending bytes from one chain to another. - -`Event`: A message emitted by a contract/module/pallet during transaction execution. - -`XCVM Event`: An event emitted by part of the XCVM contracts. - -`Beneficiary`: Recipient of assets. - -`Relayer`: Initiator of the destination side transaction, paying for the execution fees. - -`Tip`: Tip address for execution. - -`Opaque Contract`: Any smart contract, module, or pallet. - -`Chain`: A blockchain with its consensus and execution environment, but may also refer to rollups. - -`User`: A third party user of XCVM contracts. Can be another contract, module, pallet or actual human. - -`Implementor`: An entity implementing technology according to the XCVM specification. - -# 2. XCVM - -The `XCVM` refers to both a set of on-chain contracts, orchestrating the bridging operations, ownership, and execution, as well as the interchain system of bridges and relayers. This document mainly specifies the logic within a single chain, and how implementors MUST execute messages and maintain state. - -Although execution environments change depending on the chain, the `XCVM` protocol is generic over the differences and provides an abstract target for smart contracts to interact with. We describe components as separate contracts, but implementors MAY be a pallet, Cosmos SDK module, or a single contract as opposed to many. Here the choice is based made on gas optimizations, engineering standards, and security practices. - -`XCVM` is bridge agnostic, as long as the underlying bridging protocol is capable of generic message passing. Developers can opt-in to their usages for each interpreter instance. We highly recommend `IBC` if available, and by default only allow communication across trustless bridges. - -```mermaid -sequenceDiagram - participant IBC - participant Gateway - participant Router - participant Interpreter - IBC->>Gateway: Pass program. - Gateway->>Router: Add bridging info and transfer funds. - Router->>Interpreter: Instantiate VM and transfer funds. - loop Instructions - Interpreter-->Interpreter: Interact with contracts. - end - Interpreter-->>Gateway: Send program. - Gateway->>IBC: Route through IBC. -``` - -Interpreter may be also be singleton instance of contract per chain. - -Cross chain(XC) account contract is instantiated for each user which hold funds and proxies calls in this case. - -```mermaid -sequenceDiagram - Router->>Interpreter: Instantiate VM - Router->>XcAccount: Transfer funds - loop Instructions - Interpreter-->XcAccount: Interact with contracts. - end - Interpreter-->>Gateway: Send program. - Gateway->>IBC: Route through IBC. -``` - - -## 2.1. Versioning - -`XCVM` protocol versions and implementations use [semantic versioning](https://semver.org/spec/v2.0.0.html) to identify capabilities and backward compatibility. - -## 2.2. Instruction Set - -Messages executed by the `XCVM` follow the `Program` format. - -```typescript -interface Program { - tag : Tag - instructions: Instruction[] -} -type Tag = Uint8Array - -type Instruction = Transfer | Call | Spawn | Query | Exchange -``` - -Each instruction is executed by the on-chain interpreter in sequence. The execution semantics are defined in section 2.4.5. - -The following sequence shows possible high-level implementations for each instruction. - -```mermaid -sequenceDiagram - Interpreter->>ERC20 or CW20 or Native: Transfer - Interpreter->>XcAccount: Proxy Call - XcAccount->>Opaque Contract: Raw Call - Interpreter->>Gateway: Spawn - Interpreter->>Gateway: Query -``` - -### 2.2.1. Transfer - -Transfers funds within a chain between accounts. - -``` - ::= | - - ::= bytes - ::= { : } - ::= | - ::= u128 - ::= bytes - ::= | | - ::= u128 - ::= u128 Ratio - ::= u128 u128 -``` - -### 2.2.2. Call - -Executes a payload within the execution context of the chain, such as an extrinsic or smart contract invocation. Call is guaranteed to execute on the specified `Network` of the `Spawn` context. - -``` - ::= - ::= bytes - ::= [ u16 ] - ::= - ::= | | | | -``` - -### 2.2.2.1. Late Bindings - -The call instruction supports bindings values on the executing side of the program by specifying the `Bindings`. This allows us to construct a program that uses data only available on the executing side. For example, the swap call of the following smart contract snippet expects a `to` address to receive the funds after a trade. - -```rust -fn swap(amount: u256, pair: (u128, u128), to: AccountId) { ... } -``` - -If the caller wants to swap funds from the interpreter account and receive the funds into the interpreter account, we need to specify the BindingValue `Self`, using the index of the `to` field for the serialized data being passed to the smart contract. - -On the executing instance, `BindingValue::Self` will be interpolated at byte index 13 of the payload before being executed, the final payload then becomes `swap(10,(1,2), BindingValue::Self)`, where `BindingValue::Self` is the canonical address of the interpreter on the destination side. - -Besides accessing the `Self` register, `BindingValue` allows for lazy lookups of `AssetId` conversions, by using `BindingValue::AssetId(GlobalId)`, or lazily converting `Ratio` to absolute `Balance` type. - -Indices in bindings must to be **sorted** in an ascending order and **unique**. - -Bindings do not support non-byte aligned encodings. - -### 2.2.3. Spawn - -Sends a `Program` to another chain to be executed asynchronously. It is only guaranteed to execute on the specified `Network` if its `Program` contains an instruction that is guaranteed to execute on the `Network` of the `Spawn` context. - -``` - ::= u128 - ::= bytes - ::= bytes - - ::= -``` - -Where the **salt** is used by the Router while instantiating the interpreter (see section 2.5.2.). - -`OriginNonce` is unique number generated once per program execution on originating consensus. Allows unique identify program invocation from origin to all child spawns. Combined with `Network` and `Program` can be considered `cross chain transaction identifier`. - -In case of escrow(reserver) transfer, `AssetId` in `Assets` are converted from as on sender to as on receiver network. - -### 2.2.3.1. IBC - -Spawned program using IBC based bridges need to be wrapped into packet data before being sent to IBC bridges. Protobuf encoding and decoding is implemented in this case for both sending and receiving packages. -The packet data is defined as follows: - -``` - ::= Account Network - ::= Account - - ::= -``` - -Where the **interpreter** is used in when the IBC packet execution fail or timeout to return the locked funds. - -`Assets` are fungible `ICS-20` assets. - -### 2.2.3.1.1. Spawn send - -The bridge MUST escrow the **assets** transferred. - -Upon successful acknowledgement (see section 2.2.3.1.2.), the bridge MUST burn -the previously escrowed **assets**. - -Upon failure acknowledgement (see section 2.2.3.1.2.) or timeout, the bridge -MUST unescrow and return the **assets** to the **interpreter** (using the -`InterpreterOrigin`). - -### 2.2.3.1.2. Spawn receive - -Upon reception of a `SpawnPackage`, the XCVM execution MUST happen on a -sub-transaction (the transaction MUST not fail even if the execution fails) and -an XCVM-specific acknowledgement must be committed for the packet: -- A single byte, `0x00` if unsuccessful -- A single byte, `0x01` if successful - -The bridge MUST deposit the **assets** in the Router before executing the -XCVM program. - -Note: Assuming we transfer the assets `[asset1 amount1, ..., assetN amountN]`, -the bridge MUST ensure that the sequence `[mint1, ... mintN, executeProgram]` is -atomically executed within a sub-transaction. If any error occur, the according -acknowledgement byte MUST be committed and the sub-transaction MUST be reverted. - -### 2.2.4. Query - -Queries register values of an `XCVM` instance across chains. It sets the current `Result Register` to `QueryResult`. See section 3. on the semantics of registers and `RegisterValues`. - -``` - ::= - ::= {} -``` - -### Exchange - -If underlying state machine and configuration of state machine support `Exchange` it can be executed. - -```typescript -interface Exchange { - in: AssetAmount[] - min_out: AssetAmount[] -} -``` - -`ResultRegister` is set after execution. - -## 2.3. Balances - -Amounts of assets can be specified using the `Balance` type. This allows foreign programs to specify sending a part of the total amount of funds using `Ratio`, or express the amounts in the canonical unit of the asset: `Unit`, or if the caller knows amount of the assets on the destination side: `Absolute`. - -## 2.4. Abstract Virtual Machine - -Each `XCVM` instance is a bytecode interpreter with a limited set of specialized registers. - -### 2.4.1 Registers - -Each interpreter keeps track of persistent states during and across executions, which are stored in different registers. Register values are always updated during execution and can be observed by other contracts. - -``` - ::= {} - ::= | | | | -``` - -#### 2.4.1.1 Result Register - -The result register contains the result of the last executed instruction. - -``` - ::= - - | - - - | - | - | - - ::= - | bytes - ::= '0' - - ::= bytes - ::= bytes - ::= bytes - ::= bytes -``` - -If `ResultRegister` was set to `Error` and there is `Restoration` register contains XCVM program it will be executed. - -#### 2.4.1.2 IP Register - -The instruction pointer register contains the instruction pointer of the last executed program and is updated during program execution. Querying for the `IP` and `Result` can be used to compute the state of the interpreter on another chain. - -``` - ::= u32 -``` - -#### 2.4.1.3 Tip Register - -The Tip register contains the `Account` of the account triggering the initial execution. This can be the IBC relayer or any other entity. By definition, the tip is the account paying the fees for interpreter execution. - -``` - ::= -``` - -#### 2.4.1.4 Self Register - -The self register contains the `Account` of the interpreter. Most implementations will not need to use storage but have access to special keywords, such as `this` in Solidity. - -``` - ::= -``` - -#### 2.4.1.5 Version Register - -The version register contains the semantic version of the contract code, which can be used to verify the subset of XCVM functionality supported by the contract. Implementations that support upgradable contracts MUST update the version register. Functionality advertised through the version register MUST be supported by the contract. - -### 2.4.5 Program Execution Semantics - -Execution of a program is a two-stage process. First, the virtual machine MUST verify that the caller is allowed to execute programs for that specific instance, by verifying that the caller is one of the owners. See section 2.6. for ownership semantics. Second, the TipRegister must be set. Third, the instructions are iterated over and executed. Implementors MUST execute each instruction in the provided order and MUST update the IP register after each instruction is executed. After each instruction is executed, the result register MUST be set to the return value of the instruction. The interpreter SHOULD NOT mangle the return values but store them as returned. Because the return values are chain specific, the actual structure is left *undefined*. - -If an error is encountered by executing an instruction, the defined transactional behavior for that instruction should be abided by. All instructions defined in this document require the transaction to be aborted on failure, however, subsequent addendums may define new instructions with different behavior. - -After the final instruction has been executed and registers are set, the execution stops and the transaction ends. - -See Appendix A for the algorithm. - -## 2.5. XCVM Execution Semantics - -Each chain within the `XCVM` contains a singleton entity consisting of the Router, and the Gateway. Implementors MAY choose to create a monolithic smart contract or a set of modular contracts. - -### 2.5.1. Gateway - -Each chain contains a singleton bridge aggregator, the `Gateway`, which abstracts over transports. - - -Outgoing messages are routed based on bridge identifier, or by specifying the bridge contract directly. - -Each XCVM execution has access to its message `MessageOrigin` and can be configured to deny execution depending on the address or security level: - -``` - ::= - - | - | - - ::= - ::= bytes -``` - -The `Gateway` allows for third parties to add their bridges as well, using our open transport protocol (`OTP`), although this is a feature that we will only later make public. `OTP` provides the following functionality - -- Registration of bridges. -- Deregistration. -- Pausing. - -`OTP` will later be extended to handle more granular black/whitelisting of beneficiaries, assets, and message filters. - -### 2.5.2. Router - -Each program arriving through the `Gateway` is passed to the `Router`, which becomes the initial beneficiary of the provided `Assets` before finding or instantiating an `Interpreter` instance. The router then transfers funds to the `Interpreter` instance. - -Subsequent calls by the same `Origin` will not result in an instantiation, but instead in re-use of the `Interpreter` instance. This allows foreign `Origins` to maintain state across different protocols, such as managing LP positions. - -If no interpreter instance has been created for a given caller, the call to the `Router` must either come from the `IBC`, `XCM`, `OTP`, or a local origin. After the instance has been created, it can be configured to accept other origins by the caller. - -**Example** - -For a given XCVM program, its interpreter instance is derived from `Network Account Salt`. This allows users to create different interpreter instances to execute programs against. Note that the `Salt` is not additive and only the composite `Network Account` is forwarded to remote chains as the user origin: -``` -Spawn A 0x01 [ // Parent program spawned on A, with 0x01 as salt, the origin for the instructions is (A, AccountOnA, 0x1) - Call 0x1337, // Call instruction executed on A - Spawn B 0x02 [] {}, // Sub-program spawned on B, with 0x02 as salt, the origin for the instructions is (A, AccountOnA, 0x2) -] {} -``` -Possible usage is to allow one program execution to act on state of other program execution to restore funds. - - -In the above XCVM program, the parent program salt `0x01` is not a prefix of the sub-program salt `0x02`. The user is able to make it's interpreter origin using a fine grained mode. The following program is an example on how we can spread a salt: -``` -Spawn A 0x01 [ // Parent program spawned on A, with 0x01 as salt, the origin for the instructions is (A, AccountOnA, 0x01) - Call 0x1337, // Call instruction executed on A - Spawn B 0x0102 [] {}, // Sub-program spawned on B, with 0x0102 as salt, the origin for the instructions is (A, AccountOnA, 0x0102) -] {} -``` - -In next program, all spawned instances on all chains share state (including assets): -``` -Spawn A 0x01 [ - Call 0x1337, - Spawn B 0x01 [] {}, // Sub-program spawned on B, with 0x01 as salt, the origin for the instructions is (A, AccountOnA, 0x01) allows to share -] {} -``` - -### 2.6. Ownership - -interpreter instances maintain a set of owners. - -``` - ::= {} - ::= -``` - -Programs are only executed by the interpreter if the caller is in the set of owners. - -On initial instantiation of the `XCVM` interpreter, the calling `Identity` is the owner. This can be a local or foreign account, depending on the origin. The owning `Identity` has total control of the interpreter instance and the funds held and can make delegate calls from the instance's account. - -Oftentimes, multiple `Identities` represent a single real-world entity, such as a cross-chain protocol or a user. To accommodate for shared/global ownership of resources, each interpreter keeps track of a set of `Identities`, which share ownership of the interpreter. Each owning `Identity` has full permissions on the interpreter instance. - -Owners may be added by having the interpreter call the appropriate setters. We will consider adding specialized instructions later. Owners may be removed by other owners. An XCVM instance MUST always have at least one owner. - -# 3. Encoding - -Different chains may choose to accept different encodings as the main entry point for contract calls. Such encodings can include but are not limited to `scale`, `ethabi`, `bors`, `borsh`. Chain-to-chain calls are always in a single encoding: `protobuf`, which is used within the transport. - -`protobuf` is generally [not deterministic](https://protobuf.dev/programming-guides/encoding/). XCVM restricts encoders and decoders to a [deterministic subset of protobuf](https://docs.cosmos.network/main/architecture/adr-027-deterministic-protobuf-serialization). - -## 3.1. JSON Encoding - -The current prototyping of `XCVM` uses JSON encoding, although users SHOULD not rely on this feature. - -# 4. Fees - -There are three different components to the fees charged for interacting with the `XCVM`: - -1. Gas fees on the origin chain, are used to pay for local submission and partial execution. -2. Bridging fees (optional): Some bridges charge a dynamic fee based on the number of assets sent. If possible, fees are folded into 1., otherwise charged during transmission. -3. Execution fees (optional): A reward added by the instruction author to reward the relayer for paying for the execution on the destination chain. - -## 4.1. Execution Fees - -Gas and Bridging fees are handled during the invocation and at the `Router` level, however, Execution fees are opt-in and paid by the user by using the `Tip` registry value. The following example program performs an operation, and rewards the tip address: - -``` - 0x13371337... - { USDC: 15000000000000 } -``` - -This model is very much like Bitcoin's UTXOs, where the difference between inputs and outputs defines the tip. Here we are more explicit with the actual fee, which allows for more fine-grained control. Together with branching (to be implemented later), this fee model can be used to incentivize the relayer to precompute the outcome, and only submit the program if it were to succeed at the current state of the destination chain. - -# 5. Asset Registries - -Assets can be identified using a global asset identifier. - -``` - ::= u128 -``` - -Each chain contains data which maps assets to their local representations, such as erc20 addresses. The `Transfer` instruction uses this registry to look up the correct identifiers. Interpreter instances can be reconfigured by the owner to use alternative registries. - -Propagating updates across registries is handled by the `XCVM` too. We will go more in-depth on how we bootstrap this system in a later specification. - -# 6. Further Work - -## 6.1. NFTs - -The design specification currently does not take NFTs into account. We have chosen to not (yet) specify NFTs as part of `Assets` due to the complexity of owning and value accruing NFTs. We do however intend to update the specification once the approach has been finalized. - -## 6.2. Name Service - -The `CNS` provides an abstraction on top of the `Identity` system, allowing developers and users to use a single name across interpreter instances. Each `XCVM` chain contains a `CNS` registry, which maps `Identity` to `Name`. On bridge relays, the calling program can specify to use an associated `Name` instead of its `Identity`. The `XCVM` interpreter has to be configured to accept the `CNS` as an owner. - -``` - ::= bytes -``` - -We will later elaborate on using alternative name registries such as [`ENS`](https://ens.domains/). - -# 7. Security Considerations - -Ensuring that the caller is an owner is an incredibly important check, as the owner can delegate calls through the interpreter, directly owning all state, funds, and possible (financial) positions associated with the interpreter account. Since each interpreter has their own `Identity`, they might own other accounts as well. Thus the owners control more accounts than just the contract storing the owners. - -The `Call` instruction has the same security risks as calling any arbitrary smart contract, such as setting unlimited allowances. - -Adding an owner to the set of owners grants them the ability to evict other owners. - -Failure to execute an instruction will lead to a transaction being reverted, however, the funds will still be in the interpreter account's control. Ensure that changing ownership is always done atomically (add and remove in the same transaction) to ensure funds are not lost forever. - -Using bridges is equivalent to adding them as owners on your interpreter instance. - -## Security layers - -In general different security can be applied to different programs. - -### Anonymous programs - -These programs operating only on funds inside program and with limited set of instructions can be executed without sender authentication. - -Specific case is program consist of `Transfer`, `Spawn`, `Exchange` only on assets transferred. - - -### Cross protocol verification - -**Example** - -When program needs to transfer assets in IBC use ICS20 protocol. -In order to execute remote transaction on behalf of account, it can use ICS27. -In both packets same program can be sent as part of batch and verified on other end to be exact same when assembled for execution. -For this if one protocol compromised we still validate via second one. - - -### Trusted topology - -Program can be executed iff these where send only from some subset of of trusted channels. - -### Cross chain multisignatures - -In this case program can be executed if it was send by several chains. - -### Signatures - -For operations of high importance EDSCA signature of program can be propagated from sending chain and verified on target chain. - -# 8. Limited instruction support - -## No support for arbitrary contracts - -Some chains do not support arbitrary contracts, but support limited subset of instructions. -In this case only programs which use limited subset of instruction will be executed on target chain via virtual spawns. - -**Example** - -Cosmos Hub has complies with IBC ICS Atomic swap spec, but does not host contract runtime. - -In this case, programs trying to reach Cosmos Hub from other chains, will not spawn full programs on it. - -But will send only swaps and handle invocation return on sender chain. - -## No support for contract postconditions - -Some chains cannot abort transaction based on arbitrary check after ABI invocation. -In this case for specific subset of instructions to specific whitelisted contracts list will be allowed. - -**Example** - -On Near cannot abort Swap transaction if amount less than expected limit. -In this case only trusted Swap contracts will be callable. - - -# 9. Appendix - -## A. -```rust -fn execute(&mut self, sender: Account, tip: Account, caller: Identity, instructions: Vec) { - assert_eq!(sender, ROUTER::ACCOUNT); - assert!(self.owners.contains(&caller)) - - // reset the IP from the last execution - self.IP = 0; - self.TIP = tip; - - while let Some(instr) = take_next(&mut instructions).unwrap() { - self.IP += 1; - self.result = self.execute(instr).unwrap(); - } -} -``` - -## B. - -### Examples - -#### Cross-chain borrowing - -A concrete example of using the XCVM protocol is to transfer funds to a different chain, use them as collateral in a loan, transmit funds back to the source chain, and use them there. For this example, we'll omit querying for current account `health` and repayments. - -Concretely, we want to execute the following operations: - -- Transfer funds to chain XYZ. -- Call a smart contract to take out a loan. -- Reward the relayer, to incentivize execution. -- Send funds back. - -Since we might not know the current interest rates, we'll use relative values for fund transfers, instead of absolute ones. - -For this example, we have the source initiator be a regular user, however, a smart contract is capable of executing the same operations. - -```mermaid -sequenceDiagram - User->>Interpreter ABC: Submit Program - Interpreter ABC->>Router ABC: Spawn Program - Router ABC->>Gateway ABC: Submit Program - Gateway ABC->>Gateway XYZ: Relay Program - Gateway XYZ->>Router XYZ: Instantiate VM - Router XYZ->>Interpreter XYZ: Execute Spawn - Interpreter XYZ->>Lender: Call 0x1337 (Borrow USDC for DOT) - Lender->>Interpreter XYZ: Transfer USDC - Interpreter XYZ->>Tip: Transfer USDC fee to Relayer - Interpreter XYZ->>Router XYZ: Spawn Program - Router XYZ->>Gateway XYZ: Submit Program - Gateway XYZ->>Gateway ABC: Relay Program - Gateway ABC->>Router ABC: Instantiate VM - Router ABC->>Interpreter ABC: Execute Spawn - Interpreter ABC->>Tip: Transfer USDC fee to Relayer - Interpreter ABC->>User: Transfer USDC -``` - -Although these operations are quite complicated to code by hand, using the XCVM protocol, we can very succinctly express them: - -``` -Spawn XYZ 0 [ - Call 0x1337, // chain-specific encoding to make a smart contract call. - Transfer Tip USDC Unit 50, // 50 bucks for the fee. The relayer earns this if the inner spawn is dispatched. - Spawn HOME 0 [ - Transfer Tip USDC Unit 50 // Another 50 bucks fee for the operation, but now reverse direction. - Transfer USER { USDC: Ratio::ALL } // On ABC, we transfer all USDC to the user. - ] { USDC: ALL }, // We send over all our USDC back to ABC. -] { DOT: UNIT 100 }, // We send over 100 DOT from ABC to XYZ. -``` - -# 10. Contributors - -- Abdullah Eryuzlu -- Cor Pruijs -- Sofia de Proença -- Jiang Qijong -- Joon Whang -- 0xbrainjar -- 0xslenderman diff --git a/code/xcvm/otp.md b/code/xcvm/otp.md deleted file mode 100644 index 322ab3ce635..00000000000 --- a/code/xcvm/otp.md +++ /dev/null @@ -1,204 +0,0 @@ -# Open Transport Protocol (OTP) - -This document describes the on-chain components related to registration and dispatching XCVM programs over different transports. - -Although [IBC](./ibc.md) is the default and preferred transport method within the `XCVM`, we also support arbitrary third party protocols. The abstract interface for registration and participation in `XCVM` transactions is what we call `OTP`. - -For a transport to be OTP compatible, it has to support the following operations: - -1. Fungible token transfers. -2. Opaque data transfers. - -Ideally, a protocol supports both in a single operation, although most bridges will need to be wrapped in an additional set of contracts to be fully compatible. - -`OTP` handles the following operations: - -1. Maintaining a blacklist of transports. -2. Ingress of messages on the chain. -3. Registration of routing. -4. Egress of messages on the chain. - -## XCVM Ingress - -A transport does not need to register itself to pass messages into the `XCVM`, it can do so directly, assuming that the interpreter instance accepting the transport's messages has whitelisted this transport. - -The following diagram describes the flow of data (and funds) when OTP is used to for ingress of programs. - -```mermaid -sequenceDiagram - Third-party transport->>Third-party OTP-adapter: Transform message. - Third-party OTP-adapter->>Gateway: Transfer assets and pass program. - Gateway->>Router: Add bridging info and transfer funds. - Note over Gateway: Accept/deny program based on blacklist. - Router->>XCVM Interpreter: Instantiate vm and transfer funds. - Note over XCVM Interpreter: Accept/deny program based on gateway annotation. -``` - -Although the diagram simplifies the work that the OTP-adapter might need to perform, it can be relatively complicated depending on how the transport operates. We go into more concrete implementations [later](#possible-implementations) in this document. - -## Registration of Routes - -For a transport to be possible be selected by the Gateway to transfer messages to different chains, a more involved registration process is required. - -- A stake needs to be put down, which is used to reward disputers in case of bridge fraud. -- Metadata on the bridge must be provided, including - 1. The `Account` of the administrator, used to deregister the bridge, and add routes. - 2. Destinations reachable through this bridge. - -``` -RegistrationInfo ::= Account [Destination] -Destination ::= NetworkId [AssetId] -``` - -Immediately after registration, the bridge registration can be disputed for approximately 72 hours. The stake can be lost during this time, if governance determines that the registration is fraudulent. If a dispute is triggered, the registration can be delayed by up to 2 weeks. - -#### Disputed Registration - -The following diagram displays the sequence of a registration, including the dispute by a validator. - -```mermaid -sequenceDiagram - Third-party Transport->>Gateway: Register bridge for egress. - Note over Gateway: Dispute window is opened. - Validator->>Gateway: Dispute the registration. - Note over Validator, Gateway: Validator puts down a stake as well. - Governance->>Gateway: Settle dispute. -``` - -Validators can be any entity, including a user triggering the dispute through our UI, as well as nodes automatically tracking registrations. For bridging teams, it is especially important to dispute registrations of your bridge with an incorrect administrator account. - -## Egress of messages - -Once a transport has been successfully registered, it becomes accessible to the `Gateway`, which might route traffic based on transport requirements from the interpreter instance dispatching the program. By default, all OTP transports are considered `Trusted`, meaning that no traffic is routed through them unless specifically opted-in by the interpreter instance. - -Later we may add means to upgrade transports to the `Trustless` status using governance. This will accommodate transports such as `XCMP`. - -```mermaid -sequenceDiagram - XCVM Interpreter->>Gateway: Spawn message with next destination - Note over XCVM Interpreter,Gateway: Destination is annotated with transport requirements. - Gateway->>Third-party Transport: Relay Spawn -``` - -### Fees - -`XCVM` is not opinionated about handling fees, leaving that up to the users by adding an output to reward the relayer. Read more on how we defined fees [here](../../SPEC.md#fees). - -A note on this, fees are specified by the program, meaning that the bridge itself cannot charge a fee directly on the `Assets` being transferred. The third-party OTP-adapter will need to take this into account, by possibly using internal APIs of the bridging contract to ensure that no fees are charged based on the `Assets` transferred. - -## Reimbursements - -When a transports fails to transmit a message (such as an IBC timeout or network congestion) the `Third-party Transport` issues a reimbursement to the `Gateway` which then informs the interpreter instance of the failure. - -For `OTP`-registered transports, the reimbursement itself can be disputed as well. After issuing the reimbursement to the Gateway, a short-lived dispute window (hours) allows validators to dispute the reimbursement. This avoids the attack vector where a bridge has identified a contract which will retry a cross-chain operation until success, and extract value from that by issuing malicious reimbursements (a cross-chain reentrancy attack). - -```mermaid -sequenceDiagram - Third-party Transport->>Gateway: Issue reimbursement. - Validator->>Gateway: Dispute the reimbursement. - Note over Validator, Gateway: Validator puts down a stake as well. - Governance-->>Gateway: Settle dispute. - Gateway->>XCVM Interpreter: Issue reimbursement. - Note over Gateway, XCVM Interpreter: Only reimbursed if governance determined that the transport was honest. -``` - -## Example Implementations - -Here we expand on two architectures, `multisig` and `updater` already in existence, and how to adapt them to become OTP compatible. Multisig or TSS-based bridges are custodial solutions, where multiple parties take custody of the funds and act on behalf of the user/contract. In `updater` based solutions, a message is stored inside a Merkle tree, and a single entity broadcasts this hash to other chains. Users/relayers are then required to submit the actual message to the other chain, plus a proof-of-inclusion for message authenticity. - -### Multisignature (or TSS based) Bridge - -The theoretical multisig based bridge already exposes the following protocol: - -- It has a smart contract, which accepts a `NetworkId`, `Account`, `Assets` for token transfers, or instead of the assets, a `data` payload. (Ideally it would accept both, and some bridges do). -- It can call a contract with a `data` payload. The contract is expected to verify that the `caller` is the multisig bridge contract for message authenticity. - -#### Sequence diagram of incoming assets and data - -```mermaid -sequenceDiagram - Multisig Relayer->>Bridge Contract: Submit message. - Bridge Contract->>Contract: Forward message. - Multisig Relayer->>Token Contract: Submit mint request. - Token Contract->>User: Transfer tokens. -``` - - -#### Sequence diagram of outgoing assets and data - -```mermaid -sequenceDiagram - participant User - participant Contract - User->>Bridge Contract: Transfer tokens. - Contract->>Bridge Contract: Call message pass. - Bridge Contract->>Multisig Relayer: Enact message pass. - Bridge Contract->>Multisig Relayer: Enact token transfer. -``` - -A new contract needs to be introduced to handle the requirement to compound the asset and data transfer, as well as reimbursements. We'll also make sure to have our adapter's contract address in the `Relayer` registry so that the fees can be fairly distributed to the multisig validators. - -#### Sequence diagram of incoming Spawn. - -```mermaid -sequenceDiagram - Multisig Relayer->>Token Contract: Submit mint request. - Token Contract->>Adapter: Transfer tokens. - Multisig Relayer->>Adapter: Submit mint request. - Multisig Relayer->>Adapter: Forward message. - Note over Adapter: Waits for both message and assets to arrive. - Adapter->>Gateway: Initiate Spawn. - Note over Adapter,Gateway: Sets the Relayer registry to self. - Adapter->>Multisig Relayer: Transfer earned fees. -``` - -For outgoing messages, the pattern is very similar: - -```mermaid -sequenceDiagram - Gateway->>Adapter: Submit Spawn. - Note over Gateway,Adapter: Selects based on destinations. - Adapter->>Bridge Contract: Call transfer. - Bridge Contract->>Multisig Relayer: Enact message pass. - Adapter->>Bridge Contract: Call message pass. - Bridge Contract->>Multisig Relayer: Enact message pass. -``` - -Reimbursements can be constructed similarly to an incoming spawn. - -### Updater Architecture using Merkle Roots - -Updater style bridges do not actually pay for XCVM execution on the destination chain, but instead synchronize a proof across chains, this decouples synchronization and execution, but means that we will need to add payment for synchronization as part of the adapter, as the Relayer receives payment after synchronization and execution has taken place. Luckily `updater` based protocols are quite cheap. - -#### Sequence diagram of incoming Spawn. - -```mermaid -sequenceDiagram - participant Executor - participant Updater - participant Bridge Contract - participant Adapter - participant Gateway - Updater->>Bridge Contract: Set root hash. - Executor->>Adapter: Provide program. - Adapter->>Bridge Contract: Authenticate program. - Adapter->>Gateway: Initiate Spawn. -``` - -For outgoing messages, our adapter will need to take into account the synchronization fee charged by the updater: - -```mermaid -sequenceDiagram - Gateway->>Adapter: Submit Spawn. - Note over Adapter: Parses the Spawn to ensure enough fees are earned by the executor. - Adapter->>Bridge Contract: Submit data and assets. - Note over Adapter,Bridge Contract: Pays the synchronization fee in advance. - Bridge Contract->>Updater: Read root hash. - Updater->>Chain 2: Set root hash. - Executor->>Chain 2: Trigger program execution. -``` - -In the example of the updater-based protocol, we are assuming that the `Adapter` does not have any special privileges. The fee handling could be immensely simplified if the `Bridge Contract` would allow fees to be charged on the destination side, as that would remove the need for the `Adapter` to parse the `Spawn`. An added benefit is that the executor can be any party, not just the one controlling the Adapter contract. - -> **Note** -> Fees should always be paid on the destination side. This avoids opening a Pandora's box of headaches related to reimbursements and gas price fluctuations. \ No newline at end of file diff --git a/docs/docs/intro.md b/docs/docs/intro.md index fd4c4a562ac..4e44de4422b 100644 --- a/docs/docs/intro.md +++ b/docs/docs/intro.md @@ -101,32 +101,16 @@ The documentation for Composable is presently undergoing development, consequent ## The Vision In an ideal cross-chain world, developers and users interact unhindered across ecosystems and protocols, regardless of -where their assets reside. For this reason, our team at [Composable Finance](https://www.composable.finance/) +where their assets reside. For this reason, [Composable Finance](https://www.composable.finance/) is on a mission to pioneer innovative Web3 user experiences in a trustless, non-custodial, and decentralized manner. Our efforts will not only enable new and valuable opportunities, but will also facilitate easy onboarding of traditional finance stakeholders into DeFi. ## The Problem -While centralized solutions continue to pose setbacks in the space, decentralized finance (DeFi) continues to gain -traction. +Amidst the growth of decentralized finance (DeFi), the industry faces challenges stemming from centralization, while gaining momentum. However, this expansion has led to increased fragmentation, with projects emerging on Layer 2 (L2) or Layer 1 (L1) networks instead of or in addition to the original Ethereum mainnet. -As DeFi continues to expand and scale, **fragmentation of the industry and its market is worsening**. -Projects continue to launch on layer 2 (L2) or layer 1 (L1) networks instead of or in addition to the original Ethereum mainnet. -DeFi has thus expanded and is therefore characterized by several ecosystems beyond Ethereum, each with its own unique benefits, that often exist in silos. - -A lack of secure interoperability solutions exists between these ecosystems creating barriers to value transfer across layers and chains. -While it has become easier to move assets between ecosystems, it has wrongfully been accomplished via -**centralized, custodial, and trusted methods of asset transfer, which are vulnerable to hacks.** -Additionally, managing cross-chain assets is still a challenge as several applications are segregated inside the various ecosystems. -This infrastructure should be improved so that all DeFi participants can build and use applications that are cost-effective and performant. - -Resultantly, in the race for market share and users, two key functionalities are becoming the most important components -for remaining competitive in the quickly evolving landscape: Capital efficiency and trustless interoperability. -Both developers and users will seek methods to interface with different ecosystems in a scalable, provable, secure, and decentralized manner. - -The solution to the current fragmentation in DeFi is not more of the same bridges being built between one chain to another. -Instead, it is the unification of all ecosystems via a natively cross-chain infrastructure. +Despite the construction of blockchain bridges enabling asset movement, secure interoperability remains lacking, causing barriers to value transfer between ecosystems in a decentralized manner. Current solutions are centralized and susceptible to vulnerabilities that have led to over $2 billion dollars in exploits. Moreover, managing cross-chain assets proves challenging due to ecosystem segregation and a lack of cross-chain user friendly experiences. ## Limitations in Current Approaches Current approaches to solving these problems are limited by at least one of the below: @@ -139,48 +123,19 @@ Current approaches to solving these problems are limited by at least one of the ## The Composable Solution -Composable's full technical stack -has been designed to usher in an era of cross-ecosystem interoperability -without abandoning the trustless, decentralized, permissionless, and non-custodial aspects of web3. - -Composable is building infrastructure that allows developers to deploy applications natively capable of -cross-chain functions. This infrastructure also allows users to access previously disparate ecosystems and simultaneously interoperating across layers and chains, all through the same fabric and entry point: [Composable Virtual Machine](./products/xcvm.md). - -The result is that DeFi users will be able to have their actions reduced to parameters that determine a cascade of -automated cross-chain transactions to achieve their intentions instead of requiring users to navigate each step in -the process themselves: +Composable's technical stack establishes seamless and secure cross-ecosystem interoperability while upholding web3's core principles. Users' intentions trigger automated cross-chain transactions, streamlining processes. The solution to the current fragmentation in DeFi is not more of the same bridges being built between one chain to another. Instead, it is the unification of all ecosystems powered by a generalized framework for cross-chain infrastructure - the [Inter-blockchain Communication Protocol](https://ibcprotocol.org/). -![routing](./xcvm-routing.png) - -Our interoperable infrastructure forms the foundation for DeFi's mass adoption. -This environment will enable a new host of services to be offered to users that abstract complexity away to focus on needs: for example, -users will be able to get the best interest rates across lending pools, the best swaps across chains, and allow for -a range of other possibilities across new pool types, arbitrage opportunities, and onboarding portals to DeFi. - -We are accomplishing these goals through a multifaceted technical stack -where we begin by bridging gaps between today’s isolated blockchains in order to create a -single and unified access point that is the -[Composable VM](./products/xcvm.md) -— that serves to orchestrate and compute smart contract functions across the array of EVM, Polkadot and IBC-enabled Cosmos ecosystems autonomously, -with the purpose of optimizing for best execution and mitigating all user experience constraints for developers and end-users. +Composable's interoperable infrastructure forms the foundation for DeFi's mass adoption, offering user-centric services like optimal lending rates and efficient swaps. The [Composable VM](./products/xcvm.md) unifies monolothic chains, optimizing smart contract execution for developers and users. ## Get Involved -We’ve been working on enhancing our ecosystem and vision while ensuring that we are leading the way in terms of -innovation and accessibility for cross-chain DeFi. Through our collective vision and our suite of bespoke offerings, -we aim to embed collaboration in a space where competition has predominated. Returning back to the core values of -decentralism, we are passionate about collaborating with other projects and supporters who share our vision. -The future we are building needs everyone to play a part, and we encourage you to reach out to our team for informal or -formal enquiries to see how we can work together to build tomorrow, today. - - +We're focused on pioneering innovation and accessibility for cross-chain DeFi, emphasizing collaboration over competition through our collective vision and bespoke offerings. Embracing decentralization, we seek partnerships with like-minded projects and supporters, inviting everyone to contribute to building the future. Feel free to connect with our team for inquiries on working together. **Join the Composable community:** [Composable Twitter](https://twitter.com/ComposableFin) | [Picasso Twitter](https://twitter.com/Picasso_Network) | -[Telegram](https://t.me/composablefinance) | [Discord](https://discord.com/invite/composable) | +[Telegram](https://t.me/composable_chat) | [Discord](https://discord.com/invite/composable) | [Website](https://www.composable.finance/) | [GitHub](https://github.com/ComposableFi) | [LinkedIn](https://www.linkedin.com/company/composable-finance/) -[Composable Medium](https://composablefi.medium.com/about) | [Picasso Medium](https://medium.com/@picasso_network) - +[Composable Medium](https://composablefi.medium.com/about) | [Picasso Medium](https://medium.com/@picasso_network) \ No newline at end of file diff --git a/docs/docs/networks/picasso-parachain-overview.md b/docs/docs/networks/picasso-parachain-overview.md index 15a2df6d9c1..41bda7005a8 100644 --- a/docs/docs/networks/picasso-parachain-overview.md +++ b/docs/docs/networks/picasso-parachain-overview.md @@ -11,7 +11,7 @@ and its proprietary technology stack. [$PICA]: ./picasso/tokenomics.md ![picasso_diagram](./picasso/picasso-diagram.png) -Picasso houses a suite of modular and interoperable Substrate pallets: +**Picasso houses a suite of modular and interoperable Substrate pallets:** - [Pablo] - DEX: serving as a cross-chain liquidity hub on Picasso - [Centauri] - trustless bridging between major DeFi ecosystems @@ -31,43 +31,24 @@ The actual passing of messages between parachains is done through the use of Cro ### CosmWasm & IBC -Picasso exists as the only CosmWasm and IBC-enabled parachain. +Picasso exists as the only [CosmWasm](../products/cosmwasm-vm-overview.md) and IBC-enabled parachain. Thus, Picasso will be able to seamlessly integrate with other parachains as well as IBC-enabled blockchains in the Cosmos ecosystem. As the first instance of an IBC implementation outside of the Cosmos ecosystem, novel strategies can now be built that leverage the best of Substrate and Cosmos SDK blockchains. This is made possible through some key innovations by our bridging team. +As the first instance of CosmWasm outside of Cosmos, existing projects can deploy a satelite protocol on Picasso and gain access to a completely new ecosystem of users and builers. + ### Insights into Picasso's Pallets -The Substrate blockchain development framework allows for parachain teams, -such as ours, to quickly bootstrap a sovereign layer 1 blockchain through the utilization of core building blocks -provided in the form of pallets. -A pallet could be compared to a Lego brick -that can be stacked in various arrangements to create a highly customizable runtime environment. -With Substrate, developers can choose to reuse fundamental and proven pallets where possible -or choose to create their own pallets to add new functionality when necessary. - -Picasso delivers an extensive offering of Substrate pallets -that come together to form DeFi’s most robust interoperable platform. -By reducing transaction costs, constructing modular applications that enable flexible liquidity movement, -and implementing innovative solutions, -Picasso is tackling some of the key difficulties of interoperable DeFi such as liquidity fragmentation, -asset transfer security, and the lack of generalized cross-chain communication standards. -Picasso, which houses DeFi primitives like [Centauri] and the [Pablo DEX], is designed to bring and maintain deep -liquidity, leveraging new technologies and aligning itself closely with user requirements. - -[Pablo Dex]: ../products/pablo-overview.md +The Substrate blockchain development framework enables parachain teams to rapidly establish autonomous layer 1 blockchains using core building blocks referred to as pallets. These pallets, akin to Cosmos SDK modules, can be combined in various ways to create a customized runtime environment. Substrate offers developers the option to either reuse existing pallets or develop new ones to introduce additional functionalities as needed. -### Composable’s VM on Picasso +Picasso offers an extensive range of Substrate pallets that synergize to form a highly robust interoperable DeFi platform. By reducing transaction costs, creating modular applications for adaptable liquidity movement, and implementing pioneering solutions, Picasso effectively addresses key challenges within the realm of interoperable DeFi. These challenges encompass liquidity fragmentation, asset transfer security, and the absence of standardized cross-chain communication protocols. Within the realm of Picasso, DeFi essentials such as [Centauri] and [Pablo] thrive. -Composable’s Virtual Machine [CVM](./products/xcvm.md) -will be able to leverage the pallets above to facilitate the creation of non-custodial, -natively cross-chain smart contracts. -The CVM serves as a top-layer orchestration layer, -capable of calling into existing applications and pallets across multiple ecosystems asynchronously. -CVM applications will be deployable from any ecosystem housing the necessary satellite contracts and interpreter instances. +### Composable’s VM on Picasso +Composable’s Virtual Machine [CVM](../products/xcvm.md) powered by CosmWasm will be able to leverage the pallets above to facilitate the creation of non-custodial, natively cross-chain smart contracts. The CVM serves as a top-layer orchestration layer, capable of calling into existing applications and pallets across multiple ecosystems asynchronously. Applications on any IBC-enabled chain can leverage the CVM to interact via cross-chain contracts in order to simplify cross-chain user experiences. ### Insights into Picasso’s Security diff --git a/docs/docs/networks/picasso/crowdloan.md b/docs/docs/networks/picasso/crowdloan.md index 5b6b1701f10..5a4e8159cf4 100644 --- a/docs/docs/networks/picasso/crowdloan.md +++ b/docs/docs/networks/picasso/crowdloan.md @@ -44,5 +44,5 @@ and restake the same amount or greater. The bonus will be subject to the amount ### KSM purchase logs You can find the purchase/sell logs corresponding to the Ethereum address for stablecoin contributors -[on our Github.](https://github.com/ComposableFi/composable/tree/main/docs/docs/parachains/picasso/crowdloan-contributors/crowdloan-logs.csv) +[on our Github.](https://github.com/ComposableFi/composable/blob/main/docs/docs/networks/picasso/crowdloan-contributors/crowdloan-logs.csv) They catalogue all of the Picasso stable coin conversions to KSM via TPS (the OTC desk of 3AC). diff --git a/docs/docs/networks/picasso/pica-use-cases.md b/docs/docs/networks/picasso/pica-use-cases.md index 3a9146f70fe..f1d264e8544 100644 --- a/docs/docs/networks/picasso/pica-use-cases.md +++ b/docs/docs/networks/picasso/pica-use-cases.md @@ -1,4 +1,4 @@ -# PICA use cases +# PICA Use Cases PICA is the native token of [Picasso](../picasso-parachain-overview.md) and the [Centauri chain](../centauri-chain.md). We have made a concerted effort to ensure that the PICA token holds as much utility as possible by incorporating various value accrual methods, and governance features. While the PICA token provides the community with a strong voice and rewards for participating within the ecosystem, it is also fundamental for the operation of collators, validators, oracles, and our other cross-ecosystem strategies. Thus, the PICA token is fundamental for governance, network usage, and the security of Picasso. diff --git a/docs/docusaurus.config.js b/docs/docusaurus.config.js index 4a57636ad6f..8b2ed4a77c9 100644 --- a/docs/docusaurus.config.js +++ b/docs/docusaurus.config.js @@ -123,7 +123,7 @@ const config = { }, { label: 'Telegram', - href: 'https://t.me/composablefinance', + href: 'https://t.me/https://t.me/composablefinance', }, { label: 'Discord', @@ -150,6 +150,10 @@ const config = { label: 'Picasso Medium', href: 'https://medium.com/@picasso_network', }, + { + label: 'Press Kit', + href: 'https://docs.composable.finance/ecosystem/press-kit', + }, ], }, ], diff --git a/docs/sidebars.js b/docs/sidebars.js index 86f29b60baa..43b5cd2f908 100644 --- a/docs/sidebars.js +++ b/docs/sidebars.js @@ -77,13 +77,12 @@ collapsible: false, collapsed: false, items: [ - "networks/picasso/crowdloan", "networks/picasso/governance", "networks/picasso/asset-list", "networks/picasso/pica-use-cases", "networks/picasso/tokenomics", "networks/picasso/token-transparency", - + "networks/picasso/crowdloan", { type: "category", label: "CosmWasm", From c5635669907213f52f5934d9079928cd543b9c60 Mon Sep 17 00:00:00 2001 From: Jafar <107645336+JafarAz@users.noreply.github.com> Date: Fri, 18 Aug 2023 01:39:07 +0100 Subject: [PATCH 2/2] Update picasso-parachain-overview.md --- docs/docs/networks/picasso-parachain-overview.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/networks/picasso-parachain-overview.md b/docs/docs/networks/picasso-parachain-overview.md index 41bda7005a8..4504366b163 100644 --- a/docs/docs/networks/picasso-parachain-overview.md +++ b/docs/docs/networks/picasso-parachain-overview.md @@ -38,7 +38,7 @@ As the first instance of an IBC implementation outside of the Cosmos ecosystem, novel strategies can now be built that leverage the best of Substrate and Cosmos SDK blockchains. This is made possible through some key innovations by our bridging team. -As the first instance of CosmWasm outside of Cosmos, existing projects can deploy a satelite protocol on Picasso and gain access to a completely new ecosystem of users and builers. +As the first instance of CosmWasm outside of Cosmos, existing projects can deploy a satelite protocol on Picasso and gain access to a completely new ecosystem of users and builders. ### Insights into Picasso's Pallets