diff --git a/public/d2/docs/cross-cats/underwriting-0.svg b/public/d2/docs/cross-cats/underwriting-0.svg new file mode 100644 index 0000000..e638a05 --- /dev/null +++ b/public/d2/docs/cross-cats/underwriting-0.svg @@ -0,0 +1,1102 @@ +IndexUserOrder ServerSolverUnderwriterReactorSPV OracleInputOutputInputOutputInputInput 1.1 Quote1.2 Quote2.1 Send Signed Order2.2 Broadcast Signed Order3.1 Submit Signed Order3.2 Pull Input4.1 Fill Order5.1 Purchase Order5.2 Pull Inputs from underwriter to solver6.1 Submit Proof6.2 Prove Bitcoin Transaction6.3 Pay underwriter + + + + + + + + + + + + + + + + + + + + + + + + + + +SetupUserOrder ServerSolverUnderwriterReactorSPV OracleInputOutputInputOutputInputInput 1.1 Quote1.2 Quote2.1 Send Signed Order2.2 Broadcast Signed Order3.1 Submit Signed Order3.2 Pull Input4.1 Fill Order5.1 Purchase Order5.2 Pull Inputs from underwriter to solver6.1 Submit Proof6.2 Prove Bitcoin Transaction6.3 Pay underwriter + + + + + + + + + + + + + + + + + + + + + + + + + + +InitiationUserOrder ServerSolverUnderwriterReactorSPV OracleInputOutputInputOutputInputInput 1.1 Quote1.2 Quote2.1 Send Signed Order2.2 Broadcast Signed Order3.1 Submit Signed Order3.2 Pull Input4.1 Fill Order5.1 Purchase Order5.2 Pull Inputs from underwriter to solver6.1 Submit Proof6.2 Prove Bitcoin Transaction6.3 Pay underwriter + + + + + + + + + + + + + + + + + + + + + + + + + + +CompletionUserOrder ServerSolverUnderwriterReactorSPV OracleInputOutputInputOutputInputInput 1.1 Quote1.2 Quote2.1 Send Signed Order2.2 Broadcast Signed Order3.1 Submit Signed Order3.2 Pull Input4.1 Fill Order5.1 Purchase Order5.2 Pull Inputs from underwriter to solver6.1 Submit Proof6.2 Prove Bitcoin Transaction6.3 Pay underwriter + + + + + + + + + + + + + + + + + + + + + + + + + + +FinalisationUserOrder ServerSolverUnderwriterReactorSPV OracleInputOutputInputOutputInputInput 1.1 Quote1.2 Quote2.1 Send Signed Order2.2 Broadcast Signed Order3.1 Submit Signed Order3.2 Pull Input4.1 Fill Order5.1 Purchase Order5.2 Pull Inputs from underwriter to solver6.1 Submit Proof6.2 Prove Bitcoin Transaction6.3 Pay underwriter + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/public/d2/docs/cross-cats/underwriting-1.svg b/public/d2/docs/cross-cats/underwriting-1.svg new file mode 100644 index 0000000..05a7852 --- /dev/null +++ b/public/d2/docs/cross-cats/underwriting-1.svg @@ -0,0 +1,1132 @@ +IndexUserDeposit AddressOrder ServerSolverUnderwriterReactorSPV OracleInputOutputOutputInputOutputInputInput 1.1 Quote1.2 Quote2. Sign message to generate key3. Send BTC4.1 Request Signed Order4.2 Request Signed Order4.3 Signed Order4.4 Signed Order5.1 Submit Signed Order5.2 Pull Input Tokens6. Send Bitcoins7.1 Purchase Order7.2 Pull Inputs from underwriter to user8.1 Submit Proof8.2 Prove Bitcoin Transaction8.3 Pay underwriter + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +SetupUserDeposit AddressOrder ServerSolverUnderwriterReactorSPV OracleInputOutputOutputInputOutputInputInput 1.1 Quote1.2 Quote2. Sign message to generate key3. Send BTC4.1 Request Signed Order4.2 Request Signed Order4.3 Signed Order4.4 Signed Order5.1 Submit Signed Order5.2 Pull Input Tokens6. Send Bitcoins7.1 Purchase Order7.2 Pull Inputs from underwriter to user8.1 Submit Proof8.2 Prove Bitcoin Transaction8.3 Pay underwriter + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +InitiationUserDeposit AddressOrder ServerSolverUnderwriterReactorSPV OracleInputOutputOutputInputOutputInputInput 1.1 Quote1.2 Quote2. Sign message to generate key3. Send BTC4.1 Request Signed Order4.2 Request Signed Order4.3 Signed Order4.4 Signed Order5.1 Submit Signed Order5.2 Pull Input Tokens6. Send Bitcoins7.1 Purchase Order7.2 Pull Inputs from underwriter to user8.1 Submit Proof8.2 Prove Bitcoin Transaction8.3 Pay underwriter + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +CompletionUserDeposit AddressOrder ServerSolverUnderwriterReactorSPV OracleInputOutputOutputInputOutputInputInput 1.1 Quote1.2 Quote2. Sign message to generate key3. Send BTC4.1 Request Signed Order4.2 Request Signed Order4.3 Signed Order4.4 Signed Order5.1 Submit Signed Order5.2 Pull Input Tokens6. Send Bitcoins7.1 Purchase Order7.2 Pull Inputs from underwriter to user8.1 Submit Proof8.2 Prove Bitcoin Transaction8.3 Pay underwriter + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +FinalisationUserDeposit AddressOrder ServerSolverUnderwriterReactorSPV OracleInputOutputOutputInputOutputInputInput 1.1 Quote1.2 Quote2. Sign message to generate key3. Send BTC4.1 Request Signed Order4.2 Request Signed Order4.3 Signed Order4.4 Signed Order5.1 Submit Signed Order5.2 Pull Input Tokens6. Send Bitcoins7.1 Purchase Order7.2 Pull Inputs from underwriter to user8.1 Submit Proof8.2 Prove Bitcoin Transaction8.3 Pay underwriter + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/content/docs/cross-cats/underwriting.mdx b/src/content/docs/cross-cats/underwriting.mdx index 4b38337..eac2ab3 100644 --- a/src/content/docs/cross-cats/underwriting.mdx +++ b/src/content/docs/cross-cats/underwriting.mdx @@ -5,8 +5,24 @@ sidebar: order: 21 --- -Cross Cats manages assets in 2 ways: -- Inputs are collected from the signer of an order. For EVM -> BTC the signer is the recipient while for BTC -> VM, the signer is the Solver. These outputs are held in the Cross Cats reactor until the necessary resolution criteria are fulfilled. +import { Tabs, TabItem } from '@astrojs/starlight/components'; + +#### Glossary +- Reactor: Escrow contract for orders. +- Order: A ERC-7683 CrossChainOrder +- Signed Order: An order & its signature. +- Input: Funds pulled into the Reactor. In exchange for outputs. +- Output: Fund sent directly from filler to signer. In exchange for inputs. +- Signer: Signer of an Order. Inputs are always pulled from signer. USDC -> BTC, the signer is a User. BTC -> USDC the signer is a solver. +- Filler: Entity that sends outputs to the Signer. Will receive inputs +- Order Key: Specific order structure that is used to move storage into calldata. Contains the vast majority of all information relevant for the order. Importantly, it contains the registered inputs & outputs. +- Quote: Qualified guess for what the best order that will be accepted. +- Solver: Entity collecting order flow and completing orders. +- User: The person interacting with the cross-cats UI. Creator of Order Flow. +- Recipient: Will receive outputs. Is likely to be either a solver or a user but may be neither. + +#### Cross Cats manages assets in 2 ways: +- Inputs are collected from the signer of an order. For EVM -> BTC the signer is the user while for BTC -> VM, the signer is the Solver. These outputs are held in the Cross Cats reactor until the necessary resolution criteria are fulfilled. - Outputs are sent directly from the filler to the recipient. They are never held by Cross Cats. An important differentiator is that VM assets can be inputs and outputs while non-VM assets like Bitcoin can **only** be outputs. As a result, non-VM to non-VM swaps are not supported since they would require VM assets to be input. Since Outputs are never held by Catalyst and are directly delivered, there is no need to underwrite deliveries. The recipient is already getting their assets at the highest speed possible. @@ -15,6 +31,307 @@ Cross Cats support underwriting inputs, this allows the filler to receive the in ## Quick Overview + + + +```d2 animateInterval=3000 +style.fill: transparent +direction: right + +title: Index { + near: top-center + shape: text + style: { + font-size: 40 + } +} + +vars: { + default-opacity: 0.1 +} + +User: { + Input: { + style.opacity: 1 + } + Output: { + style.opacity: ${default-opacity} + } +} + +Order Server + +Solver: Solver { + style.multiple: true + Input: { + style.opacity: ${default-opacity} + style.fill: "#fbe1e3" + } + Output: { + style.opacity: 1 + style.fill: "#fbe1e3" + } + style.fill: "#fbe1e3" +} +Underwriter: { + Input: { + style.opacity: 1 + style.fill: "#e5ffe7" + } + style.fill: "#e5ffe7" +} + +# On chain: +Reactor: { + Input: {style.opacity: ${default-opacity}} +} +SPV Oracle + +# Step 1. Get a quote for the user. +User <-> Order Server: 1.1 Quote {style.opacity: ${default-opacity}} +Order Server <-> Solver: 1.2 Quote {style.opacity: ${default-opacity}} + +# Step 2. Broadcasting Signed Order. +User -> Order Server: 2.1 Send Signed Order {style.opacity: ${default-opacity}} +Order Server -> Solver: 2.2 Broadcast Signed Order {style.opacity: ${default-opacity}} + +# Step 3. Solver initiates order +Solver -> Reactor: 3.1 Submit Signed Order {style.opacity: ${default-opacity}} +User.Input -> Reactor.Input: 3.2 Pull Input {style.opacity: ${default-opacity}} + +# Step 4. Solver delivers tokens +Solver.Output -> User.Output: 4.1 Fill Order {style.opacity: ${default-opacity}} + +# Step 5. Underwrite +Underwriter -> Reactor: 5.1 Purchase Order {style.opacity: ${default-opacity}} +Underwriter.Input -> Solver.Input: 5.2 Pull Inputs from underwriter to solver {style.opacity: ${default-opacity}} + +# Step 6. Bitcoin Confirmed +Underwriter -> SPV Oracle: 6.1 Submit Proof {style.opacity: ${default-opacity}} +SPV Oracle -> Reactor: 6.2 Prove Bitcoin Transaction {style.opacity: ${default-opacity}} +Reactor.Input -> Underwriter.Input: 6.3 Pay underwriter {style.opacity: ${default-opacity}} + +scenarios: { + Setup: { + title.label: Setup + Solver: Solver {style.multiple: true} + (Order Server <-> Solver)[0].style.opacity: 1 + (User <-> Order Server)[0].style.opacity: 1 + (User -> Order Server)[0].style.opacity: 1 + (Order Server -> Solver)[0].style.opacity: 1 + } + Initiation: { + title.label: Initiation + Solver: Solver { + style.multiple: false + Input.style.fill: "#fbe1e3" + } + Reactor.Input.style.opacity: 1 + User.Input.style.opacity: ${default-opacity} + (User.Input -> Reactor.Input)[0].style.opacity: 1 + (User.Input -> Reactor.Input)[0].style.animated: true + (Solver -> Reactor)[0].style.opacity: 1 + Reactor.Input.style.fill: "#fbe1e3" + } + Completion: { + title.label: Completion + Solver: Solver {style.multiple: false} + Solver.Input.style.opacity: ${default-opacity} + (Underwriter.Input -> Solver.Input)[0].style.opacity: 1 + (Underwriter.Input -> Solver.Input)[0].style.animated: true + User.Input.style.opacity: 1 + Underwriter.Input.style.opacity: ${default-opacity} + Reactor.Input.style.opacity: 1 + Reactor.Input.style.fill: "#e5ffe7" + + (Solver.Output -> User.Output)[0].style.opacity: 1 + (Solver.Output -> User.Output)[0].style.animated: true + Solver.Output.style.opacity: ${default-opacity} + User.Output.style.opacity: 1 + + (Underwriter -> Reactor)[0].style.opacity: 1 + Solver.Input.style.opacity: 1 + User.Output.style.opacity: 1 + Solver.Output.style.opacity: ${default-opacity} + User.Input.style.opacity: ${default-opacity} + } + Finalisation: { + title.label: Finalisation + Solver: Solver {style.multiple: false} + Solver.Input.style.opacity: ${default-opacity} + (Underwriter -> SPV Oracle)[0].style.opacity: 1 + (SPV Oracle -> Reactor)[0].style.opacity: 1 + (Reactor.Input -> Underwriter.Input)[0].style.opacity: 1 + (Reactor.Input -> Underwriter.Input)[0].style.animated: true + Underwriter.Input.style.opacity: 1 + Solver.Input.style.opacity: 1 + User.Output.style.opacity: 1 + Solver.Output.style.opacity: ${default-opacity} + User.Input.style.opacity: ${default-opacity} + } +} +``` + + + + +```d2 animateInterval=3000 +style.fill: transparent +direction: right + +title: Index { + near: top-center + shape: text + style: { + font-size: 40 + } +} + +vars: { + default-opacity: 0.1 +} + +User: { + Input: { + style.opacity: ${default-opacity} + } + Output: { + style.opacity: 1 + } +} +Deposit Address: { + shape: page + Output: { + style.opacity: ${default-opacity} + } +} + +Order Server + +Solver: Solver { + style.multiple: true + Input: { + style.opacity: 1 + style.fill: "#fbe1e3" + } + Output: { + style.opacity: ${default-opacity} + style.fill: "#fbe1e3" + } + style.fill: "#fbe1e3" +} +Underwriter: { + Input: { + style.opacity: 1 + style.fill: "#e5ffe7" + } + style.fill: "#e5ffe7" +} + +# On chain: +Reactor: { + Input: {style.opacity: ${default-opacity}} +} +SPV Oracle + +# Step 1. Get a quote for the user. +User <-> Order Server: 1.1 Quote {style.opacity: ${default-opacity}} +Order Server <-> Solver: 1.2 Quote {style.opacity: ${default-opacity}} + +# Step 2. Sign a message to generate deposit address +User -> Deposit Address: 2. Sign message to generate key {style.opacity: ${default-opacity}} + +# Step 3. Send BTC +User.Output -> Deposit Address.Output: 3. Send BTC {style.opacity: 0.11} + +# Step 4. Request signed order. +User -> Order Server: 4.1 Request Signed Order {style.opacity: ${default-opacity}} +Order Server -> Solver: 4.2 Request Signed Order {style.opacity: ${default-opacity}} +Solver -> Order Server: 4.3 Signed Order {style.opacity: ${default-opacity}} +Order Server -> User: 4.4 Signed Order {style.opacity: 0.11} + +# Step 5. Submit Signed Order +User -> Reactor: 5.1 Submit Signed Order {style.opacity: ${default-opacity}} +Solver.Input -> Reactor.Input: 5.2 Pull Input Tokens {style.opacity: 0.11} + +# Step 6. Send BTC to Solver +Deposit Address.Output -> Solver.Output: 6. Send Bitcoins {style.opacity: ${default-opacity}} + +# Step 7. Underwrite +Underwriter -> Reactor: 7.1 Purchase Order {style.opacity: ${default-opacity}} +Underwriter.Input -> User.Input: 7.2 Pull Inputs from underwriter to user {style.opacity: ${default-opacity}} + +# Step 8. Bitcoin Confirmed +Underwriter -> SPV Oracle: 8.1 Submit Proof {style.opacity: ${default-opacity}} +SPV Oracle -> Reactor: 8.2 Prove Bitcoin Transaction {style.opacity: ${default-opacity}} +Reactor.Input -> Underwriter.Input: 8.3 Pay underwriter {style.opacity: ${default-opacity}} + +scenarios: { + Setup: { + title.label: Setup + Solver: Solver {style.multiple: true} + (User -> Deposit Address)[0].style.opacity: 1 + (Order Server <-> Solver)[0].style.opacity: 1 + (User <-> Order Server)[0].style.opacity: 1 + } + Initiation: { + title.label: Initiation + Solver: Solver { + style.multiple: false + Input.style.fill: "#fbe1e3" + } + Solver.Input.style.opacity: ${default-opacity} + Reactor.Input.style.opacity: 1 + (Solver -> Order Server)[0].style.opacity: 1 + (Order Server -> Solver)[0].style.opacity: 1 + (Order Server -> User)[0].style.opacity: 1 + (Solver.Input -> Reactor.Input)[0].style.opacity: 1 + (Solver.Input -> Reactor.Input)[0].style.animated: true + (User -> Reactor)[0].style.opacity: 1 + (User.Output -> Deposit Address.Output)[0].style.opacity: 1 + (User.Output -> Deposit Address.Output)[0].style.animated: true + (User -> Order Server)[0].style.opacity: 1 + User.Output.style.opacity: ${default-opacity} + Deposit Address.Output.style.opacity: 1 + } + Completion: { + title.label: Completion + Solver: Solver {style.multiple: false} + Solver.Input.style.opacity: ${default-opacity} + (Underwriter.Input -> User.Input)[0].style.opacity: 1 + (Underwriter.Input -> User.Input)[0].style.animated: true + User.Input.style.opacity: 1 + Underwriter.Input.style.opacity: ${default-opacity} + Reactor.Input.style.opacity: 1 + Reactor.Input.style.fill: "#e5ffe7" + (Deposit Address.Output -> Solver.Output)[0].style.opacity: 1 + (Deposit Address.Output -> Solver.Output)[0].style.animated: true + + (Underwriter -> Reactor)[0].style.opacity: 1 + Solver.Output.style.opacity: 1 + User.Output.style.opacity: ${default-opacity} + } + Finalisation: { + title.label: Finalisation + Solver: Solver {style.multiple: false} + Solver.Input.style.opacity: ${default-opacity} + (Underwriter -> SPV Oracle)[0].style.opacity: 1 + (SPV Oracle -> Reactor)[0].style.opacity: 1 + (Reactor.Input -> Underwriter.Input)[0].style.opacity: 1 + (Reactor.Input -> Underwriter.Input)[0].style.animated: true + Underwriter.Input.style.opacity: 1 + User.Input.style.opacity: 1 + Solver.Output.style.opacity: 1 + User.Output.style.opacity: ${default-opacity} + } +} +``` + + + + +The above diagram animates between all system states. Reloading the page or opening the SVG in a separate tab may be required for the animation to show. + In-code underwriting is called `purchaseOrder` since this is exactly what happens. Orders have a `fillerAddress` configured. The `fillerAddress` is the destination for the inputs once an order has been correctly finalized. Purchasing the order from the `fillerAddress` requires sending the inputs (minus a discount) to `fillerAddress`. In exchange, the underwriter gets to set `fillerAddress` to their address thus when the order is finalized they receive the inputs and they gain the discount. Any collateral is exchanged 1:1. @@ -26,6 +343,12 @@ The `purchaseOrder` function is called. Before an underwriter underwrites/purchases an order, it is important to validate that the outputs have been delivered. The underwriter does not gain the entirety of the outputs and won't be able to pay for delivering the outputs based on the discount. +## Underwriting an Order + +Underwriting a BTC -> EVM swap and EVM -> BTC swap works in the same way. From an underwriter's perspective there is no difference. + +For an underwriter, the flow starts when an order is initiated. On order initiation, the event `OrderInitiated` [is emitted](https://github.com/catalystdao/cross-cats/blob/80610c30b9ffc9604a92803adf96c864be23e66c/src/reactors/BaseReactor.sol#L190). It contains the order key along with important relevant information for an underwriter. Importantly, the order key contains a description of the outputs of the order. The underwriter needs to monitor for a payment of the outputs after which they can call [purchaseOrder](https://github.com/catalystdao/cross-cats/blob/80610c30b9ffc9604a92803adf96c864be23e66c/src/reactors/BaseReactor.sol#L406) to underwrite the order. + ## Underwriting Bitcoin Outputs Bitcoin underwriting has 2 levels: