diff --git a/docs/docs/debugging.md b/docs/docs/debugging.md index f735b53..0e7638a 100644 --- a/docs/docs/debugging.md +++ b/docs/docs/debugging.md @@ -35,7 +35,7 @@ emit Callback(chain_id, stop_order, CALLBACK_GAS_LIMIT, payload); ## Contract Inactive -If you see `Contract Status: Inactive` on Reactscan, it means the contract doesn’t have enough funds to cover gas for reactive transactions. Both **destination** and **reactive contracts** must hold sufficient balance to stay active. +If you see `Contract Status: Inactive` on Reactscan, it means the contract doesn’t have enough funds to cover gas for Reactive transactions. Both destination and Reactive contracts must hold sufficient balance to stay active. ![Debugging Image](../docs/img/contract-inactive.png) diff --git a/docs/docs/demos.md b/docs/docs/demos.md index 1216c51..9da43e4 100644 --- a/docs/docs/demos.md +++ b/docs/docs/demos.md @@ -12,30 +12,42 @@ hide_title: true This section contains practical demos of how Reactive Network enables event-driven, cross-chain smart contract automation. Each demo highlights a specific pattern from basic event callbacks to advanced DeFi protection mechanisms. -## Reactive Network Demo +## Reactive Network Basic Demo -The [Reactive Network Demo](https://github.com/Reactive-Network/reactive-smart-contract-demos/tree/main/src/demos/basic) is the starting point. It demonstrates the lifecycle of a Reactive Contract: an event emitted on an origin chain is detected by a Reactive Contract, which then triggers a callback on a destination chain. If you’re new to Reactive Network, begin here. +The [Reactive Network Basic Demo](https://github.com/Reactive-Network/reactive-smart-contract-demos/tree/main/src/demos/basic) is the starting point. It demonstrates the lifecycle of a Reactive contract: an event emitted on an origin chain is detected by a Reactive contract, which then triggers a callback on a destination chain. If you’re new to Reactive Network, begin here. ## Uniswap V2 Stop Order Demo -The [Uniswap V2 Stop Order Demo](https://github.com/Reactive-Network/reactive-smart-contract-demos/tree/main/src/demos/uniswap-v2-stop-order) implements automated stop orders on Uniswap V2 liquidity pools. A Reactive Contract subscribes to `Sync` events from a Uniswap pair. When the exchange rate crosses a user-defined threshold, it triggers a callback that executes the swap on the destination chain. This demo shows how price-based automation can run without off-chain bots. +The [Uniswap V2 Stop Order Demo](https://github.com/Reactive-Network/reactive-smart-contract-demos/tree/main/src/demos/uniswap-v2-stop-order) implements automated stop orders on Uniswap V2 liquidity pools. A Reactive contract subscribes to `Sync` events from a Uniswap pair. When the exchange rate crosses a user-defined threshold, it triggers a callback that executes the swap on the destination chain. ## Uniswap V2 Stop-Loss & Take-Profit Orders Demo -The [Uniswap V2 Stop-Loss & Take-Profit Orders Demo](https://github.com/Reactive-Network/reactive-smart-contract-demos/tree/main/src/demos/uniswap-v2-stop-take-profit-order) expands on stop orders by supporting both stop-loss and take-profit strategies within a personal deployment. A user-owned Reactive Contract monitors pair reserve updates and triggers execution when thresholds are crossed. Each user deploys their own callback and Reactive Contracts, ensuring isolated order management and full control. This example demonstrates structured, event-driven trade automation directly tied to on-chain liquidity changes. +The [Uniswap V2 Stop-Loss & Take-Profit Orders Demo](https://github.com/Reactive-Network/reactive-smart-contract-demos/tree/main/src/demos/uniswap-v2-stop-take-profit-order) expands on stop orders by supporting both stop-loss and take-profit strategies within a personal deployment. A user-owned Reactive contract monitors pair reserve updates and triggers execution when thresholds are crossed. ## Aave Liquidation Protection Demo -The [Aave Liquidation Protection Demo](https://github.com/Reactive-Network/reactive-smart-contract-demos/tree/main/src/demos/aave-liquidation-protection) shows how to automate position protection on Aave. A Reactive Contract subscribes to periodic CRON events and triggers health checks for a user’s lending position. If the health factor drops below a defined threshold, the callback contract executes protection actions — depositing collateral, repaying debt, or both. This demo illustrates time-based automation for DeFi risk management. +The [Aave Liquidation Protection Demo](https://github.com/Reactive-Network/reactive-smart-contract-demos/tree/main/src/demos/aave-liquidation-protection) shows how to automate position protection on Aave. A Reactive Contract subscribes to periodic CRON events and triggers health checks for a user’s lending position. If the health factor drops below a defined threshold, the callback contract executes protection actions: depositing collateral, repaying debt, or both. + +## Leverage Loop Demo + +The [Leverage Loop Demo](https://github.com/Reactive-Network/reactive-smart-contract-demos/tree/main/src/demos/leverage-loop) automates leveraged looping on Aave V3. The user deposits collateral into a personal smart account, and a Reactive contract detects the deposit and runs the loop automatically until the target health factor is reached or the maximum iteration count is hit. + +## Automated Prediction Market Demo + +The [Automated Prediction Market Demo](https://github.com/Reactive-Network/reactive-smart-contract-demos/tree/main/src/demos/automated-prediction-market) implements a prediction market with automated payouts. Users create questions, participants buy shares in outcomes, and a multisig resolves the result. Once the `PredictionResolved` event is emitted, a Reactive contract detects it and triggers batch distribution of winnings. + +## Gasless Cross-Chain Atomic Swap Demo + +The [Gasless Cross-Chain Atomic Swap Demo](https://github.com/Reactive-Network/reactive-smart-contract-demos/tree/main/src/demos/gasless-cross-chain-atomic-swap) enables trustless token exchanges across two blockchains without bridges or custodians. Two users initiate and acknowledge a swap on their respective chains, deposit tokens, and a Reactive contract orchestrates the rest — syncing state, confirming deposits, and completing the swap on both sides automatically. Users only pay gas on their own chain. ## Approval Magic Demo -The [Approval Magic Demo](https://github.com/Reactive-Network/reactive-smart-contract-demos/tree/main/src/demos/approval-magic) shows subscription-based automation triggered by ERC-20 approval events. A Reactive Contract monitors approval logs, while a service contract manages user registrations. When an approval is detected, the system can automatically initiate follow-up actions such as swaps or exchanges. This demo highlights how event-centric logic can simplify multi-step token workflows. +The [Approval Magic Demo](https://github.com/Reactive-Network/reactive-smart-contract-demos/tree/main/src/demos/approval-magic) shows subscription-based automation triggered by ERC-20 approval events. A Reactive contract monitors approval logs, while a service contract manages user registrations. When an approval is detected, the system can automatically initiate follow-up actions such as swaps or exchanges. ## Hyperlane Demo -The [Hyperlane Demo](https://github.com/Reactive-Network/reactive-smart-contract-demos/tree/main/src/demos/hyperlane) shows cross-chain communication using Hyperlane alongside Reactive Network. This example shows how Reactive Network can integrate with external messaging protocols for two-way cross-chain interaction. +The [Hyperlane Demo](https://github.com/Reactive-Network/reactive-smart-contract-demos/tree/main/src/demos/hyperlane) shows cross-chain communication using Hyperlane alongside Reactive Network. This example shows how Reactive can integrate with external messaging protocols for two-way cross-chain interaction. ## CRON Demo -The [Cron Demo](https://github.com/Reactive-Network/reactive-smart-contract-demos/tree/main/src/demos/cron) shows time-based automation using Reactive Network’s built-in CRON events. Instead of waiting for external transactions, the Reactive Contract subscribes to periodic system-emitted events and executes logic on a fixed schedule. This pattern is useful for recurring tasks such as scheduled updates, reward distributions, or regular DeFi position checks. \ No newline at end of file +The [Cron Demo](https://github.com/Reactive-Network/reactive-smart-contract-demos/tree/main/src/demos/cron) shows time-based automation using Reactive Network’s built-in CRON events. Instead of waiting for external transactions, the Reactive contract subscribes to periodic system-emitted events and executes logic on a fixed schedule. This pattern is useful for recurring tasks such as scheduled updates, reward distributions, or regular DeFi position checks. \ No newline at end of file diff --git a/docs/docs/economy.md b/docs/docs/economy.md index 6b663f2..2dbd557 100644 --- a/docs/docs/economy.md +++ b/docs/docs/economy.md @@ -171,7 +171,7 @@ cast call $CALLBACK_PROXY_ADDR "reserves(address)" $CONTRACT_ADDR --rpc-url $DES ### Balance -Retrieve the REACT balance of a reactive contract: +Retrieve the REACT balance of a Reactive contract: ```bash cast balance $CONTRACT_ADDR --rpc-url $REACTIVE_RPC diff --git a/docs/docs/events-and-callbacks.md b/docs/docs/events-and-callbacks.md index 6fd9142..2da90da 100644 --- a/docs/docs/events-and-callbacks.md +++ b/docs/docs/events-and-callbacks.md @@ -14,7 +14,7 @@ Reactive Contracts process on-chain events and trigger transactions on destinati ## Event Processing -To process events, a Reactive Contract must implement the `react()` function defined in the [IReactive](https://github.com/Reactive-Network/reactive-lib/blob/main/src/interfaces/IReactive.sol) interface: +To process events, a Reactive contract must implement the `react()` function defined in the [IReactive](https://github.com/Reactive-Network/reactive-lib/blob/main/src/interfaces/IReactive.sol) interface: ```solidity // SPDX-License-Identifier: UNLICENSED @@ -81,7 +81,7 @@ When this event appears in the transaction trace, Reactive Network submits a tra - **payload** — encoded function call :::info[Callback Authorization] -Reactive Network automatically replaces the first 160 bits of the callback payload with the ReactVM ID (the deployer's address). As a result, the first callback argument is always the ReactVM address (`address` type), regardless of how it is named in Solidity. This ensures that callbacks are tied to the correct Reactive Contract. +Reactive Network automatically replaces the first 160 bits of the callback payload with the ReactVM ID (the deployer's address). As a result, the first callback argument is always the ReactVM address (`address` type), regardless of how it is named in Solidity. This ensures that callbacks are tied to the correct Reactive contract. ::: ### Example: Uniswap Stop Order Demo diff --git a/docs/docs/hyperlane.mdx b/docs/docs/hyperlane.mdx index ed91e9f..61557a4 100644 --- a/docs/docs/hyperlane.mdx +++ b/docs/docs/hyperlane.mdx @@ -12,11 +12,11 @@ import MailboxAddressTable from "../../src/components/hyperlane-mailbox-table"; ## Overview -Reactive Contracts send **cross-chain callback transactions** to destination chains. By default, callbacks are delivered through the Reactive **Callback Proxy**. Hyperlane Mailboxes provide an alternative transport for these callbacks. The Mailbox contract on each supported chain acts as the entry and exit point for cross-chain messages. +Reactive Contracts send **cross-chain callback transactions** to destination chains. By default, callbacks are delivered through the Reactive callback proxy. Hyperlane Mailboxes provide alternative transport for these callbacks. The Mailbox contract on each supported chain acts as the entry and exit point for cross-chain messages. Reactive Contracts still listen to event logs and trigger actions in the same way, only the callback transport changes. Hyperlane transport is useful when: -- A chain does not yet support the Callback Proxy +- A chain does not yet support the callback proxy - You need additional routing flexibility - You want to integrate Reactive Contracts with existing Hyperlane-based systems diff --git a/docs/docs/official-addresses.md b/docs/docs/official-addresses.md index d8e4c34..a9478c8 100644 --- a/docs/docs/official-addresses.md +++ b/docs/docs/official-addresses.md @@ -8,13 +8,11 @@ unlisted: true # Addresses -This page contains all blockchain addresses related to the Reactive Network. +This page contains all blockchain addresses related to Reactive Network. -| Chain | Address | Description | -|------------------|----------------------------------------------|-----------------------------------| -| Ethereum Mainnet | `0x6fBb0C7A0ec62007013748e47823C239Dd48BfEf` | Bridge PRQ\<\>REACT | -| Ethereum Mainnet | `0x42458259d5c85fB2bf117f197f1Fef8C3b7dCBfe` | Bridge WREACT\<\>REACT | -| BNB Smart Chain | `0x577432505892F7B18a26166247a7456B814E2f68` | Bridge PRQ BNB>REACT | -| Reactive Mainnet | `0x4F55172b66bab5e58DB20bd4d25e9301A22f2979` | Reactive part of PRQ\<\>REACT | -| Reactive Mainnet | `0x1aa8615D92e0F5b65Bf02939C116db3AA654D38A` | Reactive part of WREACT\<\>REACT | -| Reactive Mainnet | `0x1176172108b1611f7A1d2F7b0A6f889650F99EAB` | Reactive part of PRQ BNB>REACT | +| Chain | Address | Description | +|------------------|----------------------------------------------|-----------------------------| +| Ethereum Mainnet | `0x42458259d5c85fB2bf117f197f1Fef8C3b7dCBfe` | Bridge WREACT\<\>REACT | +| Base Mainnet | `0xe68eAD313A33A78E0B00e25aE22800D4455cd5C8` | Bridge WREACT\<\>REACT | +| Reactive Mainnet | `0x1aa8615D92e0F5b65Bf02939C116db3AA654D38A` | REACT\<\>WREACT to Ethereum | +| Reactive Mainnet | `0xCAe30c6Ca71E830bE6370d110758e76fB9e44D9B` | REACT\<\>WREACT to Base | diff --git a/docs/docs/origins-and-destinations.mdx b/docs/docs/origins-and-destinations.mdx index 91b72bb..de5445c 100644 --- a/docs/docs/origins-and-destinations.mdx +++ b/docs/docs/origins-and-destinations.mdx @@ -18,7 +18,7 @@ Reactive Contracts (RCs) can **listen to event logs on one chain** and **trigger - **Origin** — the chain where events happen and event logs are read from (the event source). - **Destination** — the chain where Reactive Network delivers a callback transaction (the chain where state changes happen). -Origins and destinations don’t have to be the same. A single Reactive Contract can subscribe to events from multiple origin chains, and it can send callbacks to one or more destination chains. Your Solidity logic can also choose the destination conditionally. +Origins and destinations don’t have to be the same. A single Reactive contract can subscribe to events from multiple origin chains, and it can send callbacks to one or more destination chains. Your Solidity logic can also choose the destination conditionally. ## Callback Proxy Address @@ -27,7 +27,7 @@ Callbacks are delivered to destination chains via a **Callback Proxy** contract. A destination contract can validate a callback by checking: 1. **The sender is the Callback Proxy** (so the call is coming through the expected entry point). -2. **The embedded RVM ID matches the intended Reactive Contract** (so the callback is tied to the correct RC). +2. **The embedded RVM ID matches the intended Reactive contract** (so the callback is tied to the correct RC). :::info[Hyperlane] Some networks can’t act as destination chains yet because the Callback Proxy contract hasn’t been deployed there. In that case, use [Hyperlane](./hyperlane) as the transport for cross-chain callbacks. diff --git a/docs/docs/reactive-lib.mdx b/docs/docs/reactive-lib.mdx index ca7726c..bc58295 100644 --- a/docs/docs/reactive-lib.mdx +++ b/docs/docs/reactive-lib.mdx @@ -260,7 +260,7 @@ struct LogRecord { } ``` -The `Callback` event is emitted when a Reactive Contract triggers a callback transaction. +The `Callback` event is emitted when a Reactive contract triggers a callback transaction. ```solidity event Callback( diff --git a/docs/docs/reactvm.md b/docs/docs/reactvm.md index 98a751e..5766322 100644 --- a/docs/docs/reactvm.md +++ b/docs/docs/reactvm.md @@ -10,23 +10,44 @@ hide_title: true ## Overview -ReactVM is a private execution environment within Reactive Network where [Reactive Contracts](./reactive-contracts) process events and execute logic. Each Reactive Contract runs inside a dedicated ReactVM that activates when subscribed events occur. Event logs are delivered to the ReactVM, where the contract executes Solidity logic and determines whether callback transactions should be sent to destination chains. ReactVMs run independently and can execute in parallel, allowing Reactive Contracts to process events while maintaining deterministic execution within each ReactVM. +ReactVM is a private execution environment within Reactive Network where [Reactive Contracts](./reactive-contracts) process events and execute logic. Each Reactive contract runs inside a dedicated ReactVM that activates when subscribed events occur. Event logs are delivered to the ReactVM, where the contract executes Solidity logic and determines whether callback transactions should be sent to destination chains. ReactVMs run independently and can execute in parallel, allowing Reactive contracts to process events while maintaining deterministic execution within each ReactVM. ## My ReactVM -Each deployed Reactive Contract is assigned to a ReactVM derived from the deployer’s address. Contracts deployed from the same EOA share the same ReactVM and can interact through shared state. Although multiple Reactive Contracts can be deployed within one ReactVM, separating contracts across ReactVMs is generally recommended. +Each deployed Reactive contract is assigned to a ReactVM derived from the deployer's address. Contracts deployed from the same EOA share the same ReactVM and can interact through shared state. Although multiple Reactive Contracts can be deployed within one ReactVM, separating contracts across ReactVMs is generally recommended. ### Calling subscribe() Calling `subscribe()` or `unsubscribe()` inside ReactVM has no effect. Subscriptions must be managed through the Reactive Network instance of the contract. ReactVM contracts should communicate through callback transactions instead of direct subscription calls. +### Callback Identity + +When a Reactive contract constructs a callback payload, the first argument must be reserved for the RVM ID. Developers pass `address(0)` as a placeholder in this slot, and Reactive Network automatically overwrites the first 160 bits with the deployer's address before the callback reaches the destination chain. This means callbacks always carry an authenticated origin that can't be forged by the contract itself. + +The callback must include at least one argument, omitting the first slot entirely will cause the call to fail, since the system has no location to inject the RVM ID. Destination contracts can rely on this first argument to identify which ReactVM originated the callback. + +Example from [Uniswap V2 Stop Order Demo](https://github.com/Reactive-Network/reactive-smart-contract-demos/blob/f1f85ab2a0a8f917b9b37a57c00be2ffc8ad5ad4/src/demos/uniswap-v2-stop-order/UniswapDemoStopOrderReactive.sol#L107): + +```solidity +bytes memory payload = abi.encodeWithSignature( + "stop(address,address,address,bool,uint256,uint256)", + address(0), // Overwritten with the deployer's RVM ID + pair, + client, + token0, + coefficient, + threshold +); +emit Callback(chain_id, stop_order, CALLBACK_GAS_LIMIT, payload); +``` + ## State Each ReactVM maintains its own state based on processed events. ReactVM blocks include references to origin-chain block numbers and hashes, allowing Reactive Network to track and handle chain reorganizations. ReactVM states operate independently, and the overall Reactive Network state is the combination of all ReactVM states. ### Dual-State Environment -Each Reactive Contract exists in two environments with separate state: +Each Reactive contract exists in two environments with separate state: - **ReactVM State** — updated automatically when subscribed events occur - **Reactive Network State** — updated when EOAs call contract functions diff --git a/docs/docs/rnk-rpc-methods.md b/docs/docs/rnk-rpc-methods.md index 93b869a..a30fc1d 100644 --- a/docs/docs/rnk-rpc-methods.md +++ b/docs/docs/rnk-rpc-methods.md @@ -832,9 +832,9 @@ Returns an array of filter objects. Each filter object contains the following fi - **chainId** (`uint32`): The chain ID on which the filter is active. - **contract** (`string`): The address of the contract the filter is listening to. - **topics** (`array[string | null]`): An array of up to 4 log topics (from `topic_0` to `topic_3`) used for event filtering. Unused topics are null. -- **configs** (`array[object]`): An array of configuration objects for reactive contracts and their associated ReactVMs. -- **contract** (`string`): The reactive contract address. -- **rvmId** (`string`): The ReactVM ID where the reactive contract resides. +- **configs** (`array[object]`): An array of configuration objects for Reactive contracts and their associated ReactVMs. +- **contract** (`string`): The Reactive contract address. +- **rvmId** (`string`): The ReactVM ID where the Reactive contract resides. - **active** (`bool`): Indicates whether the subscription/filter is active. ```json diff --git a/docs/education/introduction/index.md b/docs/education/introduction/index.md index 48ea3f0..fb25e3e 100644 --- a/docs/education/introduction/index.md +++ b/docs/education/introduction/index.md @@ -1,7 +1,7 @@ --- sidebar_position: 1 title: Introduction -description: Embark on a journey through Reactive Contracts with our educational program. Dive into lectures, GitHub code, and video demos for a hands-on learning experience. +description: Educational course on Reactive Contracts covering events, callbacks, subscriptions, oracles, and ReactVM. Includes lectures, GitHub code examples, and video workshops for developers building on Reactive Network. slug: /education/introduction hide_title: true --- @@ -10,11 +10,11 @@ hide_title: true ## Overview -To better understand the concept of Reactive Contracts (RCs), we have developed an educational course featuring detailed lectures, code snippets on [GitHub](https://github.com/Reactive-Network/reactive-smart-contract-demos/tree/main/src/demos), and video workshops on [YouTube](https://www.youtube.com/@0xReactive/streams). Our goal is to provide both theoretical knowledge and practical challenges, creating a community where developers can fully explore RCs. +Reactive contracts allow smart contracts to automatically respond to events on other blockchains, without anyone having to trigger them manually. If that sounds unfamiliar, you're in the right place. -## Where to Begin +This course walks you through how Reactive contracts work, step by step. You'll find detailed lectures, working code on [GitHub](https://github.com/Reactive-Network/reactive-smart-contract-demos/tree/main/src/demos), and video workshops on [YouTube](https://www.youtube.com/@0xReactive/streams). Each module pairs theory with hands-on challenges so you can learn by building, not just reading. -The Introduction chapter provides an overview of Reactive Contracts, highlighting their ability to autonomously react to events on EVM-compatible chains. It also outlines the technical and knowledge prerequisites necessary for mastering these concepts. +Start with the introduction for a closer look at what Reactive contracts can do and how they operate across EVM-compatible chains, then check the prerequisites to make sure you have the right background before moving on. [Introduction to Reactive Contracts →](./reactive-contracts.md) @@ -22,7 +22,7 @@ The Introduction chapter provides an overview of Reactive Contracts, highlightin ## Module One -[Module 1](../module-1/index.md) is dedicated to the basics of Reactive Contracts, events and callbacks, the ReactVM and Reactive Network environments, subscriptions, and the function of oracles in integrating off-chain data. +[Module 1](../module-1/index.md) covers the building blocks. You'll learn how Reactive contracts are structured, how they detect and respond to events through callbacks, and how the ReactVM execution environment fits into the picture. It also explains subscriptions (how a contract "listens" for specific events) and the role oracles play in bringing off-chain data on-chain. [Reactive Contracts →](../module-1/reactive-contracts.md) @@ -36,7 +36,7 @@ The Introduction chapter provides an overview of Reactive Contracts, highlightin ## Module Two -[Module 2](../module-2/index.md) explores Uniswap V2, focusing on liquidity pools and smart contract operations. It also elaborates on the basic functions of Reactive Contracts that enable autonomous execution. +[Module 2](../module-2/index.md) puts those building blocks to use with a real protocol. You'll walk through how Uniswap V2 works under the hood (its liquidity pools and smart contract mechanics) then see how Reactive contracts can interact with it autonomously. This is where the basics start clicking into practical applications. [How Uniswap Works →](../module-2/how-uniswap-works.md) @@ -44,7 +44,7 @@ The Introduction chapter provides an overview of Reactive Contracts, highlightin ## Use Cases -The [Use Cases](../use-cases/index.md) section explains scenarios where Reactive Contracts can improve blockchain apps. It includes a basic demo for low-latency log monitoring and interaction across different chains, a guide on deploying RCs using Remix, and a demonstration of a stop order implementation on a Uniswap V2 liquidity pool. +Once you understand the fundamentals, the [Use Cases](../use-cases/index.md) section shows what you can build with them. It walks through a basic demo for monitoring logs across chains with low latency, a stop order on a Uniswap V2 pool that executes automatically, and a step-by-step guide to deploying Reactive contracts using the Remix IDE. [Basic Demo →](../use-cases/use-case-1.md) @@ -54,6 +54,6 @@ The [Use Cases](../use-cases/index.md) section explains scenarios where Reactive ## Glossary -The Glossary provides concise definitions of key terms related to blockchain technology, decentralized finance, and smart contracts, including specific Reactive terms to prevent potential confusion. +Blockchain documentation comes with a lot of specialized terminology. The glossary defines key concepts from blockchain, DeFi, and smart contract development, along with terms specific to the Reactive ecosystem. Worth bookmarking if something in the course doesn't immediately click. [Glossary →](../glossary.md) \ No newline at end of file diff --git a/docs/education/introduction/prerequisites.md b/docs/education/introduction/prerequisites.md index bd2ba92..ad6a557 100644 --- a/docs/education/introduction/prerequisites.md +++ b/docs/education/introduction/prerequisites.md @@ -1,7 +1,7 @@ --- title: Technical and Knowledge Prerequisites for Mastering Reactive Contracts sidebar_position: 2 -description: Learn Reactive Contracts (RCs) with prerequisites like Solidity, EVM basics, Git, and an Ethereum wallet. +description: What you need to know before starting the Reactive Contracts course. Covers required background in Solidity, EVM, Git, and command line tools, plus wallet setup for Ethereum Sepolia testnet deployment. slug: prerequisites --- @@ -9,54 +9,44 @@ slug: prerequisites ## Overview -Before embarking on your journey, it's crucial to have a solid foundation in several key areas. These prerequisites will ensure you can fully grasp the concepts and practical applications of Reactive Contracts (RCs). +This course aims to cover everything you need to understand and work with Reactive contracts, including deploying and interacting with them. That said, some foundational knowledge will make the material much easier to follow. Here's what helps to know going in, along with resources to get up to speed if anything is unfamiliar. -## What You Need to Know for This Course - -In this course, we aim to equip you with everything you need to grasp the basic use cases of Reactive Contracts, including deploying and interacting with them. While we intend to cover all critical information, a foundational understanding of Ethereum Smart Contracts will greatly improve your learning experience. Below are the prerequisites along with resources to help you get up to speed. +## What You Need to Know ### Solidity and Smart Contract Development -Understanding the syntax and functionalities of Solidity is fundamental. You should be comfortable writing simple smart contracts and familiar with their concepts. +You should be comfortable writing simple smart contracts in Solidity and familiar with its core concepts: variables, functions, modifiers, and contract structure. You don't need to be an expert, but the course assumes you've written and deployed at least a basic contract before. -Educational Resource: [Solidity by Example](https://solidity-by-example.org/) is an excellent place to start, offering hands-on examples to guide you through Solidity's basics to more advanced topics. +Resource: [Solidity by Example](https://solidity-by-example.org/) walks you through Solidity from basics to more advanced topics with hands-on examples. ### Ethereum Virtual Machine (EVM) -A basic understanding of the EVM is crucial as it's the runtime environment for smart contracts. Knowledge about how contracts are executed, how functions operate, and how transactions are signed will be beneficial. +A general understanding of how the EVM executes smart contracts will help. Knowing how function calls work, how transactions are signed, and what happens when a contract runs is enough. You don't need to understand bytecode-level details. -Educational Resource: The [Ethereum EVM illustrated](https://takenobu-hs.github.io/downloads/ethereum_evm_illustrated.pdf) guide provides a visual and detailed explanation of the EVM's inner workings. +Resource: The [Ethereum EVM illustrated](https://takenobu-hs.github.io/downloads/ethereum_evm_illustrated.pdf) is a visual walkthrough of how the EVM works internally. -### Git and Command Line Understanding +### Git and Command Line -Understanding basic Git commands and command line usage is crucial for effectively using the code examples that we will provide. Familiarity with an Integrated Development Environment (IDE) like Visual Studio Code can significantly enhance your coding experience. +The course includes code examples you'll clone and run locally, so you'll need to be comfortable with basic Git commands and working in a terminal. Familiarity with an IDE like Visual Studio Code also helps. -Educational Resource: The [Pro Git](https://git-scm.com/book/en/v2) book offers a concise and practical introduction to Git. For command line basics, check out the [Codecademy's Command Line](https://www.codecademy.com/learn/learn-the-command-line) course. +Resource: The [Pro Git](https://git-scm.com/book/en/v2) covers everything you need to know about Git. For terminal basics, try [Codecademy's Command Line](https://www.codecademy.com/learn/learn-the-command-line) course. ### Ethereum Wallet and Test ETH -To interact with Ethereum networks, including deploying and testing smart contracts, you'll need an Ethereum wallet and some ETH on the Sepolia testnet. This setup is vital for transaction fees (gas) and interacting with deployed contracts. - -Getting Sepolia ETH: Visit the [Sepolia Faucet](https://www.alchemy.com/faucets/ethereum-sepolia) to obtain testnet ETH. - -## What You Don’t Need to Know Beforehand - -We recognize that some topics, while not directly related to Reactive Contracts, are essential for a comprehensive understanding of the blockchain landscape. To ensure you have a well-rounded knowledge base, we've included lessons on these broader blockchain concepts and tools. This means you won’t have to look elsewhere to fill in the gaps. - -### Knowledge of EVM Events +You'll need an Ethereum wallet (like MetaMask) and some test ETH on the Ethereum Sepolia testnet to deploy and interact with contracts during the course. Test ETH is used to cover gas fees on the testnet, so you can experiment without spending real funds. -EVM events are a cornerstone for RCs, serving as triggers for reactive functionalities. An understanding of how events work, how they're logged, and how to interact with them is crucial. +Resource: Get Sepolia ETH from the [Sepolia Faucet](https://www.alchemy.com/faucets/ethereum-sepolia). -Educational Resource: Learn about [EVM events](../module-1/how-events-work.md) in detail. +## What the Course Covers for You -### Decentralized Finance Concepts +Some topics are important for working with Reactive contracts but aren't prerequisites as the course teaches them directly. You don't need to study these in advance. -Familiarity with DeFi concepts, such as liquidity pools, yield farming, and automated market makers (AMMs), will be helpful, especially for understanding real-world applications of RCs. +### EVM Events -Educational Resource: We'll explain some of these concepts in our next articles as we walk you through the corresponding use cases. +Events are central to how Reactive contracts work. They act as the triggers that tell a Reactive contract something has happened on another chain. The course covers how events are emitted, logged, and consumed in detail. -## Conclusion +Resource: [How Events and Callbacks Work](../module-1/how-events-work.md). -These prerequisites will set you up for success in mastering Reactive Contracts, and fully leveraging their potential in your blockchain projects. Stay tuned for our upcoming article on EVM events that will further solidify your understanding and application of these concepts. +### Decentralized Finance (DeFi) Concepts -Remember, the blockchain space is ever-evolving, so continuous learning is key. These resources are just the beginning; dive deep, experiment, and don't hesitate to engage with the community for insights and assistance. +Some modules use DeFi protocols like Uniswap V2 as real-world examples. Concepts like liquidity pools and automated market makers come up, but the course explains them as they become relevant. No prior DeFi knowledge required. diff --git a/docs/education/introduction/reactive-contracts.md b/docs/education/introduction/reactive-contracts.md index 1e9f26b..bd54249 100644 --- a/docs/education/introduction/reactive-contracts.md +++ b/docs/education/introduction/reactive-contracts.md @@ -1,48 +1,44 @@ --- title: "Reactive Contracts: What They Are and Why We Need Them" sidebar_position: 1 -description: Discover Reactive Contracts (RCs), revolutionizing blockchain interaction with decentralized automation. Join our course to explore their potential, from Uniswap stop orders to NFT synchronization. +description: Reactive Contracts are smart contracts that autonomously monitor and respond to events across EVM-compatible blockchains. Explains what they are, how they differ from traditional smart contracts, and why cross-chain automation matters. slug: reactive-contracts --- -# Reactive Contracts: What They Are and Why We Need Them +# What Are Reactive Contracts and Why Do They Matter -## Introduction to Reactive Contracts +## What Are Reactive Contracts -Reactive Contracts (RCs) represent a paradigm shift in how we interact with blockchain technology. Unlike traditional smart contracts that are run by user transactions, RCs actively monitor events on EVM-compatible chains and react to them. They process these events according to the implemented logic and execute further actions on the blockchain autonomously. This innovation introduces a decentralized mechanism for automating responses to on-chain events without manual actions. +Regular smart contracts sit idle until someone sends them a transaction. They can't watch what's happening on the blockchain and act on their own. They always need an external push, whether from a user or an automated script holding private keys. + +Reactive contracts work differently. They monitor events across EVM-compatible chains and respond to them automatically, executing logic and triggering on-chain actions without anyone having to intervene. No manual transactions, no centralized bots, no private key management on your end. ![Basic Reactive Workflow](./img/basic-reactive-workflow.jpg) -## Why Reactive Contracts +## Why This Matters -In the Ethereum world, smart contracts have revolutionized how we conceive of executing trustless agreements. Traditionally, these contracts spring into action only upon a user-initiated transaction. This presents inherent limitations. For one, smart contracts can't autonomously initiate actions or respond to blockchain events without an external prompt — either from a user or an automated script like a trading bot. This requires holding private keys and introducing a centralized point of control. +Traditional smart contracts have a fundamental limitation: they can't initiate anything. If you want a contract to respond to something happening on-chain (say, a price change or a token transfer), you need an external service watching for that event and submitting a transaction to trigger the response. That service holds private keys, runs on centralized infrastructure, and becomes a single point of failure. -Reactive Contracts (RCs) emerge as a solution to this constraint. RCs are designed to autonomously react to events in the Ethereum Virtual Machine (EVM) and trigger subsequent actions across the blockchain ecosystem. This capability for the implementation of complex logic that can source information from multiple chains and enact changes or transactions across various platforms without a central oversight. +Reactive contracts remove that dependency. They can receive information from multiple chains and execute actions across different networks, all without centralized oversight. The logic lives entirely on-chain, and execution is decentralized. -## The Advantages of RCs +## Advantages -**Decentralization:** RCs operate independently on the blockchain, eliminating centralized points of control and improving security by reducing the risk of manipulation or failure. +**Decentralization.** Reactive contracts operate independently on the blockchain. There's no centralized service that can be manipulated, shut down, or fail. The contract handles everything on its own. -**Automation:** RCs automatically execute smart contract logic in response to on-chain events, reducing the need for manual interventions and allowing for efficient, real-time responses. +**Automation.** Contract logic executes automatically when the right on-chain event occurs. No one needs to monitor anything manually or keep a bot running around the clock. -**Cross-Chain Interoperability:** RCs can interact with multiple blockchains, enabling complex cross-chain interactions that enhance versatility and bridge gaps between networks. +**Cross-chain interoperability.** A single Reactive contract can monitor events on one chain and trigger actions on another, enabling workflows that span multiple networks without custom bridging infrastructure. -**Enhanced Efficiency and Functionality:** By reacting to real-time data, RCs boost the efficiency of smart contracts, supporting advanced functionalities like complex financial instruments, dynamic NFTs, and innovative DeFi applications. +**Efficiency.** Because Reactive contracts respond to events in real time, they support use cases that depend on speed like reacting to price movements or processing transactions the moment they happen. -**Innovation in DeFi and Beyond:** RCs enable new possibilities in DeFi and other blockchain applications, such as automated trading and dynamic governance, creating a more responsive and interconnected blockchain ecosystem. +**New possibilities.** The combination of automation and cross-chain reach opens up applications that weren't practical before. ## About This Course -To equip developers with the skills to harness RCs, we've created a comprehensive course with detailed documentation and hands-on tutorials. Our goal is to foster a collaborative space where developers can explore the full potential of RCs. - -The course offers lectures, GitHub code examples, and video demonstrations for a multi-faceted learning experience. Whether you're interested in theory or practical [use cases](../use-cases/index.md), this course adapts to your needs. +This course is designed to give you both the theory and the hands-on experience to start building with Reactive contracts. It includes detailed lectures, code examples on GitHub, and video workshops covering everything from basic concepts to real-world deployments. -Throughout the course, we will examine various applications of RCs, including: +Whether you want to understand how Reactive contracts work under the hood or jump straight into building, the course adapts to either path. Explore the [use cases](../use-cases/index.md) if you want to see what's possible, or start from Module 1 to build up from the fundamentals. -* Implementing Uniswap stop orders through RCs -* Synchronizing NFT ownership over several chains -* Automatically collecting staking rewards from different pools and chains +Join the [Telegram](https://t.me/reactivedevs) community if you have questions or want to connect with other developers working with Reactive contracts. -## Conclusion -Reactive Contracts (RCs) represent a major leap in blockchain technology by enabling autonomous execution of complex logic without user intervention. Unlike traditional EVMs, RCs can automatically respond to events from multiple blockchains, allowing for flexible cross-chain interactions. This unique reactivity and versatility make RCs a valuable tool for developers aiming to build more dynamic and interconnected decentralized applications. Join our [Telegram](https://t.me/reactivedevs) group and explore the frontier of blockchain technology, where your creativity and expertise can help shape the future of decentralized applications. diff --git a/docs/education/module-1/how-events-work.md b/docs/education/module-1/how-events-work.md index e118910..60b9022 100644 --- a/docs/education/module-1/how-events-work.md +++ b/docs/education/module-1/how-events-work.md @@ -1,7 +1,7 @@ --- title: "Lesson 2: How Events and Callbacks Work" sidebar_position: 2 -description: Discover how EVM events enable smart contracts to communicate with the outside world on the Ethereum blockchain. Learn about event creation, emission, and listening, with a Chainlink's price oracle integration example. Learn on callbacks to destination chains. +description: Learn how EVM events and callbacks work in Reactive Contracts. Covers event creation and emission, the IReactive interface and react() method, and how callbacks trigger cross-chain transactions on destination chains. slug: how-events-work --- @@ -9,56 +9,43 @@ slug: how-events-work ## Overview -In Ethereum, events enable smart contracts to communicate with the external world by logging specific information when certain conditions are met. This allows decentralized applications (dApps) to trigger and respond to occurrences without constantly polling the blockchain. Events are indexed by the EVM, making them easily searchable, which is particularly useful for monitoring blockchain activities like transfers, contract updates, and price changes from oracles. +Events are how smart contracts communicate with the outside world. When something happens on-chain (a transfer, a price update, a contract state change), a smart contract can emit an event that gets recorded in the transaction's logs. External applications can listen for these events and respond to them. -This lesson focuses on the role of events and callbacks in smart contracts. By learning how to emit, process, and listen to events, developers can create dynamic dApps that respond to blockchain changes in real-time. We will also explore how Reactive Contracts use the `react()` method to handle events and initiate cross-chain transactions through callbacks, enabling improved functionality within the Reactive Network. +This is the foundation that Reactive contracts are built on. Instead of an external application listening for events and manually submitting transactions in response, a Reactive contract handles that entire loop on-chain: it detects events through the `react()` method, processes them, and can trigger actions on other chains through callbacks. -By the end of this lesson, you will learn to: +By the end of this lesson, you'll understand: -* Define and emit events in an Ethereum smart contract. -* Listen for and process events using decentralized applications. -* Implement event processing in Reactive Contracts. -* Send callbacks to trigger actions on destination chains. +- How events are defined, emitted, and listened for in Ethereum +- How Reactive Contracts process events through the `IReactive` interface +- How callbacks let a Reactive contract trigger transactions on destination chains ## How EVM Events Work -When a smart contract emits an event, the event data is stored in the transaction's logs. These logs are attached to the blocks of the blockchain but don't directly affect the blockchain state. Instead, they provide a way to record and retrieve information based on the event's parameters. +When a smart contract emits an event, the data is stored in the transaction's logs. These logs are attached to blocks on the blockchain but don't directly affect the blockchain state. They're a way to record and retrieve information without writing to contract storage. -Developers define events in smart contracts using the `event` keyword, followed by the event name and the data types of the information they want to log. To emit an event, the smart contract uses the `emit` keyword, followed by the event name and the data to be logged. - -External applications, such as dApps or backend services, can listen for these events. By specifying the event signature and, optionally, filtering parameters, these applications can subscribe to real-time updates whenever the event is emitted. This mechanism is pivotal for creating responsive and interactive blockchain applications. - -## Example: Chainlink Price Oracle Integration - -Chainlink's decentralized oracle network provides real-time data feeds for various cryptocurrencies, commodities, and other off-chain data, directly into smart contracts. Let's see how an EVM event can be used in conjunction with Chainlink's price oracle. - -### Defining the Price Update Event - -Imagine a smart contract that needs real-time price information to execute its logic, such as a DeFi lending platform that adjusts collateral requirements based on the latest market prices. The contract might define an event like this: +To define an event, you use the `event` keyword in Solidity, followed by the event name and the data types you want to log. To fire it, you use the `emit` keyword: ```solidity +// Define event PriceUpdated(string symbol, uint256 newPrice); -``` -This event is designed to log the symbol of the asset and its new price whenever the price is updated. - -### Emitting the Event - -When the smart contract receives a new price update from Chainlink's oracle, it emits the `PriceUpdated` event: - -```solidity +// Emit emit PriceUpdated("ETH", newEthPrice); ``` -In this line, `newEthPrice` is the updated price of Ethereum fetched from Chainlink, whose oracle is updated periodically. +External applications (dApps, backend services, or in our case Reactive contracts) can subscribe to these events by specifying the event signature and optional filtering parameters. Whenever a matching event is emitted, the subscriber gets notified. This is what makes responsive, real-time blockchain applications possible. + +## Example: Chainlink Price Oracle -### Listening for the Price Update +To make this concrete, consider a DeFi lending platform that adjusts collateral requirements based on market prices. It uses Chainlink's decentralized oracle network to get real-time price data. -A dApp or an investor's portfolio management tool can listen for the `PriceUpdated` event to trigger specific actions such as rebalancing a portfolio or issuing a loan. We will use a Reactive Contract to catch these events in later lessons. +The contract defines a `PriceUpdated` event and emits it whenever Chainlink's oracle delivers a new price. A portfolio management tool, a liquidation bot, or a Reactive contract can listen for that event and act on it immediately, rebalancing a portfolio, issuing a loan, or triggering a cross-chain transaction. + +In later lessons, you'll see how to set up a Reactive Contract to catch exactly these kinds of events. ## Event Processing in Reactive Contracts -Reactive Contracts must implement the [`IReactive`](https://github.com/Reactive-Network/reactive-lib/blob/main/src/interfaces/IReactive.sol) interface to handle incoming events. +To receive and process events, a Reactive contract must implement the [`IReactive`](https://github.com/Reactive-Network/reactive-lib/blob/main/src/interfaces/IReactive.sol) interface: ```solidity pragma solidity >=0.8.0; @@ -92,66 +79,42 @@ interface IReactive is IPayer { } ``` -**LogRecord Structure**: A structured data type, `LogRecord`, is defined to contain detailed information about an event log: -- `chain_id`: ID of the blockchain where the event originated. -- `_contract`: Address of the contract that emitted the event. -- `topic_0` to `topic_3`: Indexed topics of the log. -- `data`: Non-indexed data from the event log. -- `block_number`: Block number where the event occurred. -- `op_code`: Potentially denotes an operation code. -- `block_hash`, `tx_hash`, and `log_index`: Additional identifiers to trace the event's origin and context. +This interface has three key parts: -**Callback Event**: An event to notify subscribers of specific occurrences: -- `chain_id`: Blockchain ID of the event. -- `_contract`: Address of the emitting contract. -- `gas_limit`: Maximum gas allocated for the callback. -- `payload`: Encoded data accompanying the callback. +**LogRecord** is the data structure that describes an incoming event. It contains everything a Reactive contract needs to understand what happened and where: the chain ID, the contract address that emitted the event, indexed topics, raw event data, and identifiers like block number, transaction hash, and log index. -**react Function**: A key function that handles incoming event notifications. -- Takes a `LogRecord` as input, enabling reactive contracts to process event logs dynamically. -- Marked as `external`, allowing it to be called only from outside the contract. +**Callback** is the event a Reactive contract emits when it wants to trigger an action on another chain. It specifies the destination chain ID, the target contract address, a gas limit, and an encoded payload containing the transaction details. -The Reactive Network continuously monitors event logs and matches them against the subscription criteria defined in reactive contracts. When an event that meets the criteria is detected, the network triggers the `react()` method, passing in relevant details. +**react()** is the function Reactive Network calls when a matching event is detected. It receives a `LogRecord` as input, and your implementation decides what to do with it (update state, run calculations, emit a callback, or all of the above). -Reactive contracts can access all standard EVM functionalities. However, they run within a private ReactVM, which restricts them to interacting with contracts deployed by the same deployer. This isolation ensures that reactive contracts maintain a controlled and secure environment while processing events from the Reactive Network. +Reactive Network continuously monitors event logs and matches them against the subscription criteria defined in your contract. When a match is found, it triggers `react()` with the relevant event details. -## Callbacks to Destination Chains +One important constraint: Reactive Contracts run within a private ReactVM instance, which restricts them to interacting with contracts deployed by the same deployer. This isolation keeps the execution environment secure while the contract processes events from across the network. -Reactive contracts can initiate transactions on destination chains by emitting log records in a specific format. These records are picked up by the Reactive Network, which then carries out the desired transactions on the relevant chain. +## Callbacks to Destination Chains -### Emitting Callback Events +Callbacks are how a Reactive contract reaches beyond Reactive Network and triggers actions on other blockchains. When your `react()` logic determines that something needs to happen on a destination chain, it emits a `Callback` event. Reactive picks that up and submits the corresponding transaction. -To request actions on destination chains, the user must trigger a `Callback` event in the Reactive Contract. Once triggered, this event is emitted by the smart contract and provides critical information that the Reactive Network needs to create and submit the transaction. +### Emitting a Callback -The `Callback` event includes the following parameters: +The `Callback` event takes four parameters: -- `chain_id`: The EIP155 chain ID of the destination network. -- `_contract`: The address of the destination contract. -- `gas_limit`: The gas limit for the transaction on the destination chain. -- `payload`: Encoded data that specifies a function call on the destination. This data directs the Reactive Network on how to execute the intended action on the destination contract. +- `chain_id` — the EIP155 chain ID of the destination network +- `_contract` — the address of the target contract on that chain +- `gas_limit` — the gas limit for the destination transaction +- `payload` — ABI-encoded data specifying the function call to execute -Here’s the signature of the `Callback` event: +### How the Callback Is Processed -```solidity -event Callback( - uint256 indexed chain_id, - address indexed _contract, - uint64 indexed gas_limit, - bytes payload -); -``` +When Reactive Network detects a `Callback` event, it decodes the `payload`, constructs a transaction targeting the specified contract on the destination chain, and submits it with the provided gas limit. -### Processing the Callback +### Callback Identity -When the `Callback` event is emitted, the Reactive Network detects it and processes the `payload`, which encodes the transaction details in a specific format. The Reactive Network then submits a transaction to the specified contract on the destination chain, using the provided `chain_id` and `gas_limit`. +When a Reactive contract constructs a callback payload, the first argument must be reserved for the RVM ID. Developers pass `address(0)` as a placeholder in this slot, and Reactive Network automatically overwrites the first 160 bits with the deployer's address before the callback reaches the destination chain. This means callbacks always carry an authenticated origin that can't be forged by the contract itself. -### Important Note on Authorization +The callback must include at least one argument, omitting the first slot entirely will cause the call to fail, since the system has no location to inject the RVM ID. Destination contracts can rely on this first argument to identify which ReactVM originated the callback. -For security and authorization purposes, the Reactive Network automatically replaces the first 160 bits of the call arguments within the `payload` with the RVM ID (equivalent to the ReactVM address) of the calling reactive contract. This RVM ID is identical to the contract deployer's address. As a result, the first argument in your callback will always be the ReactVM address (of type `address`), regardless of the variable name you use in your Solidity code. - -### Encoding and Emitting the Callback Event - -To initiate actions on a destination chain, you can encode the transaction details into the `payload` and emit the `Callback` event. For example, in the Uniswap Stop Order Demo, this process is used to trigger token sales through the destination chain contract: +Example from [Uniswap V2 Stop Order Demo](https://github.com/Reactive-Network/reactive-smart-contract-demos/blob/f1f85ab2a0a8f917b9b37a57c00be2ffc8ad5ad4/src/demos/uniswap-v2-stop-order/UniswapDemoStopOrderReactive.sol#L107): ```solidity bytes memory payload = abi.encodeWithSignature( @@ -166,16 +129,10 @@ bytes memory payload = abi.encodeWithSignature( emit Callback(chain_id, stop_order, CALLBACK_GAS_LIMIT, payload); ``` -## Conclusion - -In this lesson, we've explored the fundamentals of events and callbacks in Ethereum and their application in Reactive Contracts. Key takeaways include: - -- **Understanding Events:** Events allow smart contracts to log information and interact with external applications, providing a powerful way to respond to on-chain activities without directly altering the blockchain state. - -- **Reactive Contracts and the react() Method:** RCs use the `react()` method to autonomously process incoming events based on specified criteria, enabling real-time, decentralized, and responsive contract behavior. +## About This Course -- **Callbacks for Cross-Chain Transactions:** RCs can initiate actions on different blockchains using callbacks, broadening their functionality beyond single-chain constraints and facilitating more complex decentralized applications. +This course is designed to give you both the theory and the hands-on experience to start building with Reactive contracts. It includes detailed lectures, code examples on GitHub, and video workshops covering everything from basic concepts to real-world deployments. -- **Secure and Controlled Execution:** The ReactVM environment ensures that RCs operate securely by restricting interactions to contracts deployed by the same deployer, maintaining a controlled execution space. +Whether you want to understand how Reactive contracts work under the hood or jump straight into building, the course adapts to either path. Explore the [use cases](../use-cases/index.md) if you want to see what's possible, or start from Module 1 to build up from the fundamentals. -The concepts from this lesson are shown in the [Basic Demo](../use-cases/use-case-1.md) use case. Feel free to explore it and join our [Telegram](https://t.me/reactivedevs) group for additional guidance. +Join the [Telegram](https://t.me/reactivedevs) community if you have questions or want to connect with other developers working with Reactive contracts. \ No newline at end of file diff --git a/docs/education/module-1/how-oracles-work.md b/docs/education/module-1/how-oracles-work.md index 63e4f15..4f6ed4d 100644 --- a/docs/education/module-1/how-oracles-work.md +++ b/docs/education/module-1/how-oracles-work.md @@ -1,7 +1,7 @@ --- title: "Lesson 5: How Oracles Work" sidebar_position: 5 -description: Discover the power of oracles in Reactive Contracts (RCs) and explore their role in integrating real-world data with blockchain applications. +description: How oracles bring off-chain data onto the blockchain and why they matter for Reactive Contracts. Covers the oracle problem, multisig security, Chainlink integration, and how Reactive Contracts can respond to oracle events in real time. slug: how-oracles-work --- @@ -9,42 +9,42 @@ slug: how-oracles-work ## Overview -Reactive Contracts are adept at monitoring on-chain events and executing subsequent on-chain actions in response. Yet within the smart contract ecosystem, a distinct category exists specifically for importing off-chain data onto the blockchain. These are known as oracles. Among the myriad events to which Reactive Contracts can respond, those emitted by oracles hold significant importance. This article delves deeper into the concept of oracles, setting the stage for a clearer comprehension of the upcoming use case we'll explore. By unpacking the mechanisms and implications of oracles within the blockchain framework, we aim to equip you with the knowledge needed to fully grasp the potential and utility of Reactive Contracts in interacting with real-world data. +Smart contracts can only work with data that already exists on the blockchain. They can't reach out to an API, check a price feed, or read a weather report on their own. Oracles solve this by bringing off-chain data on-chain, where smart contracts can use it. -By the end of this lesson, you will learn to: +This matters for Reactive contracts because oracles emit events when they deliver new data. A Reactive contract can subscribe to those events and act on them automatically, responding to price changes, real-world outcomes, or any other external data the moment it arrives on-chain. -* Understand the role of oracles in bridging the gap between blockchain and real-world data. -* Address the oracle problem by exploring how oracles bring off-chain data onto the blockchain. -* Implement and integrate oracles within smart contracts, using examples like Chainlink to fetch external data. -* Recognize the advantages of combining Reactive Contracts with oracles for real-time interaction with on-chain and off-chain events. +By the end of this lesson, you'll understand: -## What Oracles Do +- What oracles do and why smart contracts need them +- How the oracle problem is addressed through decentralization and multisig protocols +- How to integrate oracle data into a smart contract using Chainlink +- Why combining oracles with Reactive contracts enables real-time responses to off-chain events -In the realm of blockchain and smart contracts, the necessity to interact with the real world presents a unique challenge. Smart contracts operate in a deterministic environment, where every operation must be verifiable and repeatable. However, to unlock the full potential of smart contracts, there's often a need to access data from the outside world — be it price feeds, weather reports, or other off-chain information. This requirement introduces the oracle problem: how to fetch off-chain data onto the blockchain without sacrificing the core principles of decentralization and trustlessness. +## What Oracles Do -## Addressing the Oracle Problem +Smart contracts run in a deterministic environment where every operation must be verifiable and repeatable. But many useful applications need data from outside the blockchain: price feeds, sports results, IoT sensor readings, public records. The challenge is getting that data on-chain without breaking the decentralization and trustlessness that make smart contracts valuable in the first place. This is known as the oracle problem. -The oracle problem is tackled through entities known as oracles, which serve as bridges between the blockchain (on-chain) and the external world (off-chain). Oracles fetch data from a plethora of external sources to feed into the blockchain. This data could stem from APIs of financial marketplaces for price feeds, government databases for public records, or IoT devices for real-world physical data. The crux of an oracle's utility lies in its ability to validate and relay this data to smart contracts in a trust-minimized way. +## How Oracles Address This -The question of who signs the transactions for oracles to input data onto the blockchain brings us to the mechanism ensuring the data's integrity and trustworthiness. Typically, transactions are signed using the private keys of the oracle service provider. +Oracles act as bridges between the blockchain and the external world. They pull data from outside sources (financial APIs, government databases, IoT devices) validate it, and submit it to smart contracts on-chain. -To bolster security and mitigate the risks of failure or malicious manipulation, many decentralized oracle networks employ multisig protocols. Multisig requires a predefined number of signatures out of a set of participants to authorize a transaction, ensuring that no single entity can unilaterally submit data to the blockchain. This method adds a layer of decentralization and security to the process, aligning with the trustless nature of blockchain systems. +The natural question is: who signs these transactions? Typically, the oracle service provider holds the private keys used to submit data. To prevent any single entity from manipulating the data or becoming a point of failure, many decentralized oracle networks use multisig protocols. Multisig requires a set number of participants to sign off on each data submission before it's accepted on-chain. This adds a layer of decentralization to the process and aligns with the trustless design of blockchain systems. -Some of the popular oracle providers are Chainlink and Band Protocol. These platforms aggregate data from multiple sources, ensuring data integrity and reducing the risk of manipulation. +Chainlink and Band Protocol are two of the most widely used oracle providers. Both aggregate data from multiple independent sources to reduce the risk of manipulation and improve data integrity. -## Practical Applications and Examples +## Practical Applications -Oracles unlock a myriad of use cases for smart contracts, allowing them to react to real-world events and data. Some notable applications include: +Oracles open up use cases that wouldn't be possible with on-chain data alone: -* DeFi Platforms: Utilizing price feed oracles to manage lending rates, liquidations, and asset swaps. +**DeFi platforms** use price feed oracles to manage lending rates, trigger liquidations, and calculate asset swaps. Without reliable, up-to-date pricing, most DeFi protocols couldn't function. -* Insurance: Triggering payouts based on verifiable events, like natural disasters, reported by trusted oracles. +**Insurance** contracts can trigger payouts based on verifiable real-world events (natural disasters or flight delays) reported by trusted oracle networks. -* Online Betting: Smart contracts provide great tech solutions for trustless online betting, and oracles feed the data about the outcomes of sporting events to such systems. +**Prediction markets and betting** platforms use oracles to feed the outcomes of sporting events, elections, or other real-world results into smart contracts that handle trustless payouts. -## Code Example: Using Chainlink Oracles +## Code Example: Chainlink Price Feed -Here's a simple example of how a smart contract can use Chainlink to fetch a USD/ETH price feed: +Here's a basic contract that fetches the latest ETH/USD price from Chainlink's oracle network: ```solidity pragma solidity ^0.8.0; @@ -80,28 +80,22 @@ contract PriceConsumerV3 { } ``` -This contract demonstrates fetching the latest ETH/USD price using Chainlink's decentralized oracle network. It illustrates how smart contracts can securely and reliably access off-chain data. - -However, as you may have observed, the smart contract can only request data through the getLatestPrice() function when it's explicitly called. To ensure your contract's data remains current, you should periodically invoke the function that queries the oracle. This challenge isn't insurmountable; one could simply update the price each time someone interacts with the contract, basing this interaction on the most recent price data. Yet this approach falls short of enabling your system to respond to price changes — or other oracle-generated events — in real time. - -In the Ethereum ecosystem, while one smart contract can indeed call another, such calls must initially be triggered by an Externally Owned Account (EOA) address. An EOA is an Ethereum address controlled directly by the private key's owner, unlike smart contract addresses, which are governed by contract code. Consequently, each transaction is initiated and signed by a specific EOA, restricting the capacity for smart contracts to operate in real time. This limitation underscores the distinctive advantage of Reactive Contracts. - -## Why We Need Reactive Contracts +This works, but notice the limitation: `getLatestPrice()` only runs when someone calls it. The contract can't watch for price changes on its own. You could work around this by updating the price every time someone interacts with the contract, but that still doesn't let the system respond to changes in real time. -Our exploration has previously touched upon the Inversion of Control principle, a defining characteristic of Reactive Contracts. Here, it's worth emphasizing again: Reactive Contracts stand out because they react not just to direct user transactions but to events across various EVM chains. Following these events, they execute on-chain actions, potentially on the same or different chains. +This is a fundamental constraint of traditional smart contracts. One contract can call another, but every chain of calls must originate from an externally owned account (EOA), an address controlled by someone's private key. Nothing happens unless a person or bot initiates a transaction. -This brings us to the significance of oracles in our discussion: by integrating oracles with Reactive Contracts, we unlock the potential to respond to off-chain events — once brought on-chain by oracles — with predefined on-chain actions as articulated in our Reactive Contracts. This synergy between oracles and Reactive Contracts enables a dynamic, responsive system capable of real-time interaction with both the digital and physical worlds. This broadens the scope and utility of blockchain technology beyond its current constraints. +## Where Reactive Contracts Change This -## Conclusion +This is where the Inversion of Control principle from earlier lessons becomes directly relevant. Reactive contracts don't wait for someone to call them. They subscribe to events, including events emitted by oracles, and execute automatically when those events occur. -In this article, we’ve talked about the role of oracles within the context of Reactive Contracts (RCs), highlighting their significance in bridging the gap between on-chain and off-chain data. Key takeaways include: +By combining oracles with Reactive contracts, you get a system that can respond to off-chain events the moment they're recorded on-chain. An oracle delivers a new price, a game result, or a sensor reading. It emits an event. A Reactive contract picks it up and executes whatever logic you've defined (on the same chain or across different chains) without any manual trigger. -- **Oracle Functionality:** Oracles are essential for importing real-world data onto the blockchain, enabling smart contracts to interact with external information such as price feeds, weather reports, and more. +Oracles solve the data problem (getting real-world information on-chain) whereas Reactive Contracts solve the execution problem (acting on that information automatically). Together they enable applications that respond to the real world in real time, fully on-chain. -- **Addressing the Oracle Problem:** The oracle problem is mitigated through decentralized oracle networks that ensure data integrity and minimize trust issues. Multisig protocols and reputable providers like Chainlink and Band Protocol enhance security and reliability. +## About This Course -- **Practical Applications:** Oracles facilitate various use cases, including decentralized finance (DeFi), insurance, and online betting, by providing real-time data to smart contracts and enabling automated, trustless interactions. +This course is designed to give you both the theory and the hands-on experience to start building with Reactive contracts. It includes detailed lectures, code examples on GitHub, and video workshops covering everything from basic concepts to real-world deployments. -- **Integration with Reactive Contracts:** The synergy between oracles and RCs allows for dynamic, real-time responses to off-chain events. This integration leverages the strengths of both technologies to enhance the functionality and reach of blockchain applications. +Whether you want to understand how Reactive contracts work under the hood or jump straight into building, the course adapts to either path. Explore the [use cases](../use-cases/index.md) if you want to see what's possible, or start from Module 1 to build up from the fundamentals. -For practical applications and further insights, explore our [use cases](../use-cases/index.md) and join our [Telegram](https://t.me/reactivedevs) group to engage with the community. \ No newline at end of file +Join the [Telegram](https://t.me/reactivedevs) community if you have questions or want to connect with other developers working with Reactive contracts. \ No newline at end of file diff --git a/docs/education/module-1/index.md b/docs/education/module-1/index.md index 227783f..254c076 100644 --- a/docs/education/module-1/index.md +++ b/docs/education/module-1/index.md @@ -1,7 +1,7 @@ --- title: "Module 1: Beginner — Foundations of Reactive Contracts" sidebar_position: 1 -description: Learn the basics of RCs, including their reactive nature, state management, EVM events, and oracles. Ideal for beginners looking to understand and apply RCs in blockchain projects. +description: Introduction to Reactive Contracts covering how they respond to on-chain events, EVM event handling and callbacks, the ReactVM dual-state environment, subscriptions, and how oracles connect blockchain with off-chain data. slug: /education/module-1 --- @@ -9,24 +9,24 @@ slug: /education/module-1 # Overview -Welcome to Module 1: Beginner — Foundations of Reactive Contracts (RCs)! This module introduces the core concepts and functionalities of RCs, providing a foundation for applying them in blockchain projects. +Module 1 covers the core concepts behind Reactive contracts: how they work, what makes them different from regular smart contracts, and the infrastructure that supports them. By the end of this module, you'll understand how Reactive contracts detect events, execute responses, and interact with off-chain data. [Lesson 1: Reactive Contracts](./reactive-contracts.md) -Explore the mechanisms of RCs, focusing on their reactive nature and Inversion of Control. Learn through use cases such as data collection with oracles and executing stop orders on decentralized exchanges. +How Reactive contracts work in practice, focusing on their reactive nature. Walks through real use cases like data collection with oracles and executing stop orders on decentralized exchanges. [Lesson 2: How Events and Callbacks Work](./how-events-work.md) -Understand how EVM events and callbacks enable interaction between smart contracts and external systems. Includes a practical example of Chainlink's price oracle integration. +How EVM events and callbacks enable communication between smart contracts and external systems. Includes a practical example using Chainlink's price oracle integration. [Lesson 3: ReactVM and Reactive Network As a Dual-State Environment](./react-vm.md) -Examine the dual-state environment of RCs within the Reactive Network and ReactVM. Learn about state management and transaction execution across these domains. +Reactive Network runs on a dual-state environment: ReactVM for Reactive logic and Reactive Network (RNK) for on-chain execution. This lesson explains how state management and transactions work across both. [Lesson 4: How Subscriptions Work](./subscriptions.md) -Learn about setting up and managing subscriptions in RCs to streamline event handling and automate contract execution. +Subscriptions are how Reactive contracts listen for specific on-chain events. This lesson covers setting them up, managing them, and using them to automate contract execution. [Lesson 5: How Oracles Work](./how-oracles-work.md) -Discover the role of oracles in connecting blockchain with off-chain data. Explore multisig protocols and practical applications in DeFi, insurance, and online betting. +Oracles bridge the gap between blockchain and real-world data. This lesson explains how they work, covers multisig protocols for securing oracle data, and walks through applications in DeFi, insurance, and prediction markets. \ No newline at end of file diff --git a/docs/education/module-1/react-vm.md b/docs/education/module-1/react-vm.md index 3dab928..4aa2029 100644 --- a/docs/education/module-1/react-vm.md +++ b/docs/education/module-1/react-vm.md @@ -1,48 +1,47 @@ --- title: "Lesson 3: ReactVM and Reactive Network As a Dual-State Environment" sidebar_position: 3 -description: Understand the dual-state environment of Reactive Contracts. Learn to manage data, identify execution contexts, and handle transactions in both Reactive Network and ReactVM for efficient RC development. +description: Learn how Reactive contracts operate across two separate states — one on Reactive Network and one in a private ReactVM instance. Covers execution context detection, managing dual variable sets, and how transactions flow in each environment. slug: react-vm --- -# Lesson 3: ReactVM and Reactive Network As a Dual-State Environment +# Lesson 3: ReactVM and the Dual-State Environment ## Overview -In [Reactive Contracts](./reactive-contracts), we discuss one of the basic concepts of reactive contracts (RCs) — Inversion of Control, and how events and callbacks work in RCs. This article focuses on another crucial property of RCs: the fact they exist in two instances with separate states in the Reactive Network and ReactVM. Understanding this idea is necessary for successful reactive contract development. +Previous lessons covered how Reactive contracts respond to events and trigger actions through callbacks. This lesson focuses on something that's easy to overlook but important to understand: Reactive's dual-state environment. -By the end of this lesson, you will learn to: +This dual-state design affects how you write your contracts, which variables belong to which context, and how transactions are initiated. Getting this right is necessary for building Reactive contracts that work as expected. -* Distinguish both environments where a reactive contract is executed. -* Identify the current environment. -* Manage data with two separate states. -* Understand the types of transactions RCs operate with. +By the end of this lesson, you'll understand: -## Differences Between the Reactive Network and ReactVM +- Why Reactive contracts have two instances and what each one does +- How to detect which environment your code is running in +- How to manage variables across both states +- How transactions are initiated and processed in each environment -Each Reactive Contract has two instances — one on the Reactive Network and the other in its separate ReactVM. It is important to note that both instances are physically stored and executed on each network node. Parallelizing RCs is an architectural decision made to ensure high performance even with big numbers of events. We will talk more about that in one of our next articles. +## Reactive Network vs. ReactVM -![Reactive Network | React Vm ](./img/reactvm.jpg) +Every deployed Reactive contract has two instances: one on Reactive Network and one in a dedicated ReactVM. Both instances are physically stored and executed on each network node. This separation is an architectural decision made to ensure high performance even with large volumes of events. -The Reactive Network operates as a typical EVM blockchain with the addition of system contracts that allow subscribing to and unsubscribing from origin chain events on Ethereum, BNB, Polygon, or Optimism. Each deployer address has a dedicated ReactVM. +![Reactive Network | ReactVM](./img/reactvm.jpg) -ReactVM is a restricted virtual machine designed to process events in isolation. Contracts deployed from one address are executed in one ReactVM. They can interact with each other but not with other contracts on the Reactive Network. +**Reactive Network** operates as a standard EVM blockchain with additional system contracts that handle subscribing and unsubscribing to events on origin chains like Ethereum, BNB, Polygon, or Optimism. Each deployer address has its own dedicated ReactVM. -Contracts within a single ReactVM can interact with the external world in two ways, both through the Reactive Network: +**ReactVM** is a restricted virtual machine designed to process events in isolation. All contracts deployed from the same address run in the same ReactVM. They can interact with each other but not with other contracts on Reactive Network. -* They react to specified events to which they are subscribed and are executed when these events occur. +Contracts within a ReactVM interact with the outside world in two ways, both through Reactive Network: -* Based on the execution of the code with the inputs from events, the ReactVM sends requests to the Reactive Network for callbacks to destination chains to perform the resulting on-chain actions. +- They receive events they've subscribed to and execute when those events occur. +- Based on the results of that execution, they send callback requests to Reactive Network, which submits the corresponding transactions on destination chains. -For each RC deployed, there are two instances of it with separate states but the same code. Each method is expected to be executed in one or both environments and to interact with one or both states. This leads to the question of how we identify, within the code, which state we are currently working with. +Since both instances share the same code but maintain separate states, you need a way to control which logic runs where. That starts with detecting the current execution context. -### Identifying the Execution Context +### Detecting the Execution Context -The execution context determines whether the contract is running on the Reactive Network or within a ReactVM instance. This distinction is crucial for controlling which functions can be called in which environment. Implement [AbstractReactive](https://github.com/Reactive-Network/reactive-lib/blob/main/src/abstract-base/AbstractReactive.sol) in your project to get all the necessary functionality. +The execution context tells your contract whether it's running on Reactive Network or inside a ReactVM instance. This matters because different functions should only run in one environment or the other. Implement [AbstractReactive](https://github.com/Reactive-Network/reactive-lib/blob/main/src/abstract-base/AbstractReactive.sol) to get this functionality built in. -#### How Detection Works - -Instead of attempting to invoke the system contract in the constructor, the new code uses the function `detectVm()` to inspect the code size at the system contract’s address. The `0x0000000000000000000000000000000000fffFfF` address only has deployed code on the Reactive Network. If there is code at this address, we conclude that we are on the Reactive Network; if not, we are within a ReactVM instance. +Detection works by checking whether the system contract exists at a known address. The address `0x0000000000000000000000000000000000fffFfF` only has deployed code on Reactive Network. If there's code at that address, you're on Reactive Network. If not, you're inside a ReactVM. ```solidity function detectVm() internal { @@ -53,13 +52,11 @@ function detectVm() internal { } ``` -**Assembly Check**: An inline assembly snippet checks the size of the contract code at the system contract’s address. - -**Setting the vm Flag**: If `size == 0`, there is no code at that address. This indicates that we are running within a ReactVM instance, so `vm` is set to `true`. Otherwise, if `size > 0`, it indicates the presence of the system contract, confirming that we are on the Reactive Network, so `vm` remains `false`. +If `size == 0`, there's no system contract so you're in a ReactVM instance, and `vm` is set to `true`. If `size > 0`, the system contract is present, confirming you're on Reactive Network, and `vm` stays `false`. -#### Enforcing Execution Context +### Enforcing the Right Context -We use modifiers to ensure that each function can only be called in its intended environment. +With the `vm` flag set, you can use modifiers to restrict functions to the correct environment: ```solidity modifier rnOnly() { @@ -73,36 +70,19 @@ modifier vmOnly() { } ``` -**rnOnly()**: requires that `vm == false`, meaning the function can only run when the contract is deployed to the Reactive Network. - -**vmOnly()**: requires that `vm == true`, meaning the function can only run within a ReactVM instance. - -### Managing Dual Variable Sets for Each State - -In Reactive architecture, each deployed contract can run in two operational states: - -**Reactive Network State** +`rnOnly()` ensures a function can only run on Reactive Network. Use it for subscription management, admin functions, and anything that interacts with the system contract. -- Interacts directly with system contracts. -- Subscribes to events using `service.subscribe(...)`. -- Uses variables and methods required to register and manage event subscriptions. +`vmOnly()` ensures a function only runs inside the ReactVM. Use it for event processing and callback logic. -**ReactVM State** +## Managing Variables Across Both States -- Contains the business logic to react to subscribed events. -- Uses variables and methods that execute upon receiving an event. +Since each instance maintains its own state, you effectively work with two sets of variables: -To accommodate these states, two conceptual sets of variables are maintained — one set in the base (network-facing) contract context and another set in the ReactVM context. In this new example, the "Reactive Network" variables are inherited from our `AbstractReactive` contract, while the ReactVM variables are declared within a reactive contract itself. +**Reactive Network state** handles subscription management. If your contract inherits from `AbstractReactive`, you get access to `service` (an `ISubscriptionService` for subscribing to events), the `vm` flag, and utility methods like `service.subscribe(...)`. -### Reactive Network Variables +**ReactVM state** holds the business logic variables. Everything your contract needs to process events and decide when to act. -If a reactive contract inherits from `AbstractReactive`, the following variables and methods are available behind the scenes: - -- `service` (`ISubscriptionService`) for subscribing to events. -- `vm` (bool) that indicates whether the execution is happening on the ReactVM or in the Reactive Network context. -- Additional inherited utility methods (e.g., `service.subscribe(...)`). - -In the constructor of the [Uniswap Stop Order reactive contract](https://github.com/Reactive-Network/reactive-smart-contract-demos/blob/main/src/demos/uniswap-v2-stop-order/UniswapDemoStopOrderReactive.sol), you can notice that `if (!vm)` checks if we are running in the Reactive Network state. If so, the contract registers to receive events from `pair` and `stop_order`. Once subscribed, those events will later trigger our `react()` logic only when we are in the ReactVM state. +Here's how this looks in practice using the [Uniswap Stop Order](https://github.com/Reactive-Network/reactive-smart-contract-demos/blob/main/src/demos/uniswap-v2-stop-order/UniswapDemoStopOrderReactive.sol) contract. The constructor sets up both states: ```solidity // State specific to ReactVM instance of the contract. @@ -154,25 +134,11 @@ constructor( } ``` -### ReactVM Variables - -Within the [Uniswap Stop Order reactive contract](https://github.com/Reactive-Network/reactive-smart-contract-demos/blob/main/src/demos/uniswap-v2-stop-order/UniswapDemoStopOrderReactive.sol), the following variables and methods are used specifically after events are received: - -```solidity -bool private triggered; -bool private done; -address private pair; -address private stop_order; -address private client; -bool private token0; -uint256 private coefficient; -uint256 private threshold; -``` +The `if (!vm)` check runs the subscription logic only on Reactive Network. The ReactVM instance skips it entirely and uses the same variables for its own event processing logic. -These variables handle the logic in the `react()` function: +The `react()` function, marked `vmOnly`, handles what happens when events arrive: ```solidity -// Methods specific to ReactVM instance of the contract. function react(LogRecord calldata log) external vmOnly { assert(!done); @@ -206,50 +172,37 @@ function react(LogRecord calldata log) external vmOnly { } ``` -- `triggered` prevents multiple callbacks once the threshold condition is satisfied. -- `done` signals that the final stop has occurred. -- `pair`, `stop_order`, and `client` reference external contracts and user data. -- `token0`, `coefficient`, and `threshold` define the math around when to trigger a stop. +The key variables here: `triggered` prevents duplicate callbacks once the threshold condition is met, `done` signals that the stop order has completed, and `pair`, `stop_order`, `client`, `token0`, `coefficient`, and `threshold` define the conditions for when and how to act. All of this logic runs exclusively in the ReactVM. -The actual logic (checking liquidity reserves and emitting callbacks) is local to ReactVM. Since `react()` is labeled `vmOnly`, it is invoked by the underlying system **only** in the ReactVM context upon matching event logs. +## How Transactions Work in Each Environment -## Transaction Execution - -When working with a Reactive Contract (RC), there are two primary environments where transactions occur: the Reactive Network and the ReactVM. Each environment has different rules for initiating and processing transactions, as detailed below. The code is taken from [AbstractPausableReactive](https://github.com/Reactive-Network/reactive-lib/blob/main/src/abstract-base/AbstractPausableReactive.sol). +Understanding which environment handles which transactions is important for reasoning about your contract's behavior. Code examples below are from [AbstractPausableReactive](https://github.com/Reactive-Network/reactive-lib/blob/main/src/abstract-base/AbstractPausableReactive.sol). ### Reactive Network Transactions -Transactions on the Reactive Network can be initiated in two ways: directly by a user or triggered by an event on the origin chain. - -#### User-Initiated Transactions +Transactions on Reactive Network are initiated in two ways: -Users can invoke methods on the Reactive Network’s instance of an RC to perform administrative functions or update contract state. For instance, pausing event subscriptions is done by calling the `pause()` function: +**User-initiated transactions** let you call administrative functions directly. For example, pausing a contract's event subscriptions: ```solidity function pause() external rnOnly onlyOwner { - require(!paused, 'Already paused'); - Subscription[] memory subscriptions = getPausableSubscriptions(); - for (uint256 ix = 0; ix != subscriptions.length; ++ix) { - service.unsubscribe( - subscriptions[ix].chain_id, - subscriptions[ix]._contract, - subscriptions[ix].topic_0, - subscriptions[ix].topic_1, - subscriptions[ix].topic_2, - subscriptions[ix].topic_3 - ); - } - paused = true; + require(!paused, 'Already paused'); + Subscription[] memory subscriptions = getPausableSubscriptions(); + for (uint256 ix = 0; ix != subscriptions.length; ++ix) { + service.unsubscribe( + subscriptions[ix].chain_id, + subscriptions[ix]._contract, + subscriptions[ix].topic_0, + subscriptions[ix].topic_1, + subscriptions[ix].topic_2, + subscriptions[ix].topic_3 + ); + } + paused = true; } ``` -- `rnOnly` ensures that only the Reactive Network can call this function. -- `onlyOwner` limits the call to the contract owner. -- `service.unsubscribe()` removes the contract from listening to specific events (defined by `chain_id`, `topic_0`, etc.). - -This `pause()` function prevents the RC from reacting to events by unsubscribing from them, effectively stopping further event-driven transactions until it is resumed. - -The corresponding `resume()` function re-subscribes to those same events so that the RC can continue responding when new events are emitted: +The `rnOnly` modifier ensures this only runs on Reactive Network, and `onlyOwner` restricts it to the contract owner. Calling `pause()` unsubscribes from all events, effectively stopping the contract from reacting until `resume()` is called: ```solidity function resume() external rnOnly onlyOwner { @@ -269,38 +222,24 @@ function resume() external rnOnly onlyOwner { } ``` -#### Event-Triggered Transactions - -Even if a user does not directly initiate a transaction, the Reactive Network monitors events on the origin chain. When an event of interest is emitted, the Reactive Network dispatches it to all active subscribers, typically specialized ReactVM instances. This dispatch triggers further action or state changes in the subscribers. +**Event-triggered dispatch** happens automatically. When an event of interest is emitted on an origin chain, Reactive detects it and forwards the event data to all matching ReactVM subscribers. ### ReactVM Transactions -Within the ReactVM, transactions can't be called directly by users. Instead, they are triggered automatically when the Reactive Network forwards relevant events from the origin chain: - -- Event emitted on origin chain -- Reactive Network dispatches event -- ReactVM receives and processes Event - -When an RC running in the ReactVM receives an event, it typically calls its core reaction function `react()` to handle the event. The `react()` function contains the business logic for: - -- Updating internal state based on the received event. -- Emitting callbacks to destination chains, which can then trigger transactions on those chains. - -Thus, any callback or subsequent transaction to another chain is automatically initiated by the `ReactVM` in response to the received event, rather than manually triggered by a user. - -We will consider other examples of `react()` functions for different use cases closely in our next lessons. - -## Conclusion +Users can't call functions inside the ReactVM directly. All execution there is triggered by events forwarded from Reactive Network: -In this lesson, we've explored how Reactive Contracts (RCs) function within two distinct environments: the Reactive Network and the ReactVM. Understanding the dual-state nature of RCs is crucial for their effective development. Key takeaways include: +1. An event is emitted on an origin chain +2. Reactive Network matches it against active subscriptions and dispatches it +3. The ReactVM receives the event and calls `react()` -- **Dual-State Environments:** RCs exist in two instances, each with separate states but the same code — one in the Reactive Network and one in the ReactVM. This setup allows for parallel processing and high performance. +From there, `react()` can update internal state and emit callbacks that trigger transactions on destination chains. Everything that happens in the ReactVM is automatic, no manual intervention required. -- **Identifying Execution Context:** The environment in which the contract is executing is identified using a boolean variable (`vm`). This allows for precise control over which code and state are accessed, ensuring the correct execution flow. +Further examples of `react()` implementations for different use cases are covered in the upcoming lessons. -- **Managing Separate States:** RCs maintain separate sets of variables for the Reactive Network and ReactVM, which are used according to the environment in which the contract is executed. This helps in maintaining clarity and avoiding conflicts between the two states. +## About This Course -- **Transaction Types:** The Reactive Network handles transactions initiated by users or triggered by events on the origin chain, while the ReactVM processes events and executes the `react()` function, defining the reaction logic and initiating cross-chain callbacks. +This course is designed to give you both the theory and the hands-on experience to start building with Reactive contracts. It includes detailed lectures, code examples on GitHub, and video workshops covering everything from basic concepts to real-world deployments. -Explore more practical applications in our [use cases](../use-cases/index.md) and join our [Telegram](https://t.me/reactivedevs) group for additional guidance. +Whether you want to understand how Reactive contracts work under the hood or jump straight into building, the course adapts to either path. Explore the [use cases](../use-cases/index.md) if you want to see what's possible, or start from Module 1 to build up from the fundamentals. +Join the [Telegram](https://t.me/reactivedevs) community if you have questions or want to connect with other developers working with Reactive contracts. diff --git a/docs/education/module-1/reactive-contracts.md b/docs/education/module-1/reactive-contracts.md index 4b149b2..168e91f 100644 --- a/docs/education/module-1/reactive-contracts.md +++ b/docs/education/module-1/reactive-contracts.md @@ -1,7 +1,7 @@ --- title: "Lesson 1: Reactive Contracts" sidebar_position: 1 -description: Learn how RCs autonomously respond to blockchain events, contrasting traditional smart contracts. Understand Inversion of Control (IoC) and discover practical use cases. +description: Learn how Reactive Contracts differ from traditional smart contracts and practical use cases including oracle data aggregation, Uniswap stop orders, DEX arbitrage, and cross-chain pool rebalancing. slug: reactive-contracts --- @@ -9,77 +9,68 @@ slug: reactive-contracts ## Overview -In the [introduction article](../introduction/reactive-contracts), we discuss the basics of Reactive Contracts (RCs), what they are, and why we need them. Let's dive deeper into the technical concepts of RCs with some examples to illustrate those concepts. +The [introduction](../introduction/reactive-contracts) covered what Reactive contracts are and why they exist. This lesson goes deeper into how they work: what happens inside a Reactive contract when an event is detected, how control flow differs from traditional smart contracts, and where this approach is most useful. -By the end of this lesson, you will learn to: +By the end of this lesson, you'll understand: -* Understand the key differences between Reactive Contracts (RCs) and traditional smart contracts. -* Grasp the concept of Inversion of Control and its significance in RCs. -* Recognize how RCs autonomously monitor and react to blockchain events. -* Explore various practical use cases where RCs can be applied, such as data collection from oracles, UniSwap stop orders, DEX arbitrage, and pools rebalancing. +- How Reactive contracts differ from traditional smart contracts in practice +- What happens step by step when a Reactive contract detects an event +- Where Reactive contracts are a good fit, from oracle data aggregation to automated trading -## How RCs Differ from Traditional Smart Contracts +## How Reactive Contracts Differ from Traditional Smart Contracts -The main distinction between RCs and traditional smart contracts lies in reactivity. Traditional smart contracts are passive, only executing in response to direct EOA transactions. In contrast, RCs are reactive, continuously monitoring the blockchains for events of interest and autonomously executing predefined blockchain actions in response. +The core difference is reactivity. Traditional smart contracts are passive. They only run when someone sends them a transaction from an externally owned account (EOA). Between transactions, they do nothing. Reactive contracts (RCs) are the opposite: they continuously monitor blockchains for specific events and execute predefined actions when those events occur, without waiting for anyone to trigger them. -## Inversion of Control +With traditional smart contracts, control flows from the outside in. An external actor (a user or a bot) decides when to call a contract function. The contract itself has no say in when it runs. -A key concept in understanding RCs is the Inversion of Control (IoC). Traditional smart contracts operate under a direct control model, where the execution of their functions is initiated by external actors (EOA users or bots). RCs, however, invert this control by autonomously deciding when to execute based on the occurrence of predefined events. This IoC paradigm shifts how applications interact with the blockchain, enabling more dynamic and responsive systems. +Reactive contracts invert that. The contract itself defines which events it cares about and what to do when they happen. Execution is triggered by on-chain events, not by someone signing a transaction. ![Inversion of Control](./img/inversion-of-control.jpg) -Without a reactive contract, you would need to set up a separate entity — let's say a bot — to monitor the blockchains using existing, most likely centralized, data solutions. This bot would hold the private keys for the managed funds and initiate transactions on EVM chains from its EOA address. Though such systems prove to be useful, they might be suboptimal for some use cases and not suitable at all for others. +To see why this matters, consider the alternative. Without a Reactive contract, you'd need to set up a separate service (typically a bot) to monitor blockchains using centralized data providers. That bot holds private keys for the funds it manages and submits transactions from its own EOA address. It works, but it introduces a centralized point of control that can fail, be compromised, or go offline. -Inversion of Control allows us to avoid hosting additional entities that emulate humans signing transactions. If you have a predefined scenario outlining the sequence of transactions following on-chain events, you should be able to run this logic in a completely decentralized manner, as both your inputs and outputs remain on the blockchain. The Reactive Network gives smart contracts the property they’ve been missing from the start — the ability to be executed automatically, without a person (or a bot) signing a transaction, just based on other on-chain events. +Inversion of Control removes that dependency. If you have a predefined sequence of actions that should follow specific on-chain events, you can run that logic in a fully decentralized way: both the inputs (events) and outputs (transactions) live on-chain. Reactive Network gives smart contracts the property they've been missing from the start: the ability to execute automatically based on other on-chain events, without a person or bot signing anything. ## What Happens Inside a Reactive Contract -When creating a Reactive Contract, the first thing you need to specify is the chains, contracts, and events (topic 0) of interest. The RC will monitor these addresses for the specified events and initiate execution when one is detected. These events can include simple currency or token transfers, DEX swaps, loans, flash loans, votes, whale moves, or any other smart contract activity. +When you create a Reactive contract, the first thing you define is what to watch: which chains, which contract addresses, and which events (identified by topic 0). The contract monitors those addresses and begins execution when a matching event is detected. These events can be anything that happens on-chain: token transfers, DEX swaps, loans, flash loans, governance votes, large wallet movements, or any other smart contract activity. -Once an event of interest is detected, the Reactive Network automatically executes the logic you’ve implemented in your reactive contract. This may involve performing calculations based on the event data. RCs are stateful, meaning they have a state where values can be stored and updated. You can accumulate data over time in the state and then act when the combination of historical data and a new blockchain event meets the specified criteria. +Once an event is detected, Reactive Network automatically runs the logic you've implemented. This might involve calculations based on the event data. Reactive contracts are stateful, meaning they can store and update values over time. You can accumulate data across multiple events and only act when the combination of historical data and a new event meets your criteria. -As a result of the event, the RC updates its state, keeping it up to date, and can initiate transactions on EVM blockchains. The entire process runs trustlessly within the Reactive Network, ensuring automatic, fast, and reliable execution. +The result: the contract updates its state, and if your logic calls for it, initiates transactions on EVM blockchains. The entire process runs trustlessly within Reactive Network. ## Use Cases -Let's take a closer look at several use cases to illustrate the concepts we’ve just discussed. This educational course will be structured around those use cases because we see practical application as the best way to learn about this tech. +The best way to understand Reactive contracts is to see them applied to real problems. The examples below illustrate the concepts from this lesson, and the rest of the course is structured around building these out in practice. -### Collecting Data from Several Oracles +### Collecting Data from Multiple Oracles -For RCs to respond to a broader spectrum of events, including off-chain occurrences, they integrate with oracles. Oracles are third-party services that feed trusted external data into the blockchain. A simple example of such data includes exchange rates or sports event outcomes. RCs can use this data to make informed decisions and execute actions based on real-world events, extending their applicability beyond the blockchain. +Oracles are third-party services that feed external data into the blockchain: things like exchange rates, sports scores, or weather data. Reactive contracts can monitor oracle update events across multiple contracts and chains, combine the results (for example, by averaging price feeds from several sources), and act on the aggregated data. -Moreover, since an RC can monitor data from different smart contracts across various EVM-compatible blockchains, it can combine data from multiple oracles, resulting in more precise and decentralized information. In this case, the events that RCs will monitor are the updated events from the corresponding oracles. The calculations within the RC will involve combining data from different oracles (for example, by taking the average). The resulting action might be a trustless payout based on the outcome of a basketball game. +This is more reliable than relying on a single oracle, and it's fully decentralized. The Reactive contract handles all the monitoring and aggregation on its own. A practical example: a trustless payout triggered by the outcome of a sporting event, verified against multiple independent oracle feeds. ### Uniswap Stop Order -Another example of a reliable data source on the blockchain is a trading pool, such as a Uniswap pool. It can be even more dependable than oracles since it consists of pure on-chain data and does not rely on third parties. +A trading pool like Uniswap provides reliable on-chain price data. It's arguably more dependable than oracles since it's purely on-chain with no third-party dependency. -In this setup, a reactive contract would monitor the swaps in the specified UniSwap pool, calculating the liquidity and the exchange rate. When the exchange rate reaches a predetermined price, the reactive contract executes a swap transaction, thereby implementing a trustless stop order on top of the existing DEX. +A Reactive contract can monitor swaps in a specific Uniswap pool, track the exchange rate, and execute a swap transaction when the price hits a predetermined level. The result is a fully trustless stop order running on top of an existing DEX, with no bot or off-chain service involved. ### DEX Arbitrage -However, we can take the previous example further by implementing an actual arbitrage using RCs. Our reactive contract will monitor several different pools for price discrepancies and capitalize on them. Both one-chain and cross-chain approaches are possible. In the first case, we can use flash loans; in the second case, we will need liquidity on several chains, but we will gain access to more arbitrage opportunities. +Taking the previous example further, a Reactive contract can monitor multiple pools for price discrepancies and act on them automatically. Both single-chain and cross-chain approaches are possible. Single-chain arbitrage can use flash loans, while cross-chain arbitrage requires liquidity on multiple networks but opens up a wider range of opportunities. -The beauty of this solution is that it will be decentralized, unlike the traditional approach with bots. This allows for numerous improvements that we have yet to explore — hopefully, together with you. +The key advantage over the traditional approach is decentralization. There's no centralized bot racing other bots as the logic runs on-chain through Reactive Network. -### Pools Rebalancing +### Cross-Chain Pool Rebalancing -While all the previous use cases involve building RCs on top of existing traditional Smart Contracts, the next one requires initially developing a DApp that relies on RCs. If we design our system from the start, knowing that we can leverage the Reactive Network technology, we can build our Ethereum Smart Contracts utilizing the functionality of RCs. +The previous use cases build Reactive contracts on top of existing smart contracts. This one goes a step further: designing a system from the ground up to take advantage of reactive capabilities. -This approach allows us to potentially create liquidity pools that automatically rebalance across several exchanges. The RC will monitor liquidity on all chains of interest and rebalance them by adding or draining funds as needed. +If you know from the start that your application can leverage Reactive Network, you can build liquidity pools that automatically rebalance across multiple exchanges. The Reactive Contract monitors liquidity levels on all relevant chains and moves funds between them as needed, adding liquidity where it's low and draining where there's excess. -## Conclusion +## About This Course -After reading this lesson, you should have a solid understanding of the foundational concepts and potential applications of Reactive Contracts (RCs). Key takeaways include: +This course is designed to give you both the theory and the hands-on experience to start building with Reactive contracts. It includes detailed lectures, code examples on GitHub, and video workshops covering everything from basic concepts to real-world deployments. -- **Reactive vs. Traditional Contracts:** Unlike traditional smart contracts, RCs autonomously monitor blockchain events and execute actions without user intervention, providing a more dynamic and responsive system. +Whether you want to understand how Reactive contracts work under the hood or jump straight into building, the course adapts to either path. Explore the [use cases](../use-cases/index.md) if you want to see what's possible, or start from Module 1 to build up from the fundamentals. -- **Inversion of Control:** RCs invert the traditional execution model by allowing the contract itself to decide when to execute based on predefined events, eliminating the need for external triggers like bots or users. - -- **Decentralized Automation:** RCs enable fully decentralized operations, automating processes like data collection, DEX trading, and liquidity management without centralized intermediaries. - -- **Cross-Chain Interactions:** RCs can interact with multiple blockchains and sources, enabling sophisticated use cases like cross-chain arbitrage and multi-oracle data aggregation. - -- **Practical Applications:** RCs have diverse applications, including collecting data from oracles, implementing UniSwap stop orders, executing DEX arbitrage, and automatically rebalancing pools across exchanges. - -Explore more practical applications in our [use cases](../use-cases/index.md) and join our [Telegram](https://t.me/reactivedevs) group to contribute to the evolving world of Reactive Contracts. +Join the [Telegram](https://t.me/reactivedevs) community if you have questions or want to connect with other developers working with Reactive contracts. diff --git a/docs/education/module-1/subscriptions.md b/docs/education/module-1/subscriptions.md index 8b28141..ed3a6f6 100644 --- a/docs/education/module-1/subscriptions.md +++ b/docs/education/module-1/subscriptions.md @@ -1,7 +1,7 @@ --- title: "Lesson 4: How Subscriptions Work" sidebar_position: 4 -description: Understand how to implement subscriptions in the constructor of reactive contracts and how to manage subscriptions dynamically using callbacks to destination chains +description: Learn how to set up and manage event subscriptions in Reactive Contracts. Covers static subscriptions in the constructor, subscription criteria and wildcards, prohibited patterns, and dynamic subscription management through callbacks. slug: how-subscriptions-work --- @@ -9,23 +9,26 @@ slug: how-subscriptions-work ## Overview -In the previous lesson, we covered the basic differences between the Reactive Network and ReactVM. In this one, we will dive into subscriptions, a key feature that allows RCs to automatically respond to events emitted by other contracts. When these events occur, the subscribing contract can automatically execute predefined logic. +Subscriptions are how a Reactive contract tells Reactive Network which events it cares about. When a matching event is emitted on an origin chain, the subscribing contract's `react()` function is called automatically. -By the end of this article, you will learn to: +The previous lesson covered the dual-state environment and how to detect which context your code is running in. This lesson builds on that by showing how subscriptions are configured and what rules govern how they work. -* Configure and manage subscriptions both statically and dynamically. -* Handle subscription and unsubscription events within your smart contracts. -* Recognize the limitations and best practices for using subscriptions in Reactive Contracts. +By the end of this lesson, you'll understand: -## How to Implement Subscriptions +- How to set up subscriptions using the `ISubscriptionService` interface +- How wildcards and filtering criteria work +- What subscription patterns are prohibited +- How to manage subscriptions dynamically through callbacks -In reactive contracts, subscriptions are set up using the `subscribe` method from the Reactive Network’s system contract. Typically, this is done in the constructor to initialize subscriptions, though they can also be managed dynamically. We’ll discuss [dynamic subscriptions](./how-subscriptions-work#dynamic-subscriptions) closer to the end of this article. +## Setting Up Subscriptions -The reactive contract must also handle reverts due to deployments on both the Reactive Network, which has the system contract, and their deployer's private ReactVM, where the system contract is not present. +Subscriptions are created using the `subscribe` method from Reactive Network's system contract. Most commonly this happens in the constructor, but subscriptions can also be added or removed at runtime. We'll cover [dynamic subscriptions](#dynamic-subscriptions) later in this lesson. + +Since every Reactive contract is deployed to both Reactive Network and a private ReactVM (and the system contract only exists on Reactive Network), your subscription logic needs to be wrapped in the `if (!vm)` check covered in the previous lesson. ### ISubscriptionService Interface -The [ISubscriptionService](https://github.com/Reactive-Network/reactive-lib/blob/main/src/interfaces/ISubscriptionService.sol) interface serves as an event subscription service for reactive contracts that can use this service to subscribe to specific events based on certain criteria and receive notifications when those events occur. +The [ISubscriptionService](https://github.com/Reactive-Network/reactive-lib/blob/main/src/interfaces/ISubscriptionService.sol) interface provides two methods (`subscribe` and `unsubscribe`) that mirror each other: ```solidity pragma solidity >=0.8.0; @@ -53,16 +56,13 @@ interface ISubscriptionService is IPayable { } ``` -The parameters of both functions mirror each other: -- `chain_id`: A `uint256` representing the `EIP155` source chain ID for the event. -- `_contract`: The address of the origin chain contract that emitted the event. -- `topic_0`, `topic_1`, `topic_2`, `topic_3`: The topics of the event, which are `uint256` values. +Both functions take the same parameters: `chain_id` (the `EIP-155` origin chain ID), `_contract` (the address of the contract that emits the event), and `topic_0` through `topic_3` (the indexed event topics to filter on). -Unsubscribing is an expensive operation due to the necessity of searching and removing subscriptions. Duplicate or overlapping subscriptions are allowed, but clients must ensure idempotency. +Note that unsubscribing is an expensive operation because it requires searching for and removing the subscription. Duplicate subscriptions are allowed, but managing idempotency is your responsibility. ### IReactive Interface -The [IReactive](https://github.com/Reactive-Network/reactive-lib/blob/main/src/interfaces/IReactive.sol) interface defines a standard for reactive contracts that can receive and handle notifications about events matching their subscriptions. It extends the [IPayer](https://github.com/Reactive-Network/reactive-lib/blob/main/src/interfaces/IPayer.sol) interface, indicating that it includes payment-related functionalities. +The [IReactive](https://github.com/Reactive-Network/reactive-lib/blob/main/src/interfaces/IReactive.sol) interface defines a standard for Reactive contracts that can receive and handle notifications about events matching their subscriptions. It extends the [IPayer](https://github.com/Reactive-Network/reactive-lib/blob/main/src/interfaces/IPayer.sol) interface, indicating that it includes payment-related functionalities. ```solidity pragma solidity >=0.8.0; @@ -116,9 +116,9 @@ interface IReactive is IPayer { **react Function**: The main entry point for processing event notifications. - `log` (of type `LogRecord`): Contains event details. -### Constructor Subscribtion +### Subscribing in the Constructor -Here’s how you can subscribe in the constructor: +Here's a basic example of setting up a subscription when the contract is deployed: ```solidity // State specific to reactive network instance of the contract @@ -150,11 +150,11 @@ constructor( ### Subscription Criteria -When configuring subscriptions in reactive contracts, you should adhere to the following rules: +When configuring subscriptions, two rules apply: -- Wildcard Usage: Use `address(0)` to indicate filtering by any contract address, `uint256(0)` to indicate any chain ID, and `REACTIVE_IGNORE` for topics to filter by any topic. +**Wildcards.** Use `address(0)` to match any contract address, `uint256(0)` for any chain ID, and `REACTIVE_IGNORE` for any topic value. This lets you cast a wider net when you need to monitor a broad category of events. -- Concrete Values: At least one criterion must be a specific value to ensure meaningful subscriptions. +**At least one concrete value.** Every subscription must include at least one specific (non-wildcard) criterion. You can't subscribe to "everything." ### Examples @@ -228,21 +228,25 @@ constructor( ### Prohibited Subscriptions -- **Non-Equality Operations**: Subscriptions can’t match event parameters using less than (\<), greater than (\>), range, or bitwise operations. Only strict equality is supported. +Not everything is supported. Keep these restrictions in mind: + +**No inequality matching.** Subscriptions only support strict equality. You can't filter by less than, greater than, ranges, or bitwise operations. -- **Complex Criteria Sets**: Subscriptions can’t use disjunction or sets of criteria within a single subscription. While calling the `subscribe()` method multiple times can achieve similar results, it may lead to combinatorial explosion. +**No disjunction within a single subscription.** You can't say "match topic A or topic B" in one call. You can achieve similar results with multiple `subscribe()` calls, but be careful as this can lead to combinatorial explosion. -- **Single Chain and All Contracts**: Subscribing to events from all chains or all contracts simultaneously is not allowed. Subscribing to all events from only one chain is also prohibited, as it is considered unnecessary. +**No blanket subscriptions.** Subscribing to all events from all chains, all contracts, or an entire chain is not allowed. -- **Duplicate Subscriptions**: While duplicate subscriptions are technically allowed, they function as a single subscription. Users are charged for each transaction sent to the system contract. Preventing duplicates in the system contract is costly due to EVM storage limitations, so duplicate subscriptions are permitted to keep costs manageable. +**Duplicates are allowed but redundant.** Duplicate subscriptions function as a single subscription, but you're still charged for each transaction to the system contract. Preventing duplicates on-chain would be prohibitively expensive, so this is left to the developer to manage. ## Dynamic Subscriptions -Reactive contracts can dynamically manage their subscriptions based on incoming events. Since the system contract responsible for managing subscriptions is only accessible from the Reactive Network, the ReactVM's contract copy handles these operations and communicates with the Reactive Network using callbacks. You can read more on that in [ReactVM and Reactive Network As a Dual-State Environment](./react-vm). Below is an example of how you can make a dynamic subscription, based on the [Approval Magic Demo](https://github.com/Reactive-Network/reactive-smart-contract-demos/tree/main/src/demos/approval-magic). +Sometimes you need to add or remove subscriptions at runtime based on what's happening on-chain. Since the system contract is only accessible from Reactive Network, and event processing happens in the ReactVM, dynamic subscriptions work through callbacks: the ReactVM sends a callback to Reactive Network instance of the same contract, which then calls `subscribe()` or `unsubscribe()`. + +For more on why this roundtrip is necessary, see [Lesson 3: ReactVM and the Dual-State Environment](./react-vm). The example below is based on the [Approval Magic Demo](https://github.com/Reactive-Network/reactive-smart-contract-demos/tree/main/src/demos/approval-magic). -### Imports and Initialization +### Contract Setup -Initialize the contract by declaring constants and variables that will be used throughout the contract: +The contract declares its constants and state variables, then subscribes to the events that will trigger dynamic subscription changes: ```solidity pragma solidity >=0.8.0; @@ -260,24 +264,7 @@ contract ApprovalListener is AbstractReactive { address private owner; ApprovalService private approval_service; -``` - - -**Constants**: -- `REACTIVE_CHAIN_ID`: Represents the ID of the Reactive network. -- `SEPOLIA_CHAIN_ID`: Represents the Sepolia test network. -- `SUBSCRIBE_TOPIC_0`, `UNSUBSCRIBE_TOPIC_0`, `APPROVAL_TOPIC_0`: Topics used to identify the different types of actions (subscription, unsubscription, and approval) in the Reactive Network. -- `CALLBACK_GAS_LIMIT`: The maximum gas allowed for callback operations. - -**State Variables**: -- `owner`: The address of the contract owner, typically the one who deployed the contract. -- `approval_service`: An instance of the ApprovalService contract, used to manage subscription-related operations. - -### Constructor - -The constructor sets up the contract's initial state, including registering for the relevant subscription and unsubscription events. -```solidity constructor( ApprovalService service_ ) payable { @@ -301,22 +288,15 @@ The constructor sets up the contract's initial state, including registering for REACTIVE_IGNORE, REACTIVE_IGNORE ); - } } ``` -**Constructor Parameters**: -- `service_`: The address of the `ApprovalService` contract to interact with for subscription management. - -**Initialization**: -- `owner` is set to the address that deploys the contract. -- `approval_service` is set to the provided `ApprovalService` contract instance. -- If the environment is not `vm` instance, the constructor subscribes to the relevant topics (subscription and unsubscription) by calling `service.subscribe` for both `SUBSCRIBE_TOPIC_0` and `UNSUBSCRIBE_TOPIC_0`. +The constructor subscribes to two event types from the `ApprovalService` contract: subscribe requests and unsubscribe requests. When either event is detected, the contract's `react()` function handles it. ### Authorization -This modifier restricts the execution of certain functions to only authorized callers (the service contract and the owner). +A modifier ensures that only authorized callers (specifically the service contract, verified against the owner's address) can trigger subscription changes on Reactive Network: ```solidity modifier callbackOnly(address evm_id) { @@ -332,9 +312,9 @@ modifier callbackOnly(address evm_id) { **Functionality**: This ensures that only the service contract or the owner can trigger certain actions, preventing unauthorized access. -### Subscribing & Unsubscribing +### Subscribe and Unsubscribe -These functions allow the contract to subscribe or unsubscribe a subscriber address to/from the `APPROVAL_TOPIC_0` in the Reactive Network. +These functions run on Reactive Network (`rnOnly`) and are called via callbacks from the ReactVM. They add or remove subscriptions to `APPROVAL_TOPIC_0` for a given subscriber address: ```solidity // Methods specific to reactive network contract instance @@ -361,17 +341,9 @@ These functions allow the contract to subscribe or unsubscribe a subscriber addr } ``` -**Parameters**: -- `rvm_id`: The ID of the reactive virtual machine (RVM). -- `subscriber`: The address that will be subscribed or unsubscribed. - -**Operations**: -- `subscribe`: Registers a subscriber to the `APPROVAL_TOPIC_0`. -- `unsubscribe`: Removes a subscriber from the `APPROVAL_TOPIC_0`. +### Processing Events in the ReactVM -### react Function & Logic - -The function processes incoming log records from the ReactVM and executes different actions based on the topic in the log. +The `react()` function handles three types of incoming events and routes each one to the appropriate action via a callback: ```solidity // Methods specific to ReactVM contract instance @@ -400,29 +372,20 @@ The function processes incoming log records from the ReactVM and executes differ log._contract, amount ); - emit Callback(SEPOLIA_CHAIN_ID, address(approval_service), CALLBACK_GAS_LIMIT, payload); + emit Callback(DESTINATION_CHAIN_ID, address(approval_service), CALLBACK_GAS_LIMIT, payload); } } } ``` -**Log Processing**: -- Subscribe Logic: If the log's `topic_0` matches the `SUBSCRIBE_TOPIC_0`, the function encodes a payload for the `subscribe()` method and emits a callback. -- Unsubscribe Logic: If the log's `topic_0` matches the `UNSUBSCRIBE_TOPIC_0`, the function encodes a payload for the `unsubscribe()` method and emits a callback. -- Approval Logic: For any other log, it decodes the approval amount and creates a payload for the `onApproval` method, then emits a callback to the `approval_service` on Sepolia. - -**Callback Emission**: The function uses the emit `Callback` statement to send the appropriate payload and trigger the corresponding action on the Reactive chain. - -## Conclusion - -In this article, we’ve explored the use of subscriptions in Reactive Contracts, a fundamental feature that enables automatic responses to events from other contracts. Key takeaways include: +When a subscribe or unsubscribe event arrives, the ReactVM encodes the appropriate payload and sends a callback to itself on Reactive Network, where the `subscribe()` or `unsubscribe()` function executes with the system contract. When an approval event arrives, it encodes the approval details and sends a callback to the `ApprovalService` on the destination chain. -- **Subscription Setup:** Subscriptions are established using the `subscribe` method from the Reactive Network’s system contract. This can be done statically in the constructor or managed dynamically as needed. +This pattern when ReactVM detects an event, sends a callback to Reactive Network instance, which then modifies subscriptions, is how you manage subscriptions dynamically while respecting the dual-state architecture. -- **Subscription Criteria:** Proper configuration is essential for effective subscriptions. Wildcards and specific values are used to define the scope of events to which a contract subscribes. Avoid prohibited subscription patterns to ensure efficient operation. +## About This Course -- **Dynamic Management:** Subscriptions can be dynamically adjusted based on incoming events, with the `react()` method playing a central role in managing these operations. This approach ensures that RCs can respond in real-time to changes in the network. +This course is designed to give you both the theory and the hands-on experience to start building with Reactive contracts. It includes detailed lectures, code examples on GitHub, and video workshops covering everything from basic concepts to real-world deployments. -- **Handling Events:** Contracts must handle events carefully by preparing appropriate payloads for subscription, unsubscription, and approval actions. This ensures accurate and timely updates across the network. +Whether you want to understand how Reactive contracts work under the hood or jump straight into building, the course adapts to either path. Explore the [use cases](../use-cases/index.md) if you want to see what's possible, or start from Module 1 to build up from the fundamentals. -For practical applications and further insights, explore our [use cases](../use-cases/index.md) and join our [Telegram](https://t.me/reactivedevs) group to engage with the community. +Join the [Telegram](https://t.me/reactivedevs) community if you have questions or want to connect with other developers working with Reactive contracts. \ No newline at end of file