From 4ef6dd9555c67c85f1acb203293cf2dfa713e11a Mon Sep 17 00:00:00 2001 From: PRakhar Date: Fri, 20 Mar 2026 16:04:53 +0530 Subject: [PATCH] Added workflow figurs in Readme files of Basic, Cron, Aave-Liquidation-Protection, Uniswap-v2-Stop-Order, Uniswap-v2-Stop-Take-Profit-Order systems --- .../aave-liquidation-protection/README.md | 285 +++++++++--------- src/demos/basic/README.md | 119 ++++++-- src/demos/cron/README.md | 93 +++++- src/demos/uniswap-v2-stop-order/README.md | 159 ++++++---- .../README.md | 188 +++++++----- 5 files changed, 539 insertions(+), 305 deletions(-) diff --git a/src/demos/aave-liquidation-protection/README.md b/src/demos/aave-liquidation-protection/README.md index deb153b1..b38a229c 100644 --- a/src/demos/aave-liquidation-protection/README.md +++ b/src/demos/aave-liquidation-protection/README.md @@ -4,31 +4,13 @@ The **Aave Liquidation Protection Demo** implements a reactive smart contract that monitors user positions on Aave protocol through periodic CRON events. When a user's health factor drops below a predefined threshold, the contract automatically executes protection measures by either depositing additional collateral or repaying debt to prevent liquidation. This demo extends the principles introduced in the [Reactive Network Demo](https://github.com/Reactive-Network/reactive-smart-contract-demos/tree/main/src/demos/basic), which provides an introduction to building reactive smart contracts that respond to real-time events. -## Contracts - -**Reactive Contract**: [AaveProtectionDemoReactive](https://github.com/Reactive-Network/reactive-smart-contract-demos/blob/main/src/demos/aave-liquidation-protection/AaveProtectionDemoReactive.sol) subscribes to CRON events on the Reactive Network and protection lifecycle events from the callback contract on Ethereum Sepolia. It continuously monitors protection configurations and triggers periodic health checks. When the CRON event fires, it calls the callback contract to check and protect all active configurations. The contract tracks protection status through events emitted by the callback contract, including `ProtectionConfigured`, `ProtectionExecuted`, `ProtectionCancelled`, `ProtectionPaused`, `ProtectionResumed`, and `ProtectionCycleCompleted`. This contract demonstrates a simple reactive approach to automated liquidation protection on Aave. - -**Origin/Destination Chain Contract**: [AaveProtectionDemoCallback](https://github.com/Reactive-Network/reactive-smart-contract-demos/blob/main/src/demos/aave-liquidation-protection/AaveProtectionDemoCallback.sol) processes liquidation protection requests. When the Reactive Network triggers the callback via CRON, the contract checks all active protection configurations, queries the user's health factor from Aave, and executes protection measures if needed. The contract supports three protection types: collateral deposit, debt repayment, or both. It calculates the exact amount needed to reach the target health factor and executes the appropriate action through Aave's lending pool. After execution, the contract emits events that the reactive contract monitors to track protection status. The personal callback contract provides complete control and privacy for individual users. - -**Rescuable Base Contract**: [RescuableBase](https://github.com/Reactive-Network/reactive-smart-contract-demos/blob/main/src/demos/aave-liquidation-protection/RescuableBase.sol) is an abstract contract providing rescue functionality for ETH and ERC20 tokens. It allows the owner to recover any stuck funds from the callback contract, with built-in safety checks and event emissions for transparency. - -## Further Considerations - -The demo showcases essential liquidation protection functionality but can be improved with: - -- **Multiple User Support:** Extending to support multiple users with a single contract deployment. -- **Advanced Health Factor Calculations:** Implementing more sophisticated health factor prediction models. -- **Gas Optimization:** Optimizing gas usage for protection execution and batch operations. -- **Emergency Stop Mechanisms:** Adding circuit breakers for emergency situations. -- **Dynamic Protection Strategies:** Supporting time-based or market condition-based protection adjustments. - ## Deployment & Testing ### Environment Variables Before proceeding further, configure these environment variables: -* `DESTINATION_RPC` — RPC URL for the destination chain (Ethereum Sepolia), (see [Chainlist](https://chainlist.org)). +* `DESTINATION_RPC` — RPC URL for the destination chain (Ethereum Sepolia) (see [Chainlist](https://chainlist.org)). * `DESTINATION_PRIVATE_KEY` — Private key for signing transactions on the destination chain. * `REACTIVE_RPC` — RPC URL for the Reactive Network (see [Reactive Docs](https://dev.reactive.network/reactive-mainnet)). * `REACTIVE_PRIVATE_KEY` — Private key for signing transactions on the Reactive Network. @@ -45,241 +27,260 @@ Before proceeding further, configure these environment variables: > **Important**: Do not send more than 5 SepETH per request, as doing so will cause you to lose the excess amount without receiving any additional REACT. The maximum that should be sent in a single transaction is 5 SepETH, which will yield 500 REACT. > ⚠️ **Broadcast Error** -> +> > If you see the following message: `error: unexpected argument '--broadcast' found`, it means your Foundry version (or local setup) does not support the `--broadcast` flag for `forge create`. Simply remove `--broadcast` from your command and re-run it. -### Step 1 — Aave Test Tokens +--- -To test live, you'll need testnet tokens supported by Aave V3 on Sepolia. Use the Aave faucet to obtain test tokens: +## Contracts -Visit the [Aave V3 Testnet Faucet](https://staging.aave.com/faucet/) and request test tokens. +**Reactive Contract**: [AaveProtectionDemoReactive](https://github.com/Reactive-Network/reactive-smart-contract-demos/blob/main/src/demos/aave-liquidation-protection/AaveProtectionDemoReactive.sol) subscribes to CRON events on the Reactive Network and protection lifecycle events from the callback contract on Ethereum Sepolia. It continuously monitors protection configurations and triggers periodic health checks. When the CRON event fires, it calls the callback contract to check and protect all active configurations. The contract tracks protection status through events emitted by the callback contract, including `ProtectionConfigured`, `ProtectionExecuted`, `ProtectionCancelled`, `ProtectionPaused`, `ProtectionResumed`, and `ProtectionCycleCompleted`. This contract demonstrates a simple reactive approach to automated liquidation protection on Aave. -**Supported Assets on Aave V3 Sepolia:** +**Origin/Destination Chain Contract**: [AaveProtectionDemoCallback](https://github.com/Reactive-Network/reactive-smart-contract-demos/blob/main/src/demos/aave-liquidation-protection/AaveProtectionDemoCallback.sol) processes liquidation protection requests. When the Reactive Network triggers the callback via CRON, the contract checks all active protection configurations, queries the user's health factor from Aave, and executes protection measures if needed. The contract supports three protection types: collateral deposit, debt repayment, or both. It calculates the exact amount needed to reach the target health factor and executes the appropriate action through Aave's lending pool. After execution, the contract emits events that the reactive contract monitors to track protection status. The personal callback contract provides complete control and privacy for individual users. -| Symbol | Address | -|--------|---------| -| **DAI** | `0xFF34B3d4Aee8ddCd6F9AfffB6Fe49bD371b8a357` | -| **LINK** | `0xf8Fb3713D459D7C1018BD0A49D19b4C44290EBE5` | -| **USDC** | `0x94a9D9AC8a22534E3FaCa9F4e7F2E2cf85d5E4C8` | -| **WBTC** | `0x29f2D40B0605204364af54EC677bD022da425d03` | -| **WETH** | `0xC558DBdD856501FCd9aaF1E62eaE57A9F0629a3C` | -| **USDT** | `0xaA8E23Fb1079EA71e0a56f48a2aA51851D8433D0` | -| **AAVE** | `0x88541670E55cC00bEefd87EB59EDd1b7C511AC9A` | -| **EURS** | `0x6d906e526a4e2Ca02097BA9d0caA3c382f52278E` | -| **GHO** | `0xc4bF5CbDaBE595361438F8c6a187bDC330539c60` | +**Rescuable Base Contract**: [RescuableBase](https://github.com/Reactive-Network/reactive-smart-contract-demos/blob/main/src/demos/aave-liquidation-protection/RescuableBase.sol) is an abstract contract providing rescue functionality for ETH and ERC20 tokens. It allows the owner to recover any stuck funds from the callback contract, with built-in safety checks and event emissions for transparency. + +--- + +## System Workflow -Example usage: +### How It Works — End-to-End Flow + +``` +User supplies collateral and borrows from Aave (active lending position) + ↓ +User creates a protection config on the Callback Contract (health factor threshold + target + protection type) + ↓ +User approves Callback Contract to spend collateral and/or debt assets + ↓ +Reactive Contract deployed with CRON topic → begins subscribing to periodic CRON events + ↓ +Reactive Network emits CRON event at configured interval (e.g. every 1 minute) + ↓ +Reactive Contract receives CRON event → emits Callback targeting Callback Contract + ↓ +Reactive Network calls checkAndProtect() on Callback Contract (Sepolia) + ↓ +Callback Contract queries user's health factor from Aave Protocol Data Provider + ↓ (health factor ≥ threshold) +No action taken → Callback Contract emits ProtectionCycleCompleted → wait for next CRON + ↓ (health factor < threshold) +Callback Contract calculates required protection amount to reach target health factor + ↓ +Executes protection: deposits collateral to Aave and/or repays debt (per config) + ↓ +Callback Contract emits ProtectionExecuted event + ↓ +Reactive Contract detects event → updates protection status → continues monitoring +``` +### Protection Types + +| Type | Value | Description | When to Use | +|------|-------|-------------|-------------| +| Collateral Deposit | `0` | Deposits additional collateral to raise health factor | You have spare collateral and want to keep your debt | +| Debt Repayment | `1` | Repays part of debt to raise health factor | You want to reduce debt exposure | +| Both | `2` | Attempts preferred method, falls back to alternative | Maximum flexibility | + +### Key Design Decisions + +- **CRON-based polling**: Rather than waiting for a specific on-chain event, the system actively polls your health factor on each CRON tick. This is necessary because Aave positions can degrade due to market price movements rather than on-chain user actions. +- **On-chain health factor query**: The Callback contract reads health factor directly from Aave's Protocol Data Provider on each check — always using the latest state, never relying on stale cached values. +- **Per-user deployment**: Each user deploys their own Callback contract for complete isolation and privacy over their protection configuration. +- **Dual-asset approval pattern**: The Callback contract needs approval for both collateral and debt assets up front, enabling it to act autonomously when health factor drops. +- **Graceful lifecycle events**: The Reactive contract tracks `ProtectionConfigured`, `ProtectionPaused`, `ProtectionResumed`, `ProtectionCancelled`, and `ProtectionExecuted` events — allowing it to accurately maintain protection state without redeployment. + +--- + +## Step-by-Step Walkthrough + +### Phase 1: Setup Aave Position + +**Step 1 — Get testnet tokens from the Aave faucet** + +Visit the [Aave V3 Testnet Faucet](https://staging.aave.com/faucet/) and request test tokens. + +Configure your chosen assets: ```bash export COLLATERAL_ASSET=0x94a9D9AC8a22534E3FaCa9F4e7F2E2cf85d5E4C8 # USDC on Sepolia export DEBT_ASSET=0xFF34B3d4Aee8ddCd6F9AFFFB6Fe49bD371b8a357 # DAI on Sepolia ``` -### Step 2 — Destination Contract -Deploy the callback contract on Ethereum Sepolia, using the Aave V3 protocol addresses. You should also pass the Sepolia callback proxy address and the owner wallet address. Assign the `Deployed to` address from the response to `CALLBACK_ADDR`. +--- + +**Step 2 — Deploy the Callback Contract on Sepolia** + +Pass owner wallet, callback proxy, and the three Aave V3 addresses. Assign `Deployed to` to `CALLBACK_ADDR`. ```bash forge create --broadcast --rpc-url $DESTINATION_RPC --private-key $DESTINATION_PRIVATE_KEY src/demos/aave-liquidation-protection/AaveProtectionDemoCallback.sol:AaveProtectionDemoCallback --value 0.02ether --constructor-args $OWNER_WALLET $DESTINATION_CALLBACK_PROXY_ADDR $AAVE_LENDING_POOL $AAVE_PROTOCOL_DATA_PROVIDER $AAVE_ADDRESSES_PROVIDER ``` -### Step 3 — Supply Collateral and Borrow on Aave +--- -Before setting up protection, you need to have an active Aave position. Supply collateral and borrow assets: - -**Supply Collateral:** - -First, approve the Aave lending pool to spend your collateral: +**Step 3 — Supply collateral to Aave** +Approve the Aave lending pool to spend your collateral: ```bash cast send $COLLATERAL_ASSET 'approve(address,uint256)' --rpc-url $DESTINATION_RPC --private-key $DESTINATION_PRIVATE_KEY $AAVE_LENDING_POOL 100000000000000000000 ``` -Then supply the collateral to Aave: - +Supply collateral: ```bash cast send $AAVE_LENDING_POOL 'supply(address,uint256,address,uint16)' --rpc-url $DESTINATION_RPC --private-key $DESTINATION_PRIVATE_KEY $COLLATERAL_ASSET 50000000000000000000 $OWNER_WALLET 0 ``` -**Borrow Assets:** +--- -Borrow against your collateral (use mode 2 for variable rate): +**Step 4 — Borrow from Aave** +Borrow against your collateral using variable rate (mode = `2`): ```bash cast send $AAVE_LENDING_POOL 'borrow(address,uint256,uint256,uint16,address)' --rpc-url $DESTINATION_RPC --private-key $DESTINATION_PRIVATE_KEY $DEBT_ASSET 10000000000000000000 2 0 $OWNER_WALLET ``` -### Step 4 — Reactive Contract +You now have an active Aave lending position that this system will protect. + +--- -Deploy the Reactive contract specifying: +### Phase 2: Deploy Reactive Contract -- `OWNER_WALLET`: The wallet address that owns and manages the protection system. -- `CALLBACK_ADDR`: The address from Step 2. -- `CRON_TOPIC`: The CRON topic ID for periodic monitoring (e.g., `0x04463f7c1651e6b9774d7f85c85bb94654e3c46ca79b0c16fb16d4183307b687` for 1-minute intervals). +**Step 5 — Deploy AaveProtectionDemoReactive on the Reactive Network** + +Choose a CRON topic for your monitoring interval (see [Reactive Docs](https://dev.reactive.network) for available topics): ```bash forge create --broadcast --rpc-url $REACTIVE_RPC --private-key $REACTIVE_PRIVATE_KEY src/demos/aave-liquidation-protection/AaveProtectionDemoReactive.sol:AaveProtectionDemoReactive --value 0.5ether --constructor-args $OWNER_WALLET $CALLBACK_ADDR $CRON_TOPIC ``` -> 📝 **Note** -> The CRON topic determines how frequently the reactive contract checks your position. Common intervals: -> - 1 minute: Use the system CRON_1 topic -> - 5 minutes: Use the system CRON_5 topic -> - 15 minutes: Use the system CRON_15 topic -> -> Check the [Reactive Network Documentation](https://dev.reactive.network) for available CRON topics. +--- -### Step 5 — Create Protection Configuration +### Phase 3: Configure Protection -Create a protection configuration on the callback contract. You'll need to specify: +**Step 6 — Create a protection configuration** -- `PROTECTION_TYPE`: Protection type (0 = Collateral Deposit, 1 = Debt Repayment, 2 = Both) -- `HEALTH_FACTOR_THRESHOLD`: Health factor below which protection triggers (e.g., 1.5e18 for 1.5) -- `TARGET_HEALTH_FACTOR`: Target health factor to achieve after protection (e.g., 2.0e18 for 2.0) -- `PREFER_DEBT_REPAYMENT`: If using type 2 (Both), whether to prefer debt repayment (true/false) - -```bash -cast send $CALLBACK_ADDR 'createProtectionConfig(uint8,uint256,uint256,address,address,bool)' --rpc-url $DESTINATION_RPC --private-key $DESTINATION_PRIVATE_KEY $PROTECTION_TYPE $HEALTH_FACTOR_THRESHOLD $TARGET_HEALTH_FACTOR $COLLATERAL_ASSET $DEBT_ASSET $PREFER_DEBT_REPAYMENT -``` - -Example with specific values (Protection Type = Both, Threshold = 1.5, Target = 2.0, Prefer Debt Repayment = true): +Example: Protection Type `2` (Both), threshold `1.5`, target `2.0`, prefer debt repayment: ```bash cast send $CALLBACK_ADDR 'createProtectionConfig(uint8,uint256,uint256,address,address,bool)' --rpc-url $DESTINATION_RPC --private-key $DESTINATION_PRIVATE_KEY 2 1500000000000000000 2000000000000000000 $COLLATERAL_ASSET $DEBT_ASSET true ``` -### Step 6 — Approve Protection Assets +--- -Authorize the callback contract to spend your collateral and debt assets for protection execution: +**Step 7 — Approve protection assets** -**Approve Collateral Asset:** +Allow the Callback contract to pull funds from your wallet when protection triggers: +Approve collateral asset: ```bash cast send $COLLATERAL_ASSET 'approve(address,uint256)' --rpc-url $DESTINATION_RPC --private-key $DESTINATION_PRIVATE_KEY $CALLBACK_ADDR 1000000000000000000000 ``` -**Approve Debt Asset:** - +Approve debt asset: ```bash cast send $DEBT_ASSET 'approve(address,uint256)' --rpc-url $DESTINATION_RPC --private-key $DESTINATION_PRIVATE_KEY $CALLBACK_ADDR 1000000000000000000000 ``` -> 📝 **Note** -> These approvals allow the callback contract to pull funds from your wallet when protection is triggered. Ensure you maintain sufficient balance of the required assets in your wallet. +The system is now fully active. From this point, every CRON tick will trigger an automatic health factor check. No further user action is required unless you want to modify the configuration. -### Step 7 — Monitor Protection -The reactive contract will now automatically monitor your Aave position based on the CRON schedule. When your health factor drops below the threshold, it will: +--- -1. Trigger the callback contract via the Reactive Network -2. The callback contract checks your health factor on Aave -3. If below threshold, it calculates the required protection amount -4. Executes either collateral deposit or debt repayment (or both) -5. Emits events that the reactive contract monitors +### Phase 4: Test Protection (Optional) -You can view the protection execution on [Sepolia scan](https://sepolia.etherscan.io/) by monitoring the callback contract's events. - -**Check Current Health Factor:** +**Step 8 — Lower your health factor to trigger protection** +Borrow more to reduce the health factor below your configured threshold: ```bash -cast call $CALLBACK_ADDR 'getCurrentHealthFactor()' --rpc-url $DESTINATION_RPC +cast send $AAVE_LENDING_POOL 'borrow(address,uint256,uint256,uint16,address)' --rpc-url $DESTINATION_RPC --private-key $DESTINATION_PRIVATE_KEY $DEBT_ASSET 5000000000000000000 2 0 $OWNER_WALLET ``` -**View Active Configurations:** +Wait for the next CRON tick. The Callback contract will detect the health factor has crossed the threshold and automatically execute protection. -```bash -cast call $CALLBACK_ADDR 'getActiveConfigs()' --rpc-url $DESTINATION_RPC -``` -**View Protection Configuration:** +--- +### Phase 5: Read Current State + +**Check current health factor (read-only)** ```bash -cast call $CALLBACK_ADDR 'protectionConfigs(uint256)' $CONFIG_ID --rpc-url $DESTINATION_RPC +cast call $CALLBACK_ADDR 'getCurrentHealthFactor()' --rpc-url $DESTINATION_RPC ``` -### Step 8 — Test Protection Trigger (Optional) - -To manually test the protection mechanism, you can increase your borrowed amount to lower your health factor: +**View all active configurations (read-only)** +```bash +cast call $CALLBACK_ADDR 'getActiveConfigs()' --rpc-url $DESTINATION_RPC +``` +**View a specific protection configuration (read-only)** ```bash -cast send $AAVE_LENDING_POOL 'borrow(address,uint256,uint256,uint16,address)' --rpc-url $DESTINATION_RPC --private-key $DESTINATION_PRIVATE_KEY $DEBT_ASSET 5000000000000000000 2 0 $OWNER_WALLET +cast call $CALLBACK_ADDR 'protectionConfigs(uint256)' $CONFIG_ID --rpc-url $DESTINATION_RPC ``` -Monitor your health factor and watch for the protection to trigger automatically when it drops below your configured threshold. +--- ## Management Functions -### Pause Protection - -Temporarily pause a protection configuration: +### Pause a Protection Configuration +Stops the configuration from executing on future CRON ticks (does not cancel it): ```bash cast send $CALLBACK_ADDR 'pauseProtectionConfig(uint256)' $CONFIG_ID --rpc-url $DESTINATION_RPC --private-key $DESTINATION_PRIVATE_KEY ``` -### Resume Protection - -Resume a paused protection configuration: +### Resume a Protection Configuration ```bash cast send $CALLBACK_ADDR 'resumeProtectionConfig(uint256)' $CONFIG_ID --rpc-url $DESTINATION_RPC --private-key $DESTINATION_PRIVATE_KEY ``` -### Cancel Protection - -Permanently cancel a protection configuration: +### Cancel a Protection Configuration Permanently ```bash cast send $CALLBACK_ADDR 'cancelProtectionConfig(uint256)' $CONFIG_ID --rpc-url $DESTINATION_RPC --private-key $DESTINATION_PRIVATE_KEY ``` -### Rescue Funds - -If funds get stuck in the callback contract, you can rescue them: +### Rescue Stuck Funds -**Rescue ETH:** +If funds get stuck in the callback contract: +Rescue ETH: ```bash cast send $CALLBACK_ADDR 'rescueAllETH()' --rpc-url $DESTINATION_RPC --private-key $DESTINATION_PRIVATE_KEY ``` -**Rescue ERC20 Tokens:** - +Rescue ERC20 tokens: ```bash cast send $CALLBACK_ADDR 'rescueAllERC20(address)' $TOKEN_ADDRESS --rpc-url $DESTINATION_RPC --private-key $DESTINATION_PRIVATE_KEY ``` -## Architecture +--- -The Aave Liquidation Protection system consists of two main components: +## Further Considerations -1. **Reactive Contract (on Reactive Network)**: Monitors CRON events and protection lifecycle events, triggering callbacks when needed. +The demo showcases essential liquidation protection functionality but can be improved with: -2. **Callback Contract (on Ethereum Sepolia)**: Contains the business logic for checking health factors, calculating protection amounts, and executing Aave interactions. +- **Multiple User Support:** Extending to support multiple users with a single contract deployment. +- **Advanced Health Factor Calculations:** Implementing more sophisticated health factor prediction models. +- **Gas Optimization:** Optimizing gas usage for protection execution and batch operations. +- **Emergency Stop Mechanisms:** Adding circuit breakers for emergency situations. +- **Dynamic Protection Strategies:** Supporting time-based or market condition-based protection adjustments. -**Event Flow:** -``` -CRON Event → Reactive Contract → Callback on Sepolia → Check Health Factor - ↓ - If below threshold - ↓ - Calculate Protection Amount - ↓ - Execute Aave Transaction - ↓ - Emit ProtectionExecuted Event - ↓ - Reactive Contract Updates Status -``` - -## Protection Types -### Collateral Deposit (Type 0) -Deposits additional collateral to increase health factor. Best when you have available collateral assets and want to maintain your debt position. +--- -### Debt Repayment (Type 1) -Repays part of your debt to increase health factor. Best when you want to reduce your debt exposure. +## Supported Assets on Aave V3 Sepolia -### Both (Type 2) -Attempts both methods based on preference. Provides maximum flexibility by trying the preferred method first and falling back to the alternative if needed. \ No newline at end of file +| Symbol | Address | +|--------|---------| +| **DAI** | `0xFF34B3d4Aee8ddCd6F9AfffB6Fe49bD371b8a357` | +| **LINK** | `0xf8Fb3713D459D7C1018BD0A49D19b4C44290EBE5` | +| **USDC** | `0x94a9D9AC8a22534E3FaCa9F4e7F2E2cf85d5E4C8` | +| **WBTC** | `0x29f2D40B0605204364af54EC677bD022da425d03` | +| **WETH** | `0xC558DBdD856501FCd9aaF1E62eaE57A9F0629a3C` | +| **USDT** | `0xaA8E23Fb1079EA71e0a56f48a2aA51851D8433D0` | +| **AAVE** | `0x88541670E55cC00bEefd87EB59EDd1b7C511AC9A` | +| **EURS** | `0x6d906e526a4e2Ca02097BA9d0caA3c382f52278E` | +| **GHO** | `0xc4bF5CbDaBE595361438F8c6a187bDC330539c60` | \ No newline at end of file diff --git a/src/demos/basic/README.md b/src/demos/basic/README.md index a74cf9f0..3ccb8669 100644 --- a/src/demos/basic/README.md +++ b/src/demos/basic/README.md @@ -9,33 +9,16 @@ The **Reactive Network Demo** illustrates a basic use case of the Reactive Netwo This setup can be adapted for various scenarios, from simple stop orders to fully decentralized algorithmic trading. -## Contracts - -**Origin Contract**: [BasicDemoL1Contract](https://github.com/Reactive-Network/reactive-smart-contract-demos/blob/main/src/demos/basic/BasicDemoL1Contract.sol) receives Ether and returns it to the sender, emitting a `Received` event with transaction details. - -**Reactive Contract**: [BasicDemoReactiveContract](https://github.com/Reactive-Network/reactive-smart-contract-demos/blob/main/src/demos/basic/BasicDemoReactiveContract.sol) demonstrates a reactive subscription model. It subscribes to logs from a specified contract and processes event data in a decentralized manner. The contract subscribes to events from a specified contract on the origin chain. Upon receiving a log, the contract checks if `topic_3` is at least 0.01 Ether. If the condition is met, it emits a `Callback` event containing a payload to invoke an external callback function on the destination chain. - -**Destination Contract**: [BasicDemoL1Callback](https://github.com/Reactive-Network/reactive-smart-contract-demos/blob/main/src/demos/basic/BasicDemoL1Callback.sol) serves as the destination contract for handling reactive callbacks. When triggered by a cross-chain event, it logs key transaction details while ensuring only authorized senders can invoke the callback. Upon execution, it emits a `CallbackReceived` event, capturing metadata such as the origin, sender, and reactive sender addresses. - -## Further Considerations - -The demo highlights just a fraction of Reactive Network’s capabilities. Future enhancements could include: - -- **Expanded Event Subscriptions**: Monitoring multiple event sources, including callback logs. -- **Dynamic Subscriptions**: Adjusting subscriptions in real-time based on evolving conditions. -- **State Persistence**: Maintaining contract state for more complex, context-aware reactions. -- **Versatile Callbacks**: Enabling customizable transaction payloads to improve adaptability. - ## Deployment & Testing ### Environment Variables Before proceeding further, configure these environment variables: -* `ORIGIN_RPC` — RPC URL for the origin chain, (see [Chainlist](https://chainlist.org)). +* `ORIGIN_RPC` — RPC URL for the origin chain (see [Chainlist](https://chainlist.org)). * `ORIGIN_CHAIN_ID` — ID of the origin blockchain (see [Reactive Docs](https://dev.reactive.network/origins-and-destinations#mainnet-chains)). * `ORIGIN_PRIVATE_KEY` — Private key for signing transactions on the origin chain. -* `DESTINATION_RPC` — RPC URL for the destination chain, (see [Chainlist](https://chainlist.org)). +* `DESTINATION_RPC` — RPC URL for the destination chain (see [Chainlist](https://chainlist.org)). * `DESTINATION_CHAIN_ID` — ID of the destination blockchain (see [Reactive Docs](https://dev.reactive.network/origins-and-destinations#mainnet-chains)). * `DESTINATION_PRIVATE_KEY` — Private key for signing transactions on the destination chain. * `REACTIVE_RPC` — RPC URL for the Reactive Network (see [Reactive Docs](https://dev.reactive.network/reactive-mainnet)). @@ -49,39 +32,117 @@ Before proceeding further, configure these environment variables: > **Important**: Do not send more than 5 SepETH per request, as doing so will cause you to lose the excess amount without receiving any additional REACT. The maximum that should be sent in a single transaction is 5 SepETH, which will yield 500 REACT. > ⚠️ **Broadcast Error** -> +> > If you see the following message: `error: unexpected argument '--broadcast' found`, it means your Foundry version (or local setup) does not support the `--broadcast` flag for `forge create`. Simply remove `--broadcast` from your command and re-run it. -### Step 1 — Origin Contract +--- + +## Contracts -Deploy the `BasicDemoL1Contract` contract and assign the `Deployed to` address from the response to `ORIGIN_ADDR`. +**Origin Contract**: [BasicDemoL1Contract](https://github.com/Reactive-Network/reactive-smart-contract-demos/blob/main/src/demos/basic/BasicDemoL1Contract.sol) receives Ether and returns it to the sender, emitting a `Received` event with transaction details. + +**Reactive Contract**: [BasicDemoReactiveContract](https://github.com/Reactive-Network/reactive-smart-contract-demos/blob/main/src/demos/basic/BasicDemoReactiveContract.sol) demonstrates a reactive subscription model. It subscribes to logs from a specified contract and processes event data in a decentralized manner. The contract subscribes to events from a specified contract on the origin chain. Upon receiving a log, the contract checks if `topic_3` is at least 0.01 Ether. If the condition is met, it emits a `Callback` event containing a payload to invoke an external callback function on the destination chain. + +**Destination Contract**: [BasicDemoL1Callback](https://github.com/Reactive-Network/reactive-smart-contract-demos/blob/main/src/demos/basic/BasicDemoL1Callback.sol) serves as the destination contract for handling reactive callbacks. When triggered by a cross-chain event, it logs key transaction details while ensuring only authorized senders can invoke the callback. Upon execution, it emits a `CallbackReceived` event, capturing metadata such as the origin, sender, and reactive sender addresses. + +--- + +## System Workflow + +### How It Works — End-to-End Flow + +``` +User sends ≥ 0.01 ETH to Origin Contract (BasicDemoL1Contract) on origin chain + ↓ +Origin Contract receives ETH, returns it to sender, emits Received event + (topic_3 encodes the amount sent) + ↓ +Reactive Contract (on Reactive Network) detects the Received event from the origin chain + ↓ +Reactive Contract checks: is topic_3 (amount) ≥ 0.01 ETH? + ↓ (if YES) +Reactive Contract emits a Callback event with a payload targeting the Destination Contract + ↓ +Reactive Network's system contract calls the Destination Contract on the destination chain + ↓ +Destination Contract verifies the authorized sender, logs cross-chain metadata, emits CallbackReceived event +``` + +### Key Design Decisions + +- **Amount-gated reactions**: The Reactive contract only fires if the value sent to the Origin contract meets a minimum threshold (0.001 ETH). This demonstrates how reactive contracts can encode conditional logic before triggering cross-chain actions. +- **Separate origin and destination chains**: The origin and destination chains can be different networks. The Reactive Network acts as a trust layer bridging events from one chain to calls on another. +- **Authorization on destination**: The Destination contract checks that the caller is the authorized Reactive proxy — preventing unauthorized actors from calling the callback directly. +- **Topic-based filtering**: The Reactive contract reads `topic_3` from the `Received` event to extract the ETH amount, showing how on-chain event data can be used in reactive logic without additional off-chain infrastructure. + +--- + +## Step-by-Step Walkthrough + +### Phase 1: Deploy Origin Contract + +**Step 1 — Deploy BasicDemoL1Contract on the origin chain** + +Assign `Deployed to` to `ORIGIN_ADDR`. ```bash forge create --broadcast --rpc-url $ORIGIN_RPC --private-key $ORIGIN_PRIVATE_KEY src/demos/basic/BasicDemoL1Contract.sol:BasicDemoL1Contract ``` -### Step 2 — Destination Contract +--- + +### Phase 2: Deploy Destination Contract -Deploy the `BasicDemoL1Callback` contract and assign the `Deployed to` address from the response to `CALLBACK_ADDR`. +**Step 2 — Deploy BasicDemoL1Callback on the destination chain** + +Pass `DESTINATION_CALLBACK_PROXY_ADDR` as the constructor argument. Assign `Deployed to` to `CALLBACK_ADDR`. ```bash forge create --broadcast --rpc-url $DESTINATION_RPC --private-key $DESTINATION_PRIVATE_KEY src/demos/basic/BasicDemoL1Callback.sol:BasicDemoL1Callback --value 0.02ether --constructor-args $DESTINATION_CALLBACK_PROXY_ADDR ``` -### Step 3 — Reactive Contract +--- + +### Phase 3: Deploy Reactive Contract + +**Step 3 — Deploy BasicDemoReactiveContract on the Reactive Network** -Deploy the `BasicDemoReactiveContract` contract, configuring it to listen to `ORIGIN_ADDR` on `ORIGIN_CHAIN_ID` and to send callbacks to `CALLBACK_ADDR` on `DESTINATION_CHAIN_ID`. The `Received` event on the origin contract has a `topic_0` value of `0x8cabf31d2b1b11ba52dbb302817a3c9c83e4b2a5194d35121ab1354d69f6a4cb`, which we are monitoring. +This wires together the origin chain event to the destination chain callback. The `topic_0` for the `Received` event is `0x8cabf31d2b1b11ba52dbb302817a3c9c83e4b2a5194d35121ab1354d69f6a4cb`. ```bash forge create --broadcast --rpc-url $REACTIVE_RPC --private-key $REACTIVE_PRIVATE_KEY src/demos/basic/BasicDemoReactiveContract.sol:BasicDemoReactiveContract --value 0.1ether --constructor-args $ORIGIN_CHAIN_ID $DESTINATION_CHAIN_ID $ORIGIN_ADDR 0x8cabf31d2b1b11ba52dbb302817a3c9c83e4b2a5194d35121ab1354d69f6a4cb $CALLBACK_ADDR ``` -### Step 4 — Test Reactive Callback +At this point the Reactive contract is live and subscribed to the `Received` event from your Origin contract. Any qualifying ETH send will now trigger a cross-chain callback. -Test the whole setup by sending some ether to `ORIGIN_ADDR`: +--- + +### Phase 4: Trigger the Reactive Callback + +**Step 4 — Send ETH to the Origin Contract** + +Send at least 0.001 ETH. Smaller amounts will not trigger the Reactive contract. ```bash cast send $ORIGIN_ADDR --rpc-url $ORIGIN_RPC --private-key $ORIGIN_PRIVATE_KEY --value 0.001ether ``` -Ensure that the value sent is at least 0.001 ether, as this is the minimum required to trigger the process. Meeting this threshold will prompt the Reactive Network to initiate a callback transaction to `CALLBACK_ADDR` like shown [here](https://sepolia.etherscan.io/address/0x26fF307f0f0Ea0C4B5Df410Efe22754324DACE08#events). +What happens next (automatically, within a few blocks): + +1. Origin contract emits `Received` event with the amount in `topic_3`. +2. Reactive Network detects the event and evaluates the amount condition. +3. Reactive contract emits `Callback` event targeting your Destination contract. +4. Reactive Network proxy calls the Destination contract on the destination chain. +5. Destination contract emits `CallbackReceived` event with cross-chain metadata. + + +--- + +## Further Considerations + +The demo highlights just a fraction of Reactive Network's capabilities. Future enhancements could include: + +- **Expanded Event Subscriptions**: Monitoring multiple event sources, including callback logs. +- **Dynamic Subscriptions**: Adjusting subscriptions in real-time based on evolving conditions. +- **State Persistence**: Maintaining contract state for more complex, context-aware reactions. +- **Versatile Callbacks**: Enabling customizable transaction payloads to improve adaptability. \ No newline at end of file diff --git a/src/demos/cron/README.md b/src/demos/cron/README.md index 4fb6cab5..fa90e57b 100644 --- a/src/demos/cron/README.md +++ b/src/demos/cron/README.md @@ -4,41 +4,108 @@ This contract acts as a simple template for setting up automated logic on the Reactive Network. It listens for periodic CRON events, making it ideal for scheduling on-chain tasks such as maintenance routines, rewards distribution, or data polling. -## Key Features - -The contract extends `AbstractPausableReactive`, which automatically wires up pause/resume support and handles safe unsubscription. Implementing `getPausableSubscriptions()` allows Reactive to manage this contract’s active state without redeployment. - -On each CRON event, the contract emits a `Callback`, instructing the Reactive system contract to call the `callback(address)` function. You can customize this to point at another contract or trigger internal automation. The `react()` function filters log records by topic to ensure it only responds to the configured CRON topic. - ## Deployment & Testing ### Environment Variables Before proceeding further, configure these environment variables: +* `REACTIVE_RPC` — RPC URL for the Reactive Network (see [Reactive Docs](https://dev.reactive.network/reactive-mainnet)). +* `REACTIVE_PRIVATE_KEY` — Private key for signing transactions on the Reactive Network. * `CRON_TOPIC` — An event enabling time-based automation at fixed block intervals (see [Reactive Docs](https://dev.reactive.network/reactive-library#cron-functionality)). -> ⚠️ **Broadcast Error** +> ⚠️ **Broadcast Error** > If you see the following message: `error: unexpected argument '--broadcast' found`, it means your Foundry version (or local setup) does not support the `--broadcast` flag for `forge create`. Simply remove `--broadcast` from your command and re-run it. -### Step 1 — Reactive Contract +--- + +## Key Features + +The contract extends `AbstractPausableReactive`, which automatically wires up pause/resume support and handles safe unsubscription. Implementing `getPausableSubscriptions()` allows Reactive to manage this contract's active state without redeployment. + +On each CRON event, the contract emits a `Callback`, instructing the Reactive system contract to call the `callback(address)` function. You can customize this to point at another contract or trigger internal automation. The `react()` function filters log records by topic to ensure it only responds to the configured CRON topic. + +--- + +## System Workflow + +### How It Works — End-to-End Flow + +``` +Reactive Network emits a CRON event at a fixed block interval (configured via CRON_TOPIC) + ↓ +BasicCronContract receives the CRON event in its react() function + ↓ +react() verifies the topic matches the configured CRON_TOPIC + ↓ (if match) +BasicCronContract emits a Callback event with the target function payload + ↓ +Reactive Network's system contract forwards the callback to the designated destination address + ↓ +Destination contract executes the scheduled on-chain logic (e.g. distribute rewards, poll data, run maintenance) + ↓ +Process repeats on the next CRON tick (every N blocks, depending on CRON_TOPIC) +``` + +### Key Design Decisions + +- **Topic-based scheduling**: Different `CRON_TOPIC` values correspond to different intervals (e.g., every block, every minute, every 5 minutes). Choose the topic matching your desired frequency from the [Reactive Docs](https://dev.reactive.network/reactive-library#cron-functionality). +- **Pausable by design**: The contract inherits `AbstractPausableReactive`, meaning you can pause and resume the schedule without redeployment. This is useful for maintenance windows or conditional automation. +- **Customizable callback target**: By default the contract calls `callback(address)` on itself, but you can modify it to point to any external contract — making this a reusable cron trigger for your entire protocol. +- **No state carried between ticks**: Each CRON event is handled independently. If you need stateful logic between ticks, maintain that state in your destination contract. -Deploy the `BasicCronContract` contract, providing it with the system contract address and the preferred cron topic. +### CRON Topic Reference + +| Interval | Description | +|----------|-------------| +| CRON_1 | ~1 minute | +| CRON_5 | ~5 minutes | +| CRON_15 | ~15 minutes | + +Refer to the [Reactive Docs](https://dev.reactive.network/reactive-library#cron-functionality) for full topic values. + +--- + +## Step-by-Step Walkthrough + +### Phase 1: Configure Environment + +**Step 0 — Set your CRON topic** + +Choose an interval and export the corresponding topic hash. Example for 1-minute intervals: +```bash +export CRON_TOPIC= +``` + +--- + +### Phase 2: Deploy the Contract + +**Step 1 — Deploy BasicCronContract on the Reactive Network** + +Pass the CRON topic as the constructor argument. Assign `Deployed to` to `REACTIVE_ADDR`. ```bash forge create --broadcast --rpc-url $REACTIVE_RPC --private-key $REACTIVE_PRIVATE_KEY src/demos/cron/CronDemo.sol:BasicCronContract --value 0.1ether --constructor-args $CRON_TOPIC ``` -### Step 2 — Cron Pause (Optional) +The contract is now live and listening for CRON events at the chosen interval. No further setup is required for the basic demo — automated callbacks will begin firing each time the CRON topic is emitted by the Reactive Network. -To pause the cron subscription, run this command: +--- + +### Phase 3: Manage the Schedule + +**Step 2 (Optional) — Pause the CRON subscription** + +Stops the contract from responding to future CRON events without undeploying it: ```bash cast send $REACTIVE_ADDR "pause()" --rpc-url $REACTIVE_RPC --private-key $REACTIVE_PRIVATE_KEY ``` -To resume the cron subscription, run this command: +**Resume the CRON subscription** +Re-enables the contract to respond to CRON events: ```bash cast send $REACTIVE_ADDR "resume()" --rpc-url $REACTIVE_RPC --private-key $REACTIVE_PRIVATE_KEY -``` +``` \ No newline at end of file diff --git a/src/demos/uniswap-v2-stop-order/README.md b/src/demos/uniswap-v2-stop-order/README.md index 8339b751..c6bc94fd 100644 --- a/src/demos/uniswap-v2-stop-order/README.md +++ b/src/demos/uniswap-v2-stop-order/README.md @@ -4,35 +4,18 @@ The **Uniswap V2 Stop Order Demo** implements a reactive smart contract that monitors `Sync` events in a Uniswap V2 liquidity pool. When the exchange rate reaches a predefined threshold, the contract automatically executes asset sales. This demo extends the principles introduced in the [Reactive Network Demo](https://github.com/Reactive-Network/reactive-smart-contract-demos/tree/main/src/demos/basic), which provides an introduction to building reactive smart contracts that respond to real-time events. -## Contracts - -**Token Contract**: [UniswapDemoToken](https://github.com/Reactive-Network/reactive-smart-contract-demos/blob/main/src/demos/uniswap-v2-stop-order/UniswapDemoToken.sol) is a basic ERC-20 token with 100 tokens minted to the deployer's address. It provides integration points for Uniswap swaps. - -**Reactive Contract**: [UniswapDemoStopOrderReactive](https://github.com/Reactive-Network/reactive-smart-contract-demos/blob/main/src/demos/uniswap-v2-stop-order/UniswapDemoStopOrderReactive.sol) subscribes to a Uniswap V2 pair’s `Sync` events via `UNISWAP_V2_SYNC_TOPIC_0` and a stop-order contract’s events via `STOP_ORDER_STOP_TOPIC_0` on Ethereum Sepolia. It continuously monitors the pair’s reserves. If the reserves drop below a specified threshold, it triggers a stop order by emitting a `Callback` event containing the necessary parameters. The stop order’s corresponding event confirms execution, after which the contract marks the process as complete. This contract demonstrates a simple reactive approach to automated stop-order logic on Uniswap V2 pairs. - -**Origin/Destination Chain Contract**: [UniswapDemoStopOrderCallback](https://github.com/Reactive-Network/reactive-smart-contract-demos/blob/main/src/demos/uniswap-v2-stop-order/UniswapDemoStopOrderCallback.sol) processes stop orders. When the Reactive Network triggers the callback, the contract verifies the caller, checks the exchange rate and token balance, and performs the token swap through the Uniswap V2 router, transferring the swapped tokens back to the client. After execution, the contract emits a `Stop` event, signaling the reactive contract to conclude. The stateless callback contract can be used across multiple reactive stop orders with the same router. - -## Further Considerations - -The demo showcases essential stop order functionality but can be improved with: - -- **Dynamic Event Subscriptions:** Supporting multiple orders and flexible event handling. -- **Sanity Checks and Retry Policies:** Adding error handling and retry mechanisms. -- **Support for Arbitrary Routers and DEXes:** Extending functionality to work with various routers and decentralized exchanges. -- **Improved Data Flow:** Refining interactions between reactive and destination chain contracts for better reliability. - ## Deployment & Testing ### Environment Variables Before proceeding further, configure these environment variables: -* `DESTINATION_RPC` — RPC URL for the destination chain, (see [Chainlist](https://chainlist.org)). +* `DESTINATION_RPC` — RPC URL for the destination chain (see [Chainlist](https://chainlist.org)). * `DESTINATION_PRIVATE_KEY` — Private key for signing transactions on the destination chain. * `REACTIVE_RPC` — RPC URL for the Reactive Network (see [Reactive Docs](https://dev.reactive.network/reactive-mainnet)). * `REACTIVE_PRIVATE_KEY` — Private key for signing transactions on the Reactive Network. * `DESTINATION_CALLBACK_PROXY_ADDR` — The service address on the destination chain (see [Reactive Docs](https://dev.reactive.network/origins-and-destinations#callback-proxy-address)). -* `CLIENT_WALLET` — Deployer's EOA wallet address +* `CLIENT_WALLET` — Deployer's EOA wallet address. > ℹ️ **Reactive Faucet on Sepolia** > @@ -41,109 +24,179 @@ Before proceeding further, configure these environment variables: > **Important**: Do not send more than 5 SepETH per request, as doing so will cause you to lose the excess amount without receiving any additional REACT. The maximum that should be sent in a single transaction is 5 SepETH, which will yield 500 REACT. > ⚠️ **Broadcast Error** -> +> > If you see the following message: `error: unexpected argument '--broadcast' found`, it means your Foundry version (or local setup) does not support the `--broadcast` flag for `forge create`. Simply remove `--broadcast` from your command and re-run it. -### Step 1 — Test Tokens and Liquidity Pool +--- + +## Contracts + +**Token Contract**: [UniswapDemoToken](https://github.com/Reactive-Network/reactive-smart-contract-demos/blob/main/src/demos/uniswap-v2-stop-order/UniswapDemoToken.sol) is a basic ERC-20 token with 100 tokens minted to the deployer's address. It provides integration points for Uniswap swaps. + +**Reactive Contract**: [UniswapDemoStopOrderReactive](https://github.com/Reactive-Network/reactive-smart-contract-demos/blob/main/src/demos/uniswap-v2-stop-order/UniswapDemoStopOrderReactive.sol) subscribes to a Uniswap V2 pair's `Sync` events via `UNISWAP_V2_SYNC_TOPIC_0` and a stop-order contract's events via `STOP_ORDER_STOP_TOPIC_0` on Ethereum Sepolia. It continuously monitors the pair's reserves. If the reserves drop below a specified threshold, it triggers a stop order by emitting a `Callback` event containing the necessary parameters. The stop order's corresponding event confirms execution, after which the contract marks the process as complete. This contract demonstrates a simple reactive approach to automated stop-order logic on Uniswap V2 pairs. + +**Origin/Destination Chain Contract**: [UniswapDemoStopOrderCallback](https://github.com/Reactive-Network/reactive-smart-contract-demos/blob/main/src/demos/uniswap-v2-stop-order/UniswapDemoStopOrderCallback.sol) processes stop orders. When the Reactive Network triggers the callback, the contract verifies the caller, checks the exchange rate and token balance, and performs the token swap through the Uniswap V2 router, transferring the swapped tokens back to the client. After execution, the contract emits a `Stop` event, signaling the reactive contract to conclude. The stateless callback contract can be used across multiple reactive stop orders with the same router. + +--- + +## System Workflow + +### How It Works — End-to-End Flow + +``` +Reactive Contract deployed with: pair address, threshold, direction, client wallet + ↓ +Reactive Contract subscribes to Sync events from the Uniswap V2 Pair (Sepolia) + ↓ +Any swap or liquidity event causes the Pair to emit a Sync event (reserve update) + ↓ +Reactive Contract receives the Sync event → reads reserve0 and reserve1 + ↓ +Reactive Contract computes exchange rate and compares against the configured threshold + ↓ (if threshold crossed) +Reactive Contract emits Callback event → Reactive Network calls stopOrder() on Callback Contract + ↓ +Callback Contract verifies: correct caller? exchange rate still valid? sufficient token balance? + ↓ (if all checks pass) +Callback Contract pulls tokens from client wallet → swaps via Uniswap V2 Router → sends output tokens to client + ↓ +Callback Contract emits Stop event + ↓ +Reactive Contract receives Stop event → marks stop order as complete → stops monitoring +``` + +### Key Design Decisions + +- **Stateless Callback Contract**: The Callback contract stores no order state, making it reusable across many Reactive stop orders with the same router. +- **Single-use Reactive Contract**: Each Reactive contract instance represents one stop order. Once the `Stop` event is received, it halts permanently. +- **Direct pair interaction for testing**: Price adjustments bypass the router for precise threshold testing, since the router enforces minimum output constraints. +- **Two-topic subscription**: The Reactive contract listens to both the pair's `Sync` events and the callback contract's `Stop` event, allowing it to self-terminate cleanly after execution. + +--- + +## Step-by-Step Walkthrough + +### Phase 1: Setup Tokens & Liquidity -To test live, you'll need testnet tokens and a Uniswap V2 liquidity pool. Use pre-existing tokens or deploy your own. +**Step 1 — Deploy or export test tokens** +Use pre-existing tokens: ```bash export TK1=0x2AFDE4A3Bca17E830c476c568014E595EA916a04 export TK2=0x7EB2Ad352369bb6EDEb84D110657f2e40c912c95 ``` -To deploy ERC-20 tokens (if needed), provide a token name and symbol as constructor arguments. Each token mints 100 units to the deployer: - +Or deploy your own ERC-20 tokens: ```bash forge create --broadcast --rpc-url $DESTINATION_RPC --private-key $DESTINATION_PRIVATE_KEY src/demos/uniswap-v2-stop-order/UniswapDemoToken.sol:UniswapDemoToken --constructor-args TK1 TK1 ``` -Repeat the command for the second token, using a different name and symbol: - ```bash forge create --broadcast --rpc-url $DESTINATION_RPC --private-key $DESTINATION_PRIVATE_KEY src/demos/uniswap-v2-stop-order/UniswapDemoToken.sol:UniswapDemoToken --constructor-args TK2 TK2 ``` -### Step 2 — Uniswap V2 Pair +--- -If you use pre-existing tokens shown in Step 1, export the address of their Uniswap pair: +**Step 2 — Create or export the Uniswap V2 Pair** +Use the pre-existing pair: ```bash export UNISWAP_V2_PAIR_ADDR=0x1DD11fD3690979f2602E42e7bBF68A19040E2e25 ``` -To create a new pair, use the Uniswap V2 Factory contract `0x7E0987E5b3a30e3f2828572Bb659A548460a3003` and the token addresses deployed in Step 1. After the transaction, retrieve the pair's address from the `PairCreated` event on [Sepolia scan](https://sepolia.etherscan.io/tx/0x4a373bc6ebe815105abf44e6b26e9cdcd561fb9e796196849ae874c7083692a4/advanced#eventlog). - +Or create a new pair via the factory (`0x7E0987E5b3a30e3f2828572Bb659A548460a3003`): ```bash cast send 0x7E0987E5b3a30e3f2828572Bb659A548460a3003 'createPair(address,address)' --rpc-url $DESTINATION_RPC --private-key $DESTINATION_PRIVATE_KEY $TOKEN0_ADDR $TOKEN1_ADDR ``` -> 📝 **Note** -> The token with the smaller hexadecimal address becomes `token0`; the other is `token1`. Compare token contract addresses alphabetically or numerically in hexadecimal format to determine their order. +> 📝 **Note**: The token with the smaller hexadecimal address becomes `token0`; the other is `token1`. + +--- -### Step 3 — Destination Contract +### Phase 2: Deploy the Callback Contract -Deploy the callback contract on Ethereum Sepolia, using the Uniswap V2 router at `0xC532a74256D3Db42D0Bf7a0400fEFDbad7694008`, linked to the factory contract specified in Step 2. You should also pass the Sepolia callback proxy address. Assign the `Deployed to` address from the response to `CALLBACK_ADDR`. +**Step 3 — Deploy UniswapDemoStopOrderCallback on Sepolia** + +Uses Uniswap V2 router `0xC532a74256D3Db42D0Bf7a0400fEFDbad7694008`. Assign `Deployed to` to `CALLBACK_ADDR`. ```bash forge create --broadcast --rpc-url $DESTINATION_RPC --private-key $DESTINATION_PRIVATE_KEY src/demos/uniswap-v2-stop-order/UniswapDemoStopOrderCallback.sol:UniswapDemoStopOrderCallback --value 0.02ether --constructor-args $DESTINATION_CALLBACK_PROXY_ADDR 0xC532a74256D3Db42D0Bf7a0400fEFDbad7694008 ``` -### Step 4 — Add Liquidity to the Pool +--- + +### Phase 3: Add Liquidity -Transfer liquidity into the created pool: +**Step 4 — Fund the pool and mint LP tokens** +Transfer TOKEN0 into the pair: ```bash cast send $TOKEN0_ADDR 'transfer(address,uint256)' --rpc-url $DESTINATION_RPC --private-key $DESTINATION_PRIVATE_KEY $UNISWAP_V2_PAIR_ADDR 10000000000000000000 ``` +Transfer TOKEN1 into the pair: ```bash cast send $TOKEN1_ADDR 'transfer(address,uint256)' --rpc-url $DESTINATION_RPC --private-key $DESTINATION_PRIVATE_KEY $UNISWAP_V2_PAIR_ADDR 10000000000000000000 ``` -Mint the liquidity pool tokens to your wallet: - +Mint LP tokens to your wallet: ```bash cast send $UNISWAP_V2_PAIR_ADDR 'mint(address)' --rpc-url $DESTINATION_RPC --private-key $DESTINATION_PRIVATE_KEY $CLIENT_WALLET ``` -### Step 5 — Reactive Contract +--- -Deploy the Reactive contract specifying: +### Phase 4: Deploy the Reactive Contract -- `UNISWAP_V2_PAIR_ADDR`: The pair address from Step 2. -- `CALLBACK_ADDR`: The address from Step 3. -- `CLIENT_WALLET`: The wallet address initiating the order. -- `DIRECTION_BOOLEAN`: `true` to sell `token0` and buy `token1`; `false` for the reverse. -- `EXCHANGE_RATE_DENOMINATOR` and `EXCHANGE_RATE_NUMERATOR`: The exchange rate threshold, represented as integers. For example, a threshold of 1.234 would require `EXCHANGE_RATE_DENOMINATOR` to be set to `1000` and `EXCHANGE_RATE_NUMERATOR` to `1234`. +**Step 5 — Deploy UniswapDemoStopOrderReactive on the Reactive Network** + +Parameters: +- `UNISWAP_V2_PAIR_ADDR` — the pair to monitor +- `CALLBACK_ADDR` — the callback contract from Step 3 +- `CLIENT_WALLET` — wallet that owns the tokens to sell +- `DIRECTION_BOOLEAN` — `true` to sell token0 for token1; `false` for the reverse +- `EXCHANGE_RATE_DENOMINATOR` and `EXCHANGE_RATE_NUMERATOR` — e.g., denominator=`1000`, numerator=`1234` for a threshold of 1.234 ```bash forge create --broadcast --rpc-url $REACTIVE_RPC --private-key $REACTIVE_PRIVATE_KEY src/demos/uniswap-v2-stop-order/UniswapDemoStopOrderReactive.sol:UniswapDemoStopOrderReactive --value 0.1ether --constructor-args $UNISWAP_V2_PAIR_ADDR $CALLBACK_ADDR $CLIENT_WALLET $DIRECTION_BOOLEAN $EXCHANGE_RATE_DENOMINATOR $EXCHANGE_RATE_NUMERATOR ``` -### Step 6 — Authorize Token Spending +--- + +### Phase 5: Authorize Token Spending -Authorize the destination chain contract to spend your tokens. The last parameter specifies the amount to approve. For tokens with 18 decimals, the example below authorizes the callback contract to spend one token: +**Step 6 — Approve the Callback contract to spend your tokens** ```bash cast send $TOKEN_ADDR 'approve(address,uint256)' --rpc-url $DESTINATION_RPC --private-key $DESTINATION_PRIVATE_KEY $CALLBACK_ADDR 1000000000000000000 ``` -### Step 7 — Adjust the Exchange Rate +--- -To activate the reactive contract, directly adjust the exchange rate through the pair, bypassing the periphery contracts. Liquidity pools are simple and offer minimal functionality, making them cost-effective. Peripheral contracts, while more feature-rich and efficient for swaps, aren't suitable for this case as they limit our ability to directly modify the exchange rate. +### Phase 6: Trigger the Stop Order -Perform the adjustment by executing an inefficient swap directly through the pair: +**Step 7 — Adjust the exchange rate to cross the threshold** +Send tokens directly to the pair (bypasses the router so the rate shifts without output constraints): ```bash cast send $TOKEN_ADDR 'transfer(address,uint256)' --rpc-url $DESTINATION_RPC --private-key $DESTINATION_PRIVATE_KEY $UNISWAP_V2_PAIR_ADDR 20000000000000000 ``` -Next, execute the swap at an unfavorable rate to create a significant shift in the exchange rate: - +Execute an imbalanced swap to materially shift the price: ```bash cast send $UNISWAP_V2_PAIR_ADDR 'swap(uint,uint,address,bytes calldata)' --rpc-url $DESTINATION_RPC --private-key $DESTINATION_PRIVATE_KEY 0 5000000000000000 $CLIENT_WALLET "0x" ``` -The stop order will then be triggered and visible on [Sepolia scan](https://sepolia.etherscan.io/). The callback can be viewed on the destination contract's event log, as shown [here](https://sepolia.etherscan.io/address/0xA8AE573e5227555255AAb217a86f3E9fE1Fc6631#events). \ No newline at end of file +The `Sync` event from this swap is picked up by the Reactive Contract. If the new rate is below the configured threshold, execution is triggered automatically. + + +--- + +## Further Considerations + +The demo showcases essential stop order functionality but can be improved with: + +- **Dynamic Event Subscriptions:** Supporting multiple orders and flexible event handling. +- **Sanity Checks and Retry Policies:** Adding error handling and retry mechanisms. +- **Support for Arbitrary Routers and DEXes:** Extending functionality to work with various routers and decentralized exchanges. +- **Improved Data Flow:** Refining interactions between reactive and destination chain contracts for better reliability. \ No newline at end of file diff --git a/src/demos/uniswap-v2-stop-take-profit-order/README.md b/src/demos/uniswap-v2-stop-take-profit-order/README.md index fe3e8d43..9b665e49 100644 --- a/src/demos/uniswap-v2-stop-take-profit-order/README.md +++ b/src/demos/uniswap-v2-stop-take-profit-order/README.md @@ -4,24 +4,6 @@ The **Uniswap V2 Stop-Loss & Take-Profit Orders** system implements a personal reactive smart contract that automatically executes trades on Uniswap V2 when predefined price thresholds are reached. Each user deploys their own instance for complete control and privacy over their stop-loss and take-profit orders. This demo extends the principles introduced in the [Reactive Network Demo](https://github.com/Reactive-Network/reactive-smart-contract-demos/tree/main/src/demos/basic), which provides an introduction to building reactive smart contracts that respond to real-time events. -## Contracts - -**Reactive Contract**: [UniswapDemoStopTakeProfitReactive](./UniswapDemoStopTakeProfitReactive.sol) monitors a Uniswap V2 pair's `Sync` events via `UNISWAP_V2_SYNC_TOPIC_0` on Ethereum Sepolia. It tracks user-created stop-loss and take-profit orders by subscribing to lifecycle events (`StopOrderCreated`, `StopOrderCancelled`, `StopOrderExecuted`, `StopOrderPaused`, `StopOrderResumed`) emitted by the callback contract. When reserve changes indicate that a price threshold has been crossed, the contract emits a `Callback` event to trigger order execution. The contract dynamically subscribes to pairs when the first order is created and unsubscribes when all orders for a pair are completed or cancelled, optimizing gas usage. - -**Origin/Destination Chain Contract**: [UniswapDemoStopTakeProfitCallback](./UniswapDemoStopTakeProfitCallback.sol) manages the creation and execution of stop-loss and take-profit orders. Users create orders specifying the pair, direction, amount, and price threshold. When triggered by the Reactive Network, the callback contract performs a final on-chain price verification, transfers tokens from the user's wallet, executes the swap through the Uniswap V2 router, and returns the purchased tokens to the user. The contract includes retry logic, pausable orders, and emergency rescue functions for stuck funds. Each user deploys their own instance for isolated order management and complete control over their trading strategy. - -**Rescuable Base Contract**: [RescuableBase](./RescuableBase.sol) provides emergency rescue functionality for ETH and ERC20 tokens that may become stuck in the callback contract. This abstract contract allows the owner to recover funds with specific amounts or full balances through safe transfer mechanisms. - -## Further Considerations - -The demo showcases essential stop-loss and take-profit functionality but can be improved with: - -- **Advanced Order Types:** Supporting trailing stops, conditional orders, and time-based constraints. -- **Multi-Pair Order Management:** Aggregating orders across multiple pairs for unified portfolio management. -- **Slippage Protection:** Adding configurable slippage limits to prevent unfavorable execution prices. -- **Gas Optimization:** Batching order execution and reducing storage costs for large order volumes. -- **Support for Arbitrary DEXes:** Extending functionality to work with Uniswap V3, SushiSwap, and other decentralized exchanges. - ## Deployment & Testing ### Environment Variables @@ -45,157 +27,227 @@ Before proceeding further, configure these environment variables: > > If you see the following message: `error: unexpected argument '--broadcast' found`, it means your Foundry version (or local setup) does not support the `--broadcast` flag for `forge create`. Simply remove `--broadcast` from your command and re-run it. -### Step 1 — Test Tokens and Liquidity Pool +--- + +## Contracts + +**Reactive Contract**: [UniswapDemoStopTakeProfitReactive](./UniswapDemoStopTakeProfitReactive.sol) monitors a Uniswap V2 pair's `Sync` events via `UNISWAP_V2_SYNC_TOPIC_0` on Ethereum Sepolia. It tracks user-created stop-loss and take-profit orders by subscribing to lifecycle events (`StopOrderCreated`, `StopOrderCancelled`, `StopOrderExecuted`, `StopOrderPaused`, `StopOrderResumed`) emitted by the callback contract. When reserve changes indicate that a price threshold has been crossed, the contract emits a `Callback` event to trigger order execution. The contract dynamically subscribes to pairs when the first order is created and unsubscribes when all orders for a pair are completed or cancelled, optimizing gas usage. + +**Origin/Destination Chain Contract**: [UniswapDemoStopTakeProfitCallback](./UniswapDemoStopTakeProfitCallback.sol) manages the creation and execution of stop-loss and take-profit orders. Users create orders specifying the pair, direction, amount, and price threshold. When triggered by the Reactive Network, the callback contract performs a final on-chain price verification, transfers tokens from the user's wallet, executes the swap through the Uniswap V2 router, and returns the purchased tokens to the user. The contract includes retry logic, pausable orders, and emergency rescue functions for stuck funds. Each user deploys their own instance for isolated order management and complete control over their trading strategy. + +**Rescuable Base Contract**: [RescuableBase](./RescuableBase.sol) provides emergency rescue functionality for ETH and ERC20 tokens that may become stuck in the callback contract. This abstract contract allows the owner to recover funds with specific amounts or full balances through safe transfer mechanisms. + +--- + +## System Workflow + +### How It Works — End-to-End Flow + +``` +User creates order on Callback Contract (Sepolia) + ↓ +Callback Contract emits StopOrderCreated event + ↓ +Reactive Contract (Reactive Network) detects event → subscribes to the Uniswap V2 Pair's Sync events + ↓ +Uniswap V2 Pair emits Sync event on every swap/liquidity change + ↓ +Reactive Contract checks: has the price crossed the threshold? + ↓ (if YES) +Reactive Contract emits Callback event → Reactive Network calls executeOrder() on Callback Contract + ↓ +Callback Contract verifies price on-chain, pulls tokens from user wallet, executes swap via Uniswap V2 Router + ↓ +Purchased tokens sent back to user wallet + ↓ +Callback Contract emits StopOrderExecuted event + ↓ +Reactive Contract receives event → unsubscribes from pair if no more active orders +``` + +### Key Design Decisions + +- **Per-user deployment**: Each user deploys their own Callback contract for full isolation and privacy. +- **Dynamic subscriptions**: The Reactive contract only listens to pairs that have active orders, saving gas. +- **On-chain price verification**: Even after the Reactive layer triggers execution, the Callback contract independently verifies the price before swapping — protecting against stale triggers. +- **Retry logic**: If execution fails (e.g., slippage), the order stays active and can be retried on the next price event. + +--- -To test live, you'll need testnet tokens and a Uniswap V2 liquidity pool. Use pre-existing tokens or deploy your own. +## Step-by-Step Walkthrough +### Phase 1: Setup Infrastructure + +**Step 1 — Get test tokens and note token addresses** + +Either use the pre-existing test tokens: ```bash export TOKEN0=0x2AFDE4A3Bca17E830c476c568014E595EA916a04 export TOKEN1=0x7EB2Ad352369bb6EDEb84D110657f2e40c912c95 ``` -To deploy ERC-20 tokens (if needed), provide a token name and symbol as constructor arguments. Each token mints 100 units to the deployer: - +Or deploy your own ERC-20 tokens (each mints 100 units to the deployer): ```bash forge create --broadcast --rpc-url $DESTINATION_RPC --private-key $DESTINATION_PRIVATE_KEY src/demos/uniswap-v2-stop-order/UniswapDemoToken.sol:UniswapDemoToken --constructor-args TK1 TK1 ``` -Repeat the command for the second token, using a different name and symbol: - ```bash forge create --broadcast --rpc-url $DESTINATION_RPC --private-key $DESTINATION_PRIVATE_KEY src/demos/uniswap-v2-stop-order/UniswapDemoToken.sol:UniswapDemoToken --constructor-args TK2 TK2 ``` -### Step 2 — Uniswap V2 Pair +--- -If you use pre-existing tokens shown in Step 1, export the address of their Uniswap pair: +**Step 2 — Create or export the Uniswap V2 Pair** +Use the pre-existing pair: ```bash export UNISWAP_V2_PAIR_ADDR=0x1DD11fD3690979f2602E42e7bBF68A19040E2e25 ``` -To create a new pair, use the Uniswap V2 Factory contract `0x7E0987E5b3a30e3f2828572Bb659A548460a3003` and the token addresses deployed in Step 1. After the transaction, retrieve the pair's address from the `PairCreated` event on [Sepolia scan](https://sepolia.etherscan.io/). - +Or create a new pair via the Uniswap V2 Factory (`0x7E0987E5b3a30e3f2828572Bb659A548460a3003`): ```bash cast send 0x7E0987E5b3a30e3f2828572Bb659A548460a3003 'createPair(address,address)' --rpc-url $DESTINATION_RPC --private-key $DESTINATION_PRIVATE_KEY $TOKEN0 $TOKEN1 ``` -> 📝 **Note** -> -> The token with the smaller hexadecimal address becomes `token0`; the other is `token1`. Compare token contract addresses alphabetically or numerically in hexadecimal format to determine their order. +> 📝 **Note**: The token with the smaller hexadecimal address becomes `token0`; the other is `token1`. -### Step 3 — Add Liquidity to the Pool +--- -Transfer liquidity into the created pool: +**Step 3 — Add liquidity to the pool** +Transfer TOKEN0 into the pair: ```bash cast send $TOKEN0 'transfer(address,uint256)' --rpc-url $DESTINATION_RPC --private-key $DESTINATION_PRIVATE_KEY $UNISWAP_V2_PAIR_ADDR 10000000000000000000 ``` +Transfer TOKEN1 into the pair: ```bash cast send $TOKEN1 'transfer(address,uint256)' --rpc-url $DESTINATION_RPC --private-key $DESTINATION_PRIVATE_KEY $UNISWAP_V2_PAIR_ADDR 10000000000000000000 ``` -Mint the liquidity pool tokens to your wallet: - +Mint LP tokens to your wallet: ```bash cast send $UNISWAP_V2_PAIR_ADDR 'mint(address)' --rpc-url $DESTINATION_RPC --private-key $DESTINATION_PRIVATE_KEY $USER_WALLET ``` -### Step 4 — Callback Contract +--- + +### Phase 2: Deploy Contracts -Deploy the callback contract on Ethereum Sepolia, using the Uniswap V2 router at `0xC532a74256D3Db42D0Bf7a0400fEFDbad7694008`. You should also pass your wallet address as the owner and the Sepolia callback proxy address. Assign the `Deployed to` address from the response to `CALLBACK_ADDR`. +**Step 4 — Deploy the Callback Contract on Sepolia** + +Uses Uniswap V2 router at `0xC532a74256D3Db42D0Bf7a0400fEFDbad7694008`. Assign `Deployed to` to `CALLBACK_ADDR`. ```bash forge create --broadcast --rpc-url $DESTINATION_RPC --private-key $DESTINATION_PRIVATE_KEY src/demos/uniswap-v2-stop-take-profit-order/UniswapDemoStopTakeProfitCallback.sol:UniswapDemoStopTakeProfitCallback --value 0.02ether --constructor-args $USER_WALLET $DESTINATION_CALLBACK_PROXY_ADDR 0xC532a74256D3Db42D0Bf7a0400fEFDbad7694008 ``` -### Step 5 — Reactive Contract +--- + +**Step 5 — Deploy the Reactive Contract on Reactive Network** -Deploy the Reactive contract specifying your wallet address as the owner and the callback contract address from Step 4. Assign the `Deployed to` address to `REACTIVE_ADDR`. +Assign `Deployed to` to `REACTIVE_ADDR`. ```bash forge create --broadcast --rpc-url $REACTIVE_RPC --private-key $REACTIVE_PRIVATE_KEY src/demos/uniswap-v2-stop-take-profit-order/UniswapDemoStopTakeProfitReactive.sol:UniswapDemoStopTakeProfitReactive --value 0.1ether --constructor-args $USER_WALLET $CALLBACK_ADDR ``` -### Step 6 — Authorize Token Spending +--- + +### Phase 3: Authorize & Create Orders -Authorize the callback contract to spend your tokens. The last parameter specifies the amount to approve. For tokens with 18 decimals, the example below authorizes the callback contract to spend one token: +**Step 6 — Authorize token spending** +Allow the Callback contract to pull tokens from your wallet when executing orders: ```bash cast send $TOKEN0 'approve(address,uint256)' --rpc-url $DESTINATION_RPC --private-key $DESTINATION_PRIVATE_KEY $CALLBACK_ADDR 1000000000000000000 ``` -### Step 7 — Create a Stop-Loss Order +--- -Create a stop-loss order that will sell `token0` for `token1` when the price drops below a threshold. The parameters are: +**Step 7 — Create a Stop-Loss Order** -- `UNISWAP_V2_PAIR_ADDR`: The pair address from Step 2. -- `SELL_TOKEN0`: `true` to sell `token0`, `false` to sell `token1`. -- `AMOUNT`: Amount of tokens to sell (in wei). -- `COEFFICIENT`: Price calculation coefficient (typically `10000` for 4 decimal precision). -- `THRESHOLD`: Price threshold that triggers the order. -- `ORDER_TYPE`: `0` for stop-loss, `1` for take-profit. - -Example creating a stop-loss order: +Parameters: +- `pair`: Uniswap V2 pair address +- `sellToken0`: `true` to sell token0, `false` to sell token1 +- `amount`: Amount in wei to sell +- `coefficient`: Precision factor (typically `10000`) +- `threshold`: Price threshold × coefficient (e.g., `8000` = price of 0.8 when coefficient = 10000) +- `orderType`: `0` = stop-loss ```bash cast send $CALLBACK_ADDR 'createStopOrder(address,bool,uint256,uint256,uint256,uint8)' --rpc-url $DESTINATION_RPC --private-key $DESTINATION_PRIVATE_KEY $UNISWAP_V2_PAIR_ADDR true 1000000000000000000 10000 8000 0 ``` -This creates a stop-loss order to sell 1 token0 when the price drops to 0.8 (8000/10000). +*This creates a stop-loss order to sell 1 token0 when the price drops to 0.8.* -### Step 8 — Create a Take-Profit Order +--- -Similarly, create a take-profit order that will sell when the price rises above a threshold: +**Step 8 — Create a Take-Profit Order** +Same parameters as above, but `orderType` = `1` and threshold above current price: ```bash cast send $CALLBACK_ADDR 'createStopOrder(address,bool,uint256,uint256,uint256,uint8)' --rpc-url $DESTINATION_RPC --private-key $DESTINATION_PRIVATE_KEY $UNISWAP_V2_PAIR_ADDR true 1000000000000000000 10000 12000 1 ``` -This creates a take-profit order to sell 1 token0 when the price rises to 1.2 (12000/10000). +*This creates a take-profit order to sell 1 token0 when the price rises to 1.2.* + +--- -### Step 9 — Trigger Order Execution +### Phase 4: Trigger & Verify Execution -To trigger the orders, adjust the exchange rate by performing swaps directly through the pair. Transfer tokens to the pair: +**Step 9 — Move the price to trigger order execution** +Transfer tokens directly into the pair to shift reserves: ```bash cast send $TOKEN0 'transfer(address,uint256)' --rpc-url $DESTINATION_RPC --private-key $DESTINATION_PRIVATE_KEY $UNISWAP_V2_PAIR_ADDR 20000000000000000 ``` -Execute a swap to change the price: - +Execute an imbalanced swap to move the price: ```bash cast send $UNISWAP_V2_PAIR_ADDR 'swap(uint,uint,address,bytes calldata)' --rpc-url $DESTINATION_RPC --private-key $DESTINATION_PRIVATE_KEY 0 5000000000000000 $USER_WALLET "0x" ``` -The reactive contract will detect the price change and automatically trigger the appropriate orders. The execution will be visible on [Sepolia scan](https://sepolia.etherscan.io/). +The `Sync` event emitted by this swap is detected by the Reactive Contract. If the new price crosses your threshold, the order executes automatically within a few blocks. + -### Step 10 — Managing Orders +--- -You can pause, resume, or cancel orders using the callback contract: +### Phase 5: Managing Orders -Pause an order: +**Step 10 — Pause an order** ```bash cast send $CALLBACK_ADDR 'pauseStopOrder(uint256)' --rpc-url $DESTINATION_RPC --private-key $DESTINATION_PRIVATE_KEY 0 ``` -Resume a paused order: +**Resume a paused order** ```bash cast send $CALLBACK_ADDR 'resumeStopOrder(uint256)' --rpc-url $DESTINATION_RPC --private-key $DESTINATION_PRIVATE_KEY 0 ``` -Cancel an order: +**Cancel an order permanently** ```bash cast send $CALLBACK_ADDR 'cancelStopOrder(uint256)' --rpc-url $DESTINATION_RPC --private-key $DESTINATION_PRIVATE_KEY 0 ``` -View all orders: +**View all orders (read-only)** ```bash cast call $CALLBACK_ADDR 'getAllOrders()' --rpc-url $DESTINATION_RPC ``` -View active orders: +**View active orders only (read-only)** ```bash cast call $CALLBACK_ADDR 'getActiveOrders()' --rpc-url $DESTINATION_RPC -``` \ No newline at end of file +``` + +--- + +## Further Considerations + +The demo showcases essential stop-loss and take-profit functionality but can be improved with: + +- **Advanced Order Types:** Supporting trailing stops, conditional orders, and time-based constraints. +- **Multi-Pair Order Management:** Aggregating orders across multiple pairs for unified portfolio management. +- **Slippage Protection:** Adding configurable slippage limits to prevent unfavorable execution prices. +- **Gas Optimization:** Batching order execution and reducing storage costs for large order volumes. +- **Support for Arbitrary DEXes:** Extending functionality to work with Uniswap V3, SushiSwap, and other decentralized exchanges. \ No newline at end of file