Agent-driven DeFi protocol using Markov Chains to automate synthetic yield farming on RSK.
Monte-Carlo is an agent-driven DeFi protocol on RSK that issues synthetic assets (s-Assets) collateralized by tRBTC and uses autonomous Fetch.ai agents plus a Markov-Chain predictive engine (with Monte-Carlo simulation for risk) to pick, mint, monitor, and exit synthetic positions automatically.
Goals & value proposition
Let users gain exposure to asset yields (ETH, SOV, etc.) without swapping or needing liquidity for the underlying asset.
Solve cold-start for new protocols by training predictive logic on proxy historic data (e.g., BTC) and mapping behaviors to synthetic instruments.
Provide agentic automation (data → prediction → on-chain action) so users can define goals and have the system manage execution.
Make positions composable (ERC20 s-Assets) so they can later be used in other DeFi flows.
High-level architecture (three layers)
Predictive Model (Markov Chain + Monte-Carlo)
Trained on proxy asset historical returns. Produces recommendations and scenario distributions.
Agentic Layer (Fetch.ai uAgents in Python)
DataFetcherAgent: fetches historical and live price streams from Pyth (or fallbacks).
MarkovModelAgent: turns historical series into state sequences, estimates transition matrix, outputs asset recommendations + confidence.
PositionManagerAgent: orchestrates user goals → prediction → on-chain mint/burn using web3.py + vault contract.
On-Chain Layer (RSK Solidity)
Vault.sol: central contract holding tRBTC collateral and minting/burning s-Assets.
sAsset.sol: ERC-20 representation of synthetic exposure (sETH, sSOV, ...).
Pyth Oracle: on-chain price feeds read by Vault and agent verification.
Core on-chain workflow (conceptual)
User deposits C tRBTC to Vault.
PositionManager asks MarkovModelAgent for target asset (e.g., ETH).
Vault reads Pyth price P_asset_in_RBTC and mints sAsset sized to the collateral value.
tRBTC remains locked as collateral in the Vault.
To exit: burn sAsset → Vault returns RBTC equivalent at then-current oracle price (minus fees).
Smart-contract interface (essential functions & events) Vault.sol — key state and functions (conceptual) contract Vault { // State address public governor; // timelock / multisig owner mapping(address => bool) public isSAsset; // allowed synthetic tokens IERC20 public tRBTC; // collateral token interface IPyth public pyth; // price oracle
// Core API
function depositAndMint(address sAsset, uint256 collateralAmount, address to) external returns (uint256 mintedAmount);
function burnAndWithdraw(address sAsset, uint256 sAssetAmount, address to) external returns (uint256 returnedCollateral);
function setSAsset(address sAsset, bool allowed) external;
function emergencyWithdraw(address to) external; // only governance
// Events
event Minted(address indexed user, address indexed sAsset, uint256 collateralIn, uint256 sAssetOut);
event Burned(address indexed user, address indexed sAsset, uint256 sAssetIn, uint256 collateralOut);
event CollateralLocked(address indexed user, uint256 amount);
}
sAsset.sol
Standard ERC-20 with mint and burn callable only by Vault (access control).
Event: Transfer + Minted/Burned hooks if desired.
Math: minting and burning rules (step-by-step)
Definitions:
C = collateral deposited (in tRBTC, decimals normalized)
P = price of 1 target asset in tRBTC (Pyth feed gives P_asset_in_RBTC)
f_mint = mint fee (e.g., 0.001 = 0.1%)
f_burn = burn/withdraw fee
minted_asset_amount = A
Minting formula
A = (C / P) * (1 - f_mint)
Reasoning: collateral C (in RBTC) divided by price per asset P gives how many units of the asset that collateral represents. Apply mint fee.
Burning formula (user withdraws)
If user burns A_burn: returned_collateral = A_burn * P_current * (1 - f_burn)
Numeric example (showing digits)
Example parameters:
C = 3.00000000 tRBTC (user deposits 3.0)
P = 0.50000000 tRBTC per ETH (i.e., 1 ETH = 0.5 tRBTC)
f_mint = 0.005 (0.5%)
Step-by-step:
Compute C / P:
3.00000000 / 0.50000000 = 6.00000000 (units of ETH)
Apply mint fee: (1 - f_mint) = 0.995
A = 6.00000000 * 0.995 = 5.97000000 sETH minted So user receives 5.97 sETH representing an initial value of ~3 tRBTC.
If later ETH price becomes P_new = 1.00000000 tRBTC per ETH:
returned_collateral = A * P_new * (1 - f_burn) Assume f_burn = 0.005:
A * P_new = 5.97000000 * 1.00000000 = 5.97000000 tRBTC
Apply burn fee: 5.97000000 * 0.995 = 5.94015000 tRBTC returned → more than initial 3.0 tRBTC → profit realized.
Predictive model: Markov Chain + Monte-Carlo usage What the Markov Chain is modeling
State space: discretized states representing recent yield/return regimes (examples):
H = HIGH yield state (large positive returns)
N = NEUTRAL
L = LOW / NEGATIVE yield
Observation series: daily/ hourly returns of proxy asset (e.g., BTC).
Convert returns r_t to state s_t by thresholding or quantiles (e.g., top 20% → H, middle 60% → N, bottom 20% → L).
Estimating transition matrix
Count transitions count[i->j] for state i -> j across training window.
P[i->j] = count[i->j] / sum_j count[i->j]
Use Laplace smoothing: P[i->j] = (count[i->j] + alpha) / (sum_j count[i->j] + alpha * K), where K = number of states.
How recommendation is produced
For each candidate asset (ETH, SOV, etc.), compute its transition matrix from proxy historical data.
Evaluate the probability of entering H in the next time step(s) given current state s_t: P(s_{t+1}=H | s_t).
Optionally compute expected return over horizon h using powers of transition matrix: P^{(h)} gives distribution after h steps.
Combine with Monte-Carlo: simulate many trajectories over h using P to estimate distribution of asset returns or value of s-Asset collateral over time. This gives risk metrics (median expected return, 95% VaR, chance to reach user's goal).
Monte-Carlo role
The Markov chain defines transition probabilities; Monte-Carlo runs stochastic paths from the current state to simulate many possible outcomes.
Use the simulated distribution to:
Compute probability of hitting user’s target (e.g., doubling collateral) before a deadline.
Compute expected time to target.
Estimate drawdown distribution and VaR.
Model hyperparameters & engineering
Window size (lookback): 90/180/365 days — tuned via backtest.
State discretization: 3–7 states; more states = more granularity but need more data.
Recalibration cadence: daily or intraday depending on asset volatility.
Confidence threshold: only act when expected return/probability > threshold (protects against noisy predictions).
Ensembles: combine Markov predictions across multiple proxy assets and weight them.
Agentic layer details (components & responsibilities) DataFetcherAgent
Tasks:
Query Pyth public APIs for historical price series and real-time ticks.
Provide cleaned, uniformly time-sampled series.
Backfill missing points (linear interp or hold-last) and flag data quality issues.
Endpoints:
GET /historical?symbol=BTC&start=...&end=...&resolution=1d
GET /tick?symbol=ETH
MarkovModelAgent
Tasks:
Convert history → returns → discretized states.
Compute transition matrix with smoothing.
Estimate stationary distribution and hitting probabilities.
Run Monte-Carlo simulations using transition probabilities to generate outcome distributions.
Return [asset, score, probability_of_target, expected_time].
API:
POST /predict with list of candidate assets and user horizon & risk tolerance.
Response: sorted recommendations with confidence metrics.
PositionManagerAgent
Tasks:
Accept user input (deposit request, risk profile, goal).
Query MarkovModelAgent for recommendation.
Construct on-chain transaction (web3.py) to Vault.depositAndMint(...) with gas, nonce, sign.
Monitor position (value growth) and optionally trigger burns when goal hit.
Enforce safety rules (max exposure per user, check on-chain collateralization).
Key implementation details:
Use non-custodial flows — users sign transactions locally whenever possible. For automated on-behalf-of flows, use delegated signatures or smart wallet setups (meta-txs) with user consent.
Ensure idempotency (retry logic, track tx hash and receipt).
Verification: double-check Pyth price on-chain before sending.
Example pseudocode (PositionManagerAgent decision + tx):
rec = markov_agent.get_recommendation(user_goal, assets) if rec.probability_of_target >= user.min_probability: tx = vault_contract.functions.depositAndMint(rec.sAsset, collateralAmount, user.address) signed = account.signTransaction(tx.buildTransaction({'gas':..., 'nonce':...})) txhash = web3.eth.sendRawTransaction(signed.rawTransaction) wait_for_receipt(txhash)
Governance, fees, and tokenomics
Fees:
Mint fee, burn fee, performance fee on realized gains.
Small protocol fee directed to treasury for maintenance and agent incentivization.
Governance:
Multisig / timelock for sensitive parameters (fees, upgrade addresses).
Future DAO token for protocol governance (optional).
Incentives:
Optionally pay Fetch.ai agent operators small reward for data compute or for running PositionManager at scale.
Keep gas/operation costs transparent and optionally subsidize first-time deposits.
Collateralization, liquidation, and risk management
Collateralization ratio (CR): Vault must enforce minimal collateralization to protect against oracle moves.
E.g., initial_CR = 1.0 (fully backed) or more conservative initial_CR = 1.1 (10% haircut)
Liquidation:
If value of collateral / implied liability < liquidation_threshold (e.g., 1.0 or 0.95), position is flagged.
Keeper bots (or agent) can trigger liquidation with a penalty fee that goes to keepers.
Oracle risk mitigations:
Use multiple oracles or TWAP fallback (Pyth primary, Chainlink or on-chain TWAP secondary).
Apply sanity checks (max price movement limits per block/time window).
MEV / front-running mitigation:
Consider batching, time delay, or submitting critical Tx via private relays (Flashbots-like) for large operations.
Agent safety:
Agents must respect max_risk_per_user, max_total_exposure config flags in Vault.
Security & attack surface
Smart-contract risks: reentrancy (use checks-effects-interactions), integer over/underflow (use SafeMath for older compilers), access control for mint/burn.
Oracle manipulation / price feed attacks: validate against multiple feeds, reject large jumps without confirmations.
Agent compromise: ensure agent keys are stored in hardware KMS; multi-sig for privileged operations; kill switches in Vault to pause agent-driven actions.
Upgradeability risks: if using proxies, ensure timelock and multisig guardrails.
Tests & audits: required external audit + bug bounty program.
Testing, simulation & backtesting
Unit tests: Hardhat / Foundry for Solidity. Mock Pyth oracle contract to simulate price feeds. Tests for mint/burn math, edge cases.
Integration tests: run agent + vault in localnet (Ganache/Hardhat node).
Backtesting:
Walk-forward testing on proxy data (BTC or ETH) — simulate the exact agent decision logic over historical windows and compute P&L, hit-rate, drawdown.
Include realistic gas and fees in the simulation.
Monte-Carlo stress tests:
Use synthetic scenarios from Markov simulations to estimate distribution of returns and maximum loss.
Fuzzing & property tests for invariants (e.g., totalCollateral >= sumOfBacking).
Monitoring, observability & ops
Metrics:
Total Value Locked (TVL), open positions, liquidation events, agent actions per hour, model confidence distribution, oracle discrepancies.
Tools:
Prometheus + Grafana, logs to Elastic or CloudWatch, alerting for unusual spikes or oracle feed anomalies.
On-call runbooks:
Steps for pausing Vault, reverting agent permissions, emergency withdrawals, contacting multisig.
Deployment & developer workflow (recommended)
Smart contracts: develop & test locally → Hardhat/Foundry tests.
Audit & bug bounty.
Deploy to RSK testnet (RSK Testnet) — verify contracts on block explorer.
Configure Pyth addresses and sAsset tokens.
Deploy agents in containers (Docker), orchestrate via Kubernetes or systemd.
CI: run unit tests, run a small simulated backtest on PRs.
Useful commands (example Hardhat style):
npx hardhat compile npx hardhat test npx hardhat run --network rsk scripts/deploy.js
(adjust to your toolchain — Truffle/Foundry/etc.)
API & integration points (suggested)
Agent HTTP endpoints
POST /predict → {"assets":["ETH","SOV"],"horizon":"7d","risk":"medium" }
POST /monitor/position → open a watch for a minted sAsset and user target
Webhooks
On goal reached: notify frontend / user; agent can optionally trigger burn (user preference).
Frontend
Wallet connect for deposit (user signs TX).
Dashboard: shows active positions, simulated paths, probability to target, fees.
Example end-to-end scenario (detailed, numeric, step-by-step)
User goal: deposit 3.0 tRBTC and “double” to 6.0 tRBTC.
User calls frontend, chooses deposit = 3.0 tRBTC, goal target_value = 6.0 tRBTC.
PositionManager queries MarkovModelAgent:
MarkovModelAgent returns asset = ETH, probability_to_double_in_30d = 0.28, expected_time = 45d (numbers are example output).
User confirms action. Backend prepares depositAndMint tx with sAsset = sETH.
Vault logic (on-chain): read Pyth P = 0.50000000 tRBTC/ETH at mint time.
A = C / P * (1 - f_mint) as earlier: 3.0 / 0.5 * 0.995 = 5.97 sETH.
Agent monitors price. If ETH price reaches 1.00000000 tRBTC/ETH:
Position value = A * P_new = 5.97 * 1.0 = 5.97 tRBTC
After burn fee f_burn = 0.005: 5.97 * 0.995 = 5.94015 tRBTC. The user is short of 6.0 but close — depending on fee choices the exact target may be set with fees accounted for.
If target reached (by agent’s criteria), PositionManager submits burnAndWithdraw and user receives returned tRBTC.g
Monte-Carlo is a three-layer decentralized system designed to automate synthetic yield farming. It combines on-chain smart contracts, autonomous AI agents, and a Markov-Chain predictive engine that uses Monte-Carlo simulations for risk analysis.
Technologies and Their Roles Layer Key Technologies Purpose On-Chain Layer Solidity, Rootstock (RSK) EVM Locks tRBTC collateral and mints/burns synthetic ERC-20 tokens (s-Assets). Price Oracle Pyth Network Provides real-time RBTC/asset price feeds to the Vault contract. Agentic Layer Python 3, Fetch.ai uAgents, web3.py Off-chain intelligence: fetches data, predicts the best asset, and submits blockchain transactions. Predictive Model Markov Chain with Monte-Carlo simulations (NumPy, pandas, SciPy) Forecasts high-yield assets and runs scenario simulations to estimate risk and time-to-target. Development & Ops Hardhat/Foundry, Docker/Kubernetes, Prometheus/Grafana Smart-contract testing, agent deployment, and monitoring. How the Components Work Together
User specifies a goal (for example, “double my 3 tRBTC”).
DataFetcherAgent retrieves historical BTC/ETH/SOV price data from Pyth.
MarkovModelAgent builds a transition matrix and runs Monte-Carlo simulations to estimate which asset is most likely to reach a high-yield state.
PositionManagerAgent signs and sends a depositAndMint transaction to Vault.sol using web3.py.
Vault checks the on-chain Pyth feed and mints the appropriate s-Asset tokens.
tRBTC remains locked as collateral.
PositionManagerAgent monitors the position and automatically calls burnAndWithdraw once the user’s target is reached.
Notable or Hacky Details
Proxy Data Training: The Markov model trains on BTC historical data to avoid the cold-start problem for new synthetic tokens.
Agent Orchestration: Independent uAgents (fetcher, predictor, manager) communicate via lightweight messaging, making the system modular and testable.
Risk Simulation: Monte-Carlo paths provide value-at-risk and expected time-to-goal estimates before committing funds on-chain.
Transaction Bundling: The PositionManager signs and broadcasts transactions atomically to reduce the chance of front-running or partial state changes.
Partner Technology Benefits
Pyth Network delivers low-latency, reliable on-chain price feeds essential for accurate mint/burn calculations.
Fetch.ai provides a robust agent framework with built-in state handling and secure messaging, removing the need to create custom automation infrastructure.
This integration of EVM smart contracts, autonomous AI agents, and Markov/Monte-Carlo modeling creates a modular, automated, and non-custodial synthetic yield farming protocol.