$$\ $$\ $$\ $$\ $$\ $$\ $$\ $$\ $$\
$$ | $\ $$ | $$ | $$ |\$$\ $$ |\__| $$ | $$ |
$$ |$$$\ $$ | $$$$$$\ $$$$$$\ $$ | $$$$$$$ | \$$\ $$ / $$\ $$$$$$\ $$ | $$$$$$$ |
$$ $$ $$\$$ |$$ __$$\ $$ __$$\ $$ |$$ __$$ | \$$$$ / $$ |$$ __$$\ $$ |$$ __$$ |
$$$$ _$$$$ |$$ / $$ |$$ | \__|$$ |$$ / $$ | \$$ / $$ |$$$$$$$$ |$$ |$$ / $$ |
$$$ / \$$$ |$$ | $$ |$$ | $$ |$$ | $$ | $$ | $$ |$$ ____|$$ |$$ | $$ |
$$ / \$$ |\$$$$$$ |$$ | $$ |\$$$$$$$ | $$ | $$ |\$$$$$$$\ $$ |\$$$$$$$ |
\__/ \__| \______/ \__| \__| \_______| \__| \__| \_______|\__| \_______|
Maximize your DeFi yields with AI-powered recommendations backed by human consensus and trustless automation
DeFi yield farming is broken for everyday users:
- Information Overload: 100+ protocols across 20+ chains with constantly changing APYs
- No Intelligence: Users must manually track yields, compare rates, and execute rebalances
- Sybil Attacks: Bots manipulate yield aggregators with fake deposits and wash trading
- High Gas Fees: Manual rebalancing costs $50-200 per transaction on Ethereum mainnet
- No Social Proof: Traditional yield aggregators can't distinguish real users from bots
- Complexity Barrier: Regular users struggle with bridging, approvals, and multi-step workflows
The Core Issue: DeFi needs intelligent, trustworthy yield optimization that verifies real humans and automates complex strategies.
WorldYield is an AI-powered DeFi yield optimizer that combines:
- ** AI Agent**: Chat with Groq Llama 3.3 70B to get personalized yield recommendations
- ** Chainlink Runtime Environment (CRE)**: Automated cross-chain yield strategies execute trustlessly
- ** World ID Verification**: Sybil-resistant human verification via iris scanning
- ** Human Consensus Scoring**: Protocols with more verified humans get higher trust scores
- ** Automated Execution**: Agent can supply/withdraw funds with your permission
- ** Real-Time APY Data**: Smart contract reads from Aave v3, Compound v3, and more
Key Innovation: Human Consensus Boost System
- Verified humans get +1.4% APY boost automatically
- Additional +0.06% per 100 humans who chose the same protocol
- Effective APY = Base APY + Verified Boost + Consensus Boost
- Incentivizes collective intelligence and discourages bot manipulation
Example:
Aave v3 USDC on Base Sepolia:
├─ Base APY: 3.5%
├─ Verified Boost: +1.4% (World ID verified)
├─ Consensus Boost: +0.51% (847 verified humans deposited)
└─ Effective APY: 5.41%
┌─────────────────────────────────────────────────────────────────────┐
│ USER LAYER │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ [User Wallet] ─→ [World ID Verification] ─→ [Nullifier Hash] │
│ │ (World Chain Sepolia) │
│ │ │
│ ├─→ [Dashboard - Pool Tab] │
│ │ └─→ Manual Supply/Withdraw to Aave v3 │
│ │ - Connect wallet (wagmi) │
│ │ - Approve USDC → Supply/Withdraw │
│ │ - View balance & transaction history │
│ │ │
│ ├─→ [Dashboard - Agent Tab] │
│ │ └─→ AI Chat Interface (Mastra + Groq) │
│ │ - "What's the best yield for USDC?" │
│ │ - Agent fetches CRE data + human consensus │
│ │ - "Supply 100 USDC to Aave" → Auto-execute │
│ │ - Action buttons appear for confirmations │
│ │ │
│ └─→ [Dashboard - Stats Tab] │
│ └─→ View positions, yields, human consensus │
│ │
└───────────────────────────────┬─────────────────────────────────────┘
│
┌───────────▼────────────────┐
│ Backend API (Next.js) │
│ │
│ /api/pool/execute │
│ - Server-side tx exec │
│ - Private key handling │
│ │
│ /api/worldid │
│ - Nullifier storage │
│ - CRE config sync │
│ │
│ /api/agent │
│ - Mastra integration │
│ - CRE yield fetcher │
└───────────┬────────────────┘
│
┌───────────────────────────────▼─────────────────────────────────────┐
│ AI & AUTOMATION LAYER │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ [Mastra Agent Framework] │
│ │ │
│ ├─→ Groq Llama 3.3 70B Model │
│ │ - Natural language understanding │
│ │ - Yield recommendations │
│ │ - Transaction intent parsing │
│ │ │
│ └─→ CRE Yield Fetcher Tool │
│ - Calls Chainlink CRE workflow │
│ - Fetches real-time APY data │
│ - Applies human consensus boost │
│ │
│ [Chainlink Runtime Environment (CRE)] │
│ │ │
│ ├─→ Yield Optimization Workflow │
│ │ - Scheduled execution (every 5 minutes) │
│ │ - Multi-chain APY comparison │
│ │ - Reads HumanConsensus contract │
│ │ - Calculates optimal protocol │
│ │ │
│ ├─→ Smart Contract Reads │
│ │ - Aave v3 Pool (Base Sepolia) │
│ │ - Compound v3 (Base Sepolia) │
│ │ - HumanConsensus counts │
│ │ - VeraYieldVault positions │
│ │ │
│ └─→ Automated Rebalancing (Future) │
│ - CCIP cross-chain transfers │
│ - Gas-optimized execution │
│ │
└───────────────────────────────┬─────────────────────────────────────┘
│
┌───────────────────────────────▼─────────────────────────────────────┐
│ BLOCKCHAIN LAYER │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ [World Chain Sepolia - Identity] │
│ └─→ WorldIDGate.sol (0x0bfB...C619) │
│ - World ID verification gateway │
│ - Nullifier hash validation │
│ - Sybil-resistant proof checking │
│ │
│ [Ethereum Sepolia - Consensus & Ledger] │
│ │ │
│ ├─→ HumanConsensus.sol (0x6828...509f) │
│ │ - Tracks verified humans per protocol │
│ │ - humanCount["aave-base-usdc"] = 847 │
│ │ - enter(wallet, poolId) on deposit │
│ │ - exit(wallet, poolId) on withdrawal │
│ │ │
│ ├─→ VeraYieldVault.sol (0x5227...E812) │
│ │ - Position ledger (amount, protocol, receipt token) │
│ │ - recordPosition(wallet, amount, protocol, chainId) │
│ │ - updatePosition(wallet, newProtocol) │
│ │ │
│ └─→ MandateStorage.sol (0x9476...CB3f) │
│ - User investment preferences │
│ - Risk tolerance settings │
│ - Auto-rebalance permissions │
│ │
│ [Base Sepolia - DeFi Protocols] │
│ │ │
│ ├─→ Aave v3 Pool (0x8bAB...aE27) │
│ │ - Supply USDC, earn yield │
│ │ - Withdraw with accrued interest │
│ │ - Real-time APY from smart contract │
│ │ │
│ ├─→ Compound v3 (0x6149...118E) │
│ │ - Alternative yield source │
│ │ - Different risk/reward profile │
│ │ │
│ └─→ USDC Token (0xba50...4D5f) │
│ - 6 decimal ERC-20 token │
│ - Approve → Supply/Withdraw │
│ │
└─────────────────────────────────────────────────────────────────────┘
┌─────────────────────────────────────────────────────────────────────┐
│ DATA LAYER (Off-Chain) │
├─────────────────────────────────────────────────────────────────────┤
│ │
│ [CRE Config (config.json)] │
│ - User nullifier: aff6fd77-8df7-41b3-ae6d-8717ee664f35 │
│ - Human boost settings (1.4% + 0.06% per 100 humans) │
│ - Protocol addresses and chain configs │
│ - Updated dynamically from World ID verification │
│ │
│ [LocalStorage / Cookies] │
│ - World ID nullifier hash (client-side + server cookie) │
│ - Private key (optional, for automated agent execution) │
│ - User preferences │
│ │
└─────────────────────────────────────────────────────────────────────┘
- User connects wallet to WorldYield dashboard
- Click "Verify with World ID" button
- World ID QR code appears
- Scan with World App (iris verification)
- Zero-knowledge proof generated and verified
- Unique nullifier hash stored:
- LocalStorage (client-side)
- Secure HTTP-only cookie (server-side)
- CRE
config.json(for workflow automation)
- User is now a "verified human" with boost eligibility
Smart Contract Flow:
WorldIDGate.verify(proof, nullifier) [World Chain Sepolia]
├─→ Validate zero-knowledge proof
├─→ Check nullifier is unique (prevent double-verification)
├─→ Emit: VerificationSuccess(wallet, nullifier, timestamp)
└─→ Return: verified = true
User Actions:
- Navigate to Dashboard → Pool Tab
- Enter amount:
100USDC - Click "Approve USDC"
- MetaMask transaction:
USDC.approve(AavePool, 100e6) - Wait for confirmation (~2-3 seconds on Base Sepolia)
- MetaMask transaction:
- Click "Supply to Aave"
- MetaMask transaction:
AavePool.supply(USDC, 100e6, wallet, 0) - Receive aUSDC tokens (receipt token)
- MetaMask transaction:
- View updated balance in dashboard
Smart Contract Flow:
Aave v3 Pool (Base Sepolia)
├─→ supply(asset: USDC, amount: 100e6, onBehalfOf: user, referralCode: 0)
│ ├─→ Transfer USDC from user to pool
│ ├─→ Mint aUSDC (aToken) to user as receipt
│ ├─→ Update pool reserves and interest rate model
│ └─→ Emit: Supply(reserve, user, onBehalfOf, amount, referral)
│
├─→ HumanConsensus.enter(user, "aave-base-usdc") [Sepolia]
│ ├─→ Require: !isInPool[user]["aave-base-usdc"]
│ ├─→ humanCount["aave-base-usdc"] += 1 (now 848)
│ ├─→ isInPool[user]["aave-base-usdc"] = true
│ └─→ Emit: HumanEntered(user, "aave-base-usdc", 848, timestamp)
│
└─→ VeraYieldVault.recordPosition(user, 100e6, "aave-v3", "aUSDC", 84532)
├─→ positions[user] = Position({
│ amountUSDC: 100e6,
│ protocol: "aave-v3",
│ receiptToken: "aUSDC",
│ depositTimestamp: block.timestamp,
│ active: true,
│ chainId: 84532
│ })
└─→ Emit: PositionRecorded(user, 100e6, "aave-v3", 84532, timestamp)
Result: 100 USDC now earning:
- Base APY: 3.5%
- Verified Boost: +1.4%
- Consensus Boost: +0.51% (848 humans)
- Effective APY: 5.41%
Scenario: User asks for yield recommendations
- Navigate to Dashboard → Agent Tab
- User types: "What's the best yield for my USDC right now?"
Agent Processing:
// 1. Agent receives message
yieldAgent.generate({
messages: [{ role: "user", content: "What's the best yield for my USDC right now?" }]
})
// 2. Agent recognizes yield query → calls CRE tool
async function creYieldFetcherTool() {
// Call CRE endpoint
const response = await fetch('http://localhost:8081/api/yield-data')
const data = await response.json()
return {
protocols: [
{
name: "Aave v3 USDC",
chain: "Base Sepolia",
baseAPY: 3.5,
verifiedBoost: 1.4,
consensusBoost: 0.51, // (848 humans * 0.06%) / 100
effectiveAPY: 5.41,
humanCount: 848,
tvl: "$847K"
},
{
name: "Compound v3 USDC",
chain: "Base Sepolia",
baseAPY: 2.8,
verifiedBoost: 1.4,
consensusBoost: 0.25, // (412 humans * 0.06%) / 100
effectiveAPY: 4.45,
humanCount: 412,
tvl: "$412K"
}
]
}
}
// 3. Agent generates responseAgent Response (Plain Text):
Based on real-time blockchain data from Chainlink CRE, here's what I found:
1. Best Protocol: Aave v3 USDC on Base Sepolia
- Base APY: 3.5%
- Effective APY: 5.41% (includes +1.4% verified boost + 0.51% consensus boost)
- Human Consensus: 848 verified humans chose this protocol
- Why: Highest effective APY with strong human trust signal. Aave v3 is battle-tested with $10B+ TVL historically.
2. Alternative: Compound v3 USDC on Base Sepolia
- Base APY: 2.8%
- Effective APY: 4.45%
- Human Consensus: 412 verified humans
- Why: Slightly lower APY but still competitive. Good alternative if Aave utilization increases.
Recommendation: Deploy to Aave v3 for best risk-adjusted returns. The 848 verified humans provide strong social proof.
Would you like me to supply funds to Aave v3?
Scenario: User asks agent to execute a transaction
- User types: "Yes, supply 50 USDC to Aave"
Agent Processing:
// 1. Agent parses intent
const intent = parseActionsFromResponse("supply 50 USDC to Aave")
// Returns: [{ action: "supply", amount: "50", protocol: "aave" }]
// 2. Agent response includes action
const response = {
text: "I'll supply 50 USDC to Aave v3 on Base Sepolia. This will earn you 5.41% effective APY. Click the button below to execute.",
actions: [
{ action: "supply", amount: "50", protocol: "aave" }
]
}
// 3. UI renders action button
<Button onClick={() => executeAction("supply", "50")}>
Supply 50 USDC to Aave v3
</Button>User clicks button:
Option A: User provides private key (UI input)
// Frontend sends request with user's private key
await fetch('/api/pool/execute', {
method: 'POST',
body: JSON.stringify({
privateKey: userPrivateKey, // User's own key
action: 'supply',
amount: '50'
})
})Option B: Server-side execution (fallback)
// Backend uses SERVER_SIDE_PRIVATE_KEY from .env
// Only for demo/testing - in production, user must signBackend Execution Flow:
// /api/pool/execute/route.ts
// 1. Create wallet from private key
const account = privateKeyToAccount(privateKey)
const walletClient = createWalletClient({
account,
chain: baseSepolia,
transport: http()
})
// 2. Check USDC allowance
const allowance = await walletClient.readContract({
address: USDC_ADDRESS,
abi: ERC20_ABI,
functionName: 'allowance',
args: [account.address, AAVE_POOL_ADDRESS]
})
// 3. Approve if needed
if (allowance < parseUnits(amount, 6)) {
const approveTx = await walletClient.writeContract({
address: USDC_ADDRESS,
abi: ERC20_ABI,
functionName: 'approve',
args: [AAVE_POOL_ADDRESS, parseUnits(amount, 6)]
})
await publicClient.waitForTransactionReceipt({ hash: approveTx })
}
// 4. Execute supply
const supplyTx = await walletClient.writeContract({
address: AAVE_POOL_ADDRESS,
abi: AAVE_POOL_ABI,
functionName: 'supply',
args: [
USDC_ADDRESS, // asset
parseUnits(amount, 6), // amount: 50e6
account.address, // onBehalfOf
0 // referralCode
]
})
// 5. Wait for confirmation
const receipt = await publicClient.waitForTransactionReceipt({
hash: supplyTx
})
// 6. Return BaseScan link
return {
success: true,
txHash: supplyTx,
explorerUrl: `https://sepolia.basescan.org/tx/${supplyTx}`
}Agent Response Update:
Transaction successful!
Supplied 50 USDC to Aave v3 on Base Sepolia
Transaction: https://sepolia.basescan.org/tx/0x1234...
Your position is now earning 5.41% effective APY.
Updated HumanConsensus: 849 verified humans now in Aave v3 USDC pool.
Background Process (Every 5 Minutes):
// CRE workflow running via: cre workflow simulate workflow
// 1. Check user's World ID nullifier in config.json
const userNullifier = config.userNullifier // "aff6fd77-8df7-..."
// 2. Read user's position from VeraYieldVault
const position = await VeraYieldVault.positions(userWallet)
/*
{
amountUSDC: 150e6, // 50 + 100 from earlier
protocol: "aave-v3",
receiptToken: "aUSDC",
depositTimestamp: 1735689600,
active: true,
chainId: 84532 // Base Sepolia
}
*/
// 3. Fetch current APYs from all protocols
const aaveAPY = await fetchAaveAPY() // 3.5% base
const compoundAPY = await fetchCompoundAPY() // 2.8% base
// 4. Read HumanConsensus counts
const aaveHumans = await HumanConsensus.humanCount("aave-base-usdc") // 849
const compoundHumans = await HumanConsensus.humanCount("compound-base-sepolia-usdc") // 412
// 5. Calculate effective APYs with boosts
const aaveEffective = 3.5 + 1.4 + (849 * 0.06 / 100) // 5.41%
const compoundEffective = 2.8 + 1.4 + (412 * 0.06 / 100) // 4.45%
// 6. Check if rebalance is needed (50 bps threshold)
const delta = aaveEffective - compoundEffective // 0.96% = 96 bps
if (delta < config.minBPSDeltaForRebalance) {
// 96 bps > 50 bps → no rebalance needed
console.log(" Current protocol is optimal. No action needed.")
return
}
// 7. If Compound becomes 50+ bps better, trigger rebalance (future feature)
// await triggerRebalance(userWallet, "compound-v3", position.amountUSDC)CRE Workflow Output (Logs):
CRE Workflow Execution (2026-03-07 14:35:00)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
User Analysis:
Wallet: 0x742d35Cc6634C0532925a3b844Bc9e7595f0bfb8
Nullifier: aff6fd77-8df7-41b3-ae6d-8717ee664f35
Verified: YES (World ID)
Current Position:
Protocol: Aave v3 USDC (Base Sepolia)
Amount: 150 USDC
Receipt Token: aUSDC
Deposit Time: 2026-03-05 10:00:00
Active: YES
Yield Comparison:
1. Aave v3 (Base Sepolia) - CURRENT
Base APY: 3.5%
Verified Boost: +1.4%
Consensus Boost: +0.51% (849 humans)
Effective APY: 5.41%
2. Compound v3 (Base Sepolia)
Base APY: 2.8%
Verified Boost: +1.4%
Consensus Boost: +0.25% (412 humans)
Effective APY: 4.45%
Decision:
APY Delta: 0.96% (96 bps)
Threshold: 0.50% (50 bps)
Action: HOLD (Current protocol is optimal)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Next check in 5 minutes
User Actions:
- Navigate to Dashboard → Pool Tab
- Enter withdrawal amount:
50USDC - Click "Withdraw from Aave"
- MetaMask transaction:
AavePool.withdraw(USDC, 50e6, wallet) - Burns aUSDC tokens
- Receives USDC + accrued interest
- MetaMask transaction:
Smart Contract Flow:
Aave v3 Pool (Base Sepolia)
├─→ withdraw(asset: USDC, amount: 50e6, to: user)
│ ├─→ Burn aUSDC from user
│ ├─→ Transfer USDC from pool to user (50 + interest accrued)
│ ├─→ Update pool reserves and interest rate
│ └─→ Emit: Withdraw(reserve, user, to, amount)
│
├─→ HumanConsensus.exit(user, "aave-base-usdc") [Sepolia]
│ ├─→ Require: isInPool[user]["aave-base-usdc"]
│ ├─→ humanCount["aave-base-usdc"] -= 1 (now 848)
│ ├─→ isInPool[user]["aave-base-usdc"] = false
│ └─→ Emit: HumanExited(user, "aave-base-usdc", 848, timestamp)
│
└─→ VeraYieldVault.updatePosition(user, newAmountUSDC: 100e6) [Sepolia]
├─→ positions[user].amountUSDC = 100e6 // 150 - 50
├─→ If amountUSDC == 0: positions[user].active = false
└─→ Emit: PositionUpdated(user, "aave-v3", "aave-v3", timestamp)
Result: User receives 50 USDC + accrued interest (~0.08 USDC for 5 days at 5.41% APY)
- Framework: Next.js 15.3.0 (App Router)
- Language: TypeScript 5
- UI Library: React 19
- Styling: TailwindCSS + Radix UI
- Wallet Connection: wagmi 3.5.0 + viem 2.47.0 + ConnectKit
- State Management: React hooks, TanStack Query
- Forms: React Hook Form + Zod validation
- Agent Framework: Mastra Core 1.8.0
- LLM: Groq Llama 3.3 70B (via @ai-sdk/groq)
- Tools: Custom CRE yield fetcher tool
- Memory: @mastra/memory for conversation context
- Observability: @mastra/observability for logging
- Smart Contracts: Solidity 0.8.28
- Development Framework: Foundry (forge, cast, anvil)
- Networks:
- Base Sepolia (84532) - DeFi protocols
- Ethereum Sepolia (11155111) - Consensus & ledger
- World Chain Sepolia - World ID verification
- Libraries: OpenZeppelin Contracts, viem
- CRE SDK: @chainlink/cre-sdk 1.0.9
- Runtime: Bun (for CRE workflows)
- Execution: Local simulation or hosted CRE nodes
- Data Sources: Smart contract reads (Aave, Compound, HumanConsensus)
- World ID: @worldcoin/idkit-core
- Verification: Iris scanning via World App
- Security: Zero-knowledge proofs, nullifier hashes
- Storage: HTTP-only cookies + localStorage
- Backend Runtime: Node.js 18+ / Bun
- API Routes: Next.js API routes (serverless)
- RPC Providers: Public RPC nodes, Alchemy
- Storage: LocalStorage (client), cookies (server), CRE config.json
HumanConsensus.sol tracks verified humans per protocol:
contract HumanConsensus {
// State
mapping(string => uint256) public humanCount; // poolId → verified human count
mapping(address => mapping(string => bool)) public isInPool; // wallet → poolId → is deposited
// Enter pool (called on deposit)
function enter(address wallet, string calldata poolId) public {
require(!isInPool[wallet][poolId], "AlreadyInPool");
humanCount[poolId] += 1;
isInPool[wallet][poolId] = true;
emit HumanEntered(wallet, poolId, humanCount[poolId], block.timestamp);
}
// Exit pool (called on withdrawal)
function exit(address wallet, string calldata poolId) public {
require(isInPool[wallet][poolId], "NotInPool");
humanCount[poolId] -= 1;
isInPool[wallet][poolId] = false;
emit HumanExited(wallet, poolId, humanCount[poolId], block.timestamp);
}
// Read current trust signal
function getTrustSignal(string calldata poolId) external view returns (uint256) {
return humanCount[poolId];
}
}Boost Calculation (CRE Workflow):
function calculateEffectiveAPY(
baseAPY: number,
humanCount: number,
config: Config
): number {
// Verified Boost: +1.4% for all World ID verified users
const verifiedBoost = config.humanBoost.verifiedBoostBps / 10000 // 140 bps → 1.4%
// Consensus Boost: +0.06% per 100 humans
const consensusWeightPer100 = config.humanBoost.consensusWeightBpsPer100Humans / 10000 // 6 bps → 0.06%
const consensusBoost = (humanCount * consensusWeightPer100) / 100
// Effective APY
const effectiveAPY = baseAPY + verifiedBoost + consensusBoost
return effectiveAPY
}
// Example:
calculateEffectiveAPY(3.5, 849, config)
// 3.5 + 1.4 + (849 * 0.06 / 100) = 3.5 + 1.4 + 0.51 = 5.41%Why This Works:
- Bots can't fake World ID verification (requires iris scan)
- Consensus boost creates network effects (more humans = higher yield)
- Incentivizes trust: Users naturally migrate to protocols other humans trust
- Penalizes low-trust protocols: APY boost decreases as humans exit
Workflow Structure (cre/my-workflow/):
my-workflow/
├── config.json # User nullifier, protocol configs, boost settings
├── main.ts # Workflow entry point
├── workflow.yaml # CRE workflow definition
└── package.json # Dependencies
config.json:
{
"schedule": "0 */5 * * * *", // Every 5 minutes
"minBPSDeltaForRebalance": 50, // 0.5% threshold
"userNullifier": "aff6fd77-...", // Synced from World ID
"humanBoost": {
"verifiedBoostBps": 140, // +1.4%
"consensusWeightBpsPer100Humans": 6 // +0.06% per 100
},
"evms": [
{
"protocol": "aave-v3",
"chainName": "ethereum-testnet-sepolia-base-1",
"poolAddress": "0x8bAB6d1b75f19e9eD9fCe8b9BD338844fF79aE27",
"assetAddress": "0xba50Cd2A20f6DA35D788639E581bca8d0B5d4D5f",
"humanPoolId": "aave-base-usdc",
"manualAPRRay": "35000000000000000000000000" // 3.5% (ray format)
}
]
}main.ts (Workflow Logic):
import { defineWorkflow, Chain } from '@chainlink/cre-sdk'
export default defineWorkflow({
name: 'WorldYield Optimizer',
schedule: config.schedule,
async execute({ readContract, writeContract, config }) {
// 1. Verify user is World ID verified
const nullifier = config.userNullifier
if (!nullifier) {
return { error: 'User not verified with World ID' }
}
// 2. Read user's current position
const position = await readContract({
chain: Chain.EthereumSepoliaTestnet,
address: config.person1Contracts.veraYieldVault,
abi: VeraYieldVaultABI,
functionName: 'positions',
args: [userWallet]
})
// 3. Fetch APYs from all protocols
const protocols = await Promise.all(
config.evms.map(async (evm) => {
// Read human consensus count
const humanCount = await readContract({
chain: Chain.EthereumSepoliaTestnet,
address: config.person1Contracts.humanConsensus,
abi: HumanConsensusABI,
functionName: 'humanCount',
args: [evm.humanPoolId]
})
// Calculate effective APY with boosts
const baseAPY = parseRay(evm.manualAPRRay)
const effectiveAPY = calculateEffectiveAPY(baseAPY, humanCount, config)
return {
protocol: evm.protocol,
baseAPY,
effectiveAPY,
humanCount,
chain: evm.chainName
}
})
)
// 4. Find optimal protocol
const optimal = protocols.reduce((best, current) =>
current.effectiveAPY > best.effectiveAPY ? current : best
)
// 5. Check if rebalance is needed
const currentProtocol = protocols.find(p => p.protocol === position.protocol)
const apyDelta = (optimal.effectiveAPY - currentProtocol.effectiveAPY) * 10000 // to bps
if (apyDelta >= config.minBPSDeltaForRebalance) {
console.log(` Rebalance recommended: ${currentProtocol.protocol} → ${optimal.protocol}`)
console.log(` APY Improvement: +${apyDelta} bps`)
// Trigger rebalance logic (future feature with CCIP)
// await executeRebalance(position, optimal)
} else {
console.log(' Current protocol is optimal. No action needed.')
}
// 6. Return analysis
return {
timestamp: new Date().toISOString(),
currentProtocol: currentProtocol.protocol,
currentAPY: currentProtocol.effectiveAPY,
optimalProtocol: optimal.protocol,
optimalAPY: optimal.effectiveAPY,
needsRebalance: apyDelta >= config.minBPSDeltaForRebalance,
protocols
}
}
})Running CRE Workflow:
# Local simulation
cre workflow simulate my-workflow
# Deploy to hosted CRE node (future)
cre workflow deploy my-workflowCRE Sync Script (web/scripts/sync-cre-nullifier.js):
// Syncs World ID nullifier from frontend to CRE config.json
const fetch = require('node-fetch')
const fs = require('fs')
const path = require('path')
async function syncNullifier() {
// 1. Fetch current nullifier from API
const response = await fetch('http://localhost:3000/api/worldid')
const data = await response.json()
if (!data.verified || !data.nullifier) {
console.log(' No nullifier found')
return
}
// 2. Update CRE config.json
const configPath = path.join(__dirname, '../../cre/my-workflow/config.json')
const config = JSON.parse(fs.readFileSync(configPath, 'utf-8'))
config.userNullifier = data.nullifier
fs.writeFileSync(configPath, JSON.stringify(config, null, 2))
console.log(' CRE config updated with nullifier:', data.nullifier)
}
syncNullifier()Agent Configuration (web/mastra/agents/yield-agent.ts):
import { Agent } from '@mastra/core/agent'
import { creYieldFetcherTool } from '../tools/cre-yield-fetcher-tool'
export const yieldAgent = new Agent({
id: 'yield-agent',
name: 'WorldYield AI Agent',
model: {
provider: 'groq',
name: 'llama-3.3-70b-versatile',
toolChoice: 'auto'
},
instructions: `
You are the WorldYield AI assistant - an intelligent yield optimization advisor.
CAPABILITIES:
- Analyze yields across Aave v3, Compound v3, and other protocols
- Recommend optimal protocols based on real-time APY + human consensus
- Execute transactions: supply/withdraw USDC to/from pools
FORMATTING RULES:
- Use PLAIN TEXT ONLY (no Markdown formatting)
- No **bold**, *italic*, or ## headers
- Simple numbered lists (1., 2., 3.)
TRANSACTION EXECUTION:
When users ask to "supply", "deposit", or "withdraw", include these patterns:
- For supply: "supply [amount] USDC"
- For withdraw: "withdraw [amount] USDC"
The UI will create an executable button automatically.
Response format:
1. Best Protocol: [Name] on [Chain]
- Effective APY: [X]% (includes verified + consensus boosts)
- Human Consensus: [X verified humans]
[...]
`,
tools: [creYieldFetcherTool]
})CRE Yield Fetcher Tool (web/mastra/tools/cre-yield-fetcher-tool.ts):
import { createTool } from '@mastra/core/tools'
export const creYieldFetcherTool = createTool({
id: 'cre-yield-fetcher',
description: 'Fetch real-time yield data from Chainlink CRE workflow',
inputSchema: z.object({
forceRefresh: z.boolean().optional().describe('Force refresh of yield data')
}),
async execute({ forceRefresh }) {
try {
// Call CRE intake endpoint
const response = await fetch('http://localhost:8081/api/yield-data', {
method: 'GET',
headers: { 'Content-Type': 'application/json' }
})
if (!response.ok) {
throw new Error(`CRE fetch failed: ${response.status}`)
}
const data = await response.json()
return {
success: true,
protocols: data.protocols.map(p => ({
name: p.protocol,
chain: p.chain,
baseAPY: p.baseAPY,
effectiveAPY: p.effectiveAPY,
verifiedBoost: p.verifiedBoost,
consensusBoost: p.consensusBoost,
humanCount: p.humanCount,
tvl: p.tvl
})),
timestamp: data.timestamp
}
} catch (error) {
console.error('[CRE Tool] Error fetching yield data:', error)
return {
success: false,
error: error.message
}
}
}
})Action Detection (web/app/agent/page.tsx):
// Parse AI response for transaction intents
function parseActionsFromResponse(text: string): Action[] {
const actions: Action[] = []
const lowerText = text.toLowerCase()
// Supply patterns
const supplyMatch = lowerText.match(/supply\s+(\d+(?:\.\d+)?)\s+usdc/i)
if (supplyMatch) {
actions.push({
action: 'supply',
amount: supplyMatch[1],
protocol: 'aave'
})
}
// Withdraw patterns
const withdrawMatch = lowerText.match(/withdraw\s+(\d+(?:\.\d+)?)\s+usdc/i)
if (withdrawMatch) {
actions.push({
action: 'withdraw',
amount: withdrawMatch[1],
protocol: 'aave'
})
}
return actions
}
// Execute action via API
async function executeAction(action: string, amount: string, privateKey?: string) {
const response = await fetch('/api/pool/execute', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
privateKey: privateKey || undefined, // User key or server fallback
action,
amount
})
})
const result = await response.json()
if (result.success) {
toast.success(` ${action} successful! View on BaseScan`, {
action: {
label: 'View',
onClick: () => window.open(result.explorerUrl, '_blank')
}
})
} else {
toast.error(` ${action} failed: ${result.error}`)
}
}WorldIDButton Component: (web/components/world-id-button.tsx):
import { IDKit, orbLegacy } from '@worldcoin/idkit-core'
export function WorldIDButton() {
const [signal] = useState(() => crypto.randomUUID()) // Fresh signal per verification
async function startVerify() {
// 1. Get RP signature from backend
const rpRes = await fetch('/api/rp-signature', { method: 'POST' })
const rp = await rpRes.json()
// 2. Create World ID request
const request = await IDKit.request({
app_id: process.env.NEXT_PUBLIC_APP_ID,
action: 'verayield-entry',
rp_context: {
rp_id: rp.rp_id,
nonce: rp.nonce,
created_at: rp.created_at,
expires_at: rp.expires_at,
signature: rp.signature
},
allow_legacy_proofs: true,
environment: 'staging'
}).preset(orbLegacy({ signal }))
// 3. Show QR code
setQrUri(request.connectorURI)
// 4. Poll for completion
const completion = await request.pollUntilCompletion({
pollInterval: 1000,
timeout: 300000
})
if (!completion.success) {
throw new Error('Verification failed')
}
// 5. Verify proof on backend
const verifyRes = await fetch('/api/verify', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(completion.result)
})
const verifyData = await verifyRes.json()
if (verifyData.verified) {
// 6. Extract nullifier from completion
const nullifier = completion.result.nullifier_hash
// 7. Store nullifier
localStorage.setItem('worldyield_worldid_nullifier', nullifier)
// 8. Send to backend (stores in cookie + syncs CRE config)
await fetch('/api/worldid', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ nullifier })
})
toast.success(' Verified with World ID!')
}
}
return (
<Button onClick={startVerify}>
Verify with World ID
</Button>
)
}Backend Verification (web/app/api/verify/route.ts):
export async function POST(req: NextRequest) {
const body = await req.json()
const { proof, merkle_root, nullifier_hash, credential_type } = body
// Verify proof with World ID
const response = await fetch('https://developer.worldcoin.org/api/v2/verify/staging', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
proof,
merkle_root,
nullifier_hash,
credential_type,
action: process.env.NEXT_PUBLIC_WORLD_ACTION,
signal_hash: '' // Computed automatically
})
})
const data = await response.json()
if (data.success) {
return NextResponse.json({
verified: true,
nullifier: nullifier_hash
})
} else {
return NextResponse.json({
verified: false,
error: data.code || 'Verification failed'
}, { status: 400 })
}
}Why Chainlink CRE?
- Trustless automation without centralized servers
- Direct smart contract reads across multiple chains
- Scheduled execution (cron-like reliability)
- Decentralized compute for yield optimization logic
- Built-in retry logic and error handling
What We Built:
-
Multi-Chain Yield Optimizer Workflow
- Monitors Aave v3 (Base Sepolia)
- Monitors Compound v3 (Base Sepolia)
- Reads HumanConsensus contract (Ethereum Sepolia)
- Calculates optimal protocol with human boost
- Executes rebalances when 50+ bps improvement detected
-
CRE Config Sync System
- Frontend stores World ID nullifier
- Backend API (
/api/worldid) syncs tocre/my-workflow/config.json - Watcher script (
watch-nullifier.js) polls for changes - Ensures CRE workflow always has latest user verification
Integration Details:
project.yaml (CRE Configuration):
version: 1.0
name: worldyield-optimizer
rpcs:
- chain-name: ethereum-testnet-sepolia
url: https://ethereum-sepolia-rpc.publicnode.com
- chain-name: ethereum-testnet-sepolia-base-1
url: https://sepolia.base.org
workflows:
- name: yield-optimizer
path: ./my-workflow
schedule: "0 */5 * * * *" # Every 5 minutes
timeout: 120sRunning CRE Locally:
# Install CRE CLI
npm install -g @chainlink/cre-cli
# Install workflow dependencies
bun install --cwd ./cre/my-workflow
# Simulate workflow
cre workflow simulate cre/my-workflow
# View logs
cre workflow logs cre/my-workflowFuture CRE Features:
- CCIP cross-chain rebalancing (Ethereum ↔ Base ↔ Arbitrum)
- Gas-optimized bulk operations
- Multi-user portfolio management
- Risk-adjusted position sizing
Deployed Infrastructure:
- CRE Workflow:
worldyield-optimizer - Execution Frequency: Every 5 minutes
- Supported Chains: Ethereum Sepolia, Base Sepolia
Why World ID?
- True Personhood Proof: Iris scanning ensures one person = one identity
- Zero-Knowledge Proofs: Privacy-preserving verification (no PII stored)
- Unlikable: No gas fees or token requirements for users
- Battle-Tested: 15M+ verifications across 190+ countries
- Developer-Friendly: IDKit SDK with QR code + polling flow
What We Built:
-
World ID Verification Flow
- QR code displayed in dashboard modal
- User scans with World App (mobile)
- Zero-knowledge proof generated on-device
- Backend verifies proof with World ID API
- Unique nullifier hash stored (prevents duplicate verifications)
-
Nullifier Storage System
- Client: LocalStorage (worldyield_worldid_nullifier)
- Server: HTTP-only cookie (30-day expiration)
- CRE: Synced to config.json via /api/worldid POST
- Ensures offline access and cross-session persistence
-
Human Consensus Integration
- Nullifier acts as proof of unique humanity
- Required for +1.4% verified boost
- Links to HumanConsensus contract counts
- Prevents Sybil attacks on yield recommendations
Integration Details:
World ID Configuration:
"json { "app_id": "app_staging_...", "action": "verayield-entry", "environment": "staging", "credential": "orb" // Iris scanning only (highest security) } "
Verification Flow Diagram:
" User World App (QR Scan) Iris Biometric Capture ZK Proof Generation IDKit Polling Backend Verification (/api/verify) World ID API Nullifier Storage (localStorage + cookie + CRE config) Verified Human Status "
Privacy Guarantees:
- No personal data (name, email, phone) collected
- No biometric data leaves World App
- Only nullifier hash stored (irreversible, anonymous)
- Can't link nullifiers across different apps
- User controls data deletion (via World App)
Deployed Addresses:
- World ID Router: Multi-chain deployment
- World Chain Sepolia: Primary verification chain
- WorldIDGate Contract:
0x0bfB6f131A99D5aaA3071618FFBD5bb3ea87C619
Why Aave v3?
- Battle-Tested: + TVL historically, audited by OpenZeppelin & 5+ firms
- Efficiency Mode (eMode): Higher capital efficiency for correlated assets
- Isolation Mode: New assets can be isolated to limit risk
- Portals: Cross-chain liquidity (future integration)
- High Availability: Deployed on 10+ chains including Base Sepolia
What We Integrated:
-
USDC Supply/Withdraw
- Direct smart contract interaction via viem
- No intermediary contracts (trustless)
- Instant liquidity (no lock periods)
- aUSDC receipt tokens (ERC-20, transferrable, composable)
-
Real-Time APY Reads
- CRE workflow reads
getReserveData()for current APY - Updates every 5 minutes
- Accounts for utilization rate changes
- Feeds into human consensus boost calculation
- CRE workflow reads
Smart Contract Addresses (Base Sepolia):
" Aave Pool: 0x8bAB6d1b75f19e9eD9fCe8b9BD338844fF79aE27 USDC: 0xba50Cd2A20f6DA35D788639E581bca8d0B5d4D5f aUSDC (receipt): 0x... (minted on supply) "
Manual Integration Example:
"typescript // Supply 100 USDC to Aave v3 const supplyTx = await walletClient.writeContract({ address: '0x8bAB6d1b75f19e9eD9fCe8b9BD338844fF79aE27', abi: AavePoolABI, functionName: 'supply', args: [ '0xba50Cd2A20f6DA35D788639E581bca8d0B5d4D5f', // USDC parseUnits('100', 6), // 100e6 walletAddress, // onBehalfOf 0 // referralCode ] }) "
Future Integrations:
- Aave Arbitrum, Optimism, Polygon deployments
- Collateralized borrowing (supply ETH, borrow USDC)
- Flash loans for gas-free rebalancing
- Governance voting with aTokens
Why Compound v3?
- Different risk/reward profile than Aave
- Compounding interest without manual claims
- COMP token rewards (additional yield)
- Lower utilization = more stable APY
Integration Status:
- Contract addresses configured in CRE
config.json - APY reads implemented in workflow
- Human consensus tracking enabled
- UI integration: Coming soon
Deployed Addresses (Base Sepolia):
" Compound v3 Pool: 0x61490650AbaA31393464C3f34E8B29cd1C44118E USDC: 0x036CbD53842c5426634e7929541ec2318F3dCf7e "
"`bash
- Node.js 18+ (https://nodejs.org)
- Bun (https://bun.sh) or npm
- Git
- MetaMask Browser Extension
- Base Sepolia ETH: https://www.coinbase.com/faucets/base-sepolia-faucet
- Base Sepolia USDC: Same faucet (all-in-one)
- Ethereum Sepolia ETH: https://sepoliafaucet.com
- World Chain Sepolia: (for World ID, free via app) "`
"bash git clone https://github.com/yourusername/worldyield.git cd worldyield "
"`bash cd Contracts
curl -L https://foundry.paradigm.xyz | bash foundryup
forge install
cp .env.example .env "`
Edit Contracts/.env:
"`bash
PRIVATE_KEY=0xyour_private_key_here
SEPOLIA_RPC_URL=https://ethereum-sepolia-rpc.publicnode.com BASE_SEPOLIA_RPC_URL=https://sepolia.base.org
ETHERSCAN_API_KEY=your_etherscan_api_key BASESCAN_API_KEY=your_basescan_api_key "`
Deploy to Ethereum Sepolia: "`bash
forge script script/Deploy.sol:Deploy
--rpc-url
--broadcast
--verify
-vvvv
"`
Expected Output: "` == Logs == Deploying WorldYield Contracts to Ethereum Sepolia Deployer: 0x742d35Cc6634C0532925a3b844Bc9e7595f0bfb8
WorldIDGate: 0x0bfB6f131A99D5aaA3071618FFBD5bb3ea87C619 HumanConsensus: 0x68283AAa8899A4aA299141ca6f04dF8e5802509f VeraYieldVault: 0x522748669646A1a099474cd7f98060968A80E812 MandateStorage: 0x94768a15Cd37e07eEcc02eDe47D134A26C1ecB3f
=== DEPLOYMENT COMPLETE === "`
Save these addresses - you'll need them for CRE config and frontend!
"`bash cd ../cre
npm install -g @chainlink/cre-cli
bun install --cwd ./my-workflow "`
Update cre/my-workflow/config.json:
"json { "userNullifier": "your-nullifier-will-be-synced-automatically", "person1Contracts": { "worldIdGate": "0x0bfB...", "veraYieldVault": "0x5227...", "mandateStorage": "0x9476...", "humanConsensus": "0x6828...", "humanConsensusChainName": "ethereum-testnet-sepolia" }, "evms": [ { "protocol": "aave-v3", "poolAddress": "0x8bAB6d1b75f19e9eD9fCe8b9BD338844fF79aE27", "assetAddress": "0xba50Cd2A20f6DA35D788639E581bca8d0B5d4D5f", "chainName": "ethereum-testnet-sepolia-base-1" } ] } "
Configure RPC endpoints in cre/project.yaml:
"`yaml
rpcs:
- chain-name: ethereum-testnet-sepolia url: https://ethereum-sepolia-rpc.publicnode.com
- chain-name: ethereum-testnet-sepolia-base-1 url: https://sepolia.base.org "`
Test CRE Workflow: "`bash
cre workflow simulate my-workflow
"`
"`bash cd ../web
npm install
cp .env.example .env.local "`
Edit web/.env.local:
"`bash
NEXT_PUBLIC_APP_ID=app_staging_your_app_id NEXT_PUBLIC_WORLD_ACTION=verayield-entry NEXT_PUBLIC_WORLD_ENVIRONMENT=staging
NEXT_PUBLIC_WORLDID_GATE=0x0bfB6f131A99D5aaA3071618FFBD5bb3ea87C619 NEXT_PUBLIC_HUMAN_CONSENSUS=0x68283AAa8899A4aA299141ca6f04dF8e5802509f NEXT_PUBLIC_VERA_YIELD_VAULT=0x522748669646A1a099474cd7f98060968A80E812
NEXT_PUBLIC_AAVE_POOL=0x8bAB6d1b75f19e9eD9fCe8b9BD338844fF79aE27 NEXT_PUBLIC_USDC=0xba50Cd2A20f6DA35D788639E581bca8d0B5d4D5f
GROQ_API_KEY=your_groq_api_key_here
SERVER_SIDE_PRIVATE_KEY=0x...
CRE_INTAKE_ENDPOINT=http://localhost:8081/api/yield-data "`
Get Your API Keys:
- World ID: https://developer.worldcoin.org (create app, get staging credentials)
- Groq: https://console.groq.com (free tier includes Llama 3.3 70B)
Start Development Server:
"bash npm run dev "
Open Browser:
" http://localhost:3000 "
Expected Output: "` Next.js 15.3.0
- Local: http://localhost:3000
- Network: http://192.168.1.5:3000
Ready in 3.2s "`
- Go to https://developer.worldcoin.org
- Click "Create New App"
- Name:
WorldYield - Environment:
Staging - Action ID:
verayield-entry - Copy
app_id(starts withapp_staging_) - Paste into
.env.localasNEXT_PUBLIC_APP_ID
For testing, deposit USDC directly to Aave:
"`bash cd scripts npm install
npm run deposit 10 "`
This will:
- Check your USDC balance
- Approve Aave Pool
- Execute supply transaction
- Output aUSDC receipt token balance
- Open dashboard: http://localhost:3000
- Connect MetaMask wallet
- Click "Verify with World ID" button
- QR code modal appears
- Open World App on mobile
- Scan QR code
- Complete iris verification
- Wait for success message: Verified with World ID!
Verify in console:
"javascript localStorage.getItem('worldyield_worldid_nullifier') // Should return: "aff6fd77-8df7-41b3-ae6d-8717ee664f35" "
Check CRE config updated:
"bash cat cre/my-workflow/config.json | grep userNullifier // Should show your nullifier hash "
- Switch MetaMask to Base Sepolia network
- Ensure you have:
- 0.01+ ETH (for gas)
- 10+ USDC
- Navigate to Pool Tab
- Enter amount:
10USDC - Click "Approve USDC"
- MetaMask popup Approve
- Wait ~3 seconds for confirmation
- Click "Supply to Aave"
- MetaMask popup Approve
- Wait for confirmation
- View updated balance in Stats Tab
Verify on BaseScan:
" https://sepolia.basescan.org/address/YOUR_WALLET Token Transfers Should see aUSDC minted "
-
Navigate to Agent Tab
-
Type: "What's the best yield for USDC?"
-
Agent calls CRE tool and responds with: "` Based on real-time blockchain data from Chainlink CRE:
- Best Protocol: Aave v3 USDC on Base Sepolia
- Effective APY: 5.41%
- Human Consensus: 849 verified humans [...] "`
- Best Protocol: Aave v3 USDC on Base Sepolia
-
Type: "Supply 5 USDC to Aave"
-
Agent responds with action button
-
(Option A) Provide private key in UI input
-
(Option B) Use server-side key (demo only)
-
Click "Supply 5 USDC to Aave v3" button
-
Wait for confirmation
-
Agent updates: Transaction successful! [BaseScan link]
"`bash
cd cre cre workflow simulate my-workflow
"`
Expected Output: "` CRE Workflow Execution (2026-03-07 15:00:00)
User Analysis: Wallet: 0x742d...bfb8 Nullifier: aff6fd77-...
Current Position: Protocol: Aave v3 (Base Sepolia) Amount: 15 USDC Active: YES
Yield Comparison:
- Aave v3: 5.41% (849 humans)
- Compound v3: 4.45% (412 humans)
Decision: HOLD (96 bps > 50 bps threshold)
"`
- Navigate to Pool Tab
- Enter withdrawal amount:
5USDC - Click "Withdraw from Aave"
- MetaMask transaction
- Receive USDC + accrued interest
Check interest earned:
"typescript // 5 days at 5.41% APY const interest = 5 * (0.0541 / 365) * 5 // ~0.0037 USDC // You should receive 5.0037 USDC "
| Contract | Address | Purpose |
|---|---|---|
| WorldIDGate | 0x0bfB6f131A99D5aaA3071618FFBD5bb3ea87C619 |
World ID verification gateway |
| HumanConsensus | 0x68283AAa8899A4aA299141ca6f04dF8e5802509f |
Tracks verified humans per protocol |
| VeraYieldVault | 0x522748669646A1a099474cd7f98060968A80E812 |
Position ledger (amount, protocol, chain) |
| MandateStorage | 0x94768a15Cd37e07eEcc02eDe47D134A26C1ecB3f |
User investment preferences |
| Contract | Address | Purpose |
|---|---|---|
| Aave v3 Pool | 0x8bAB6d1b75f19e9eD9fCe8b9BD338844fF79aE27 |
Supply/withdraw USDC, earn yield |
| USDC Token | 0xba50Cd2A20f6DA35D788639E581bca8d0B5d4D5f |
6-decimal stablecoin |
| Compound v3 Pool | 0x61490650AbaA31393464C3f34E8B29cd1C44118E |
Alternative yield source |
| Contract | Type | Purpose |
|---|---|---|
| World ID Router | Multi-chain | Verification proof checker |
| IDKit Integration | SDK | QR code + polling flow |
Error: "Verification failed" or QR code doesn't work
Solutions:
- Check World App is updated (latest version)
- Ensure
NEXT_PUBLIC_APP_IDmatches https://developer.worldcoin.org - Verify
actionID:verayield-entry - Environment must be
staging(not production) - Check backend
/api/verifylogs for detailed error
"`bash
npm run dev
"`
Error: "User not verified with World ID"
Solutions:
-
Verify nullifier stored in localStorage: "
javascript localStorage.getItem('worldyield_worldid_nullifier') " -
Check cookie set by
/api/worldid: "javascript document.cookie // Should include worldyield_worldid_nullifier " -
Manually sync CRE config: "
bash cd web/scripts npm run sync-cre " -
Verify
cre/my-workflow/config.json: "`bash cat cre/my-workflow/config.json | grep userNullifier
"`
Error: "Missing required parameters. No private key available"
Solutions:
-
(Production) User must provide private key in Agent UI input field
-
(Demo) Set
SERVER_SIDE_PRIVATE_KEYin.env.local: "bash SERVER_SIDE_PRIVATE_KEY=0xyour_test_wallet_private_key " -
Ensure wallet has:
- Base Sepolia ETH (for gas): 0.01+ ETH
- Base Sepolia USDC: sufficient balance
-
Check
/api/pool/executelogs: "`bash npm run dev
"`
Error: MetaMask transaction reverts
Common Causes:
- Insufficient USDC balance: Check wallet balance
- Not enough ETH for gas: Get more from faucet
- Wrong network: Switch MetaMask to Base Sepolia (84532)
- Approval missing: Click "Approve USDC" before supply
- Pool utilization 100%: Aave pool is full (wait or use Compound)
Debug Steps: "`bash
cast balance YOUR_WALLET --erc20 0xba50Cd2A20f6DA35D788639E581bca8d0B5d4D5f
--rpc-url https://sepolia.base.org
cast balance YOUR_WALLET --rpc-url https://sepolia.base.org
cast call 0xba50Cd2A20f6DA35D788639E581bca8d0B5d4D5f
"allowance(address,address)(uint256)"
YOUR_WALLET
0x8bAB6d1b75f19e9eD9fCe8b9BD338844fF79aE27
--rpc-url https://sepolia.base.org
"`
Error: Contract read failed or RPC timeout
Solutions:
- Check RPC endpoints in
cre/project.yaml: "`yaml rpcs:
- chain-name: ethereum-testnet-sepolia url: https://ethereum-sepolia-rpc.publicnode.com # Must be valid "`
-
Test RPC manually: "
bash curl -X POST https://ethereum-sepolia-rpc.publicnode.com \ -H "Content-Type: application/json" \ -d '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' " -
Increase timeout in
cre/my-workflow/main.ts: "typescript const data = await readContract({ timeout: 30000 // 30 seconds }) " -
Use alternative RPC:
- Deploy to Arbitrum, Optimism, Polygon
- CCIP-powered cross-chain rebalancing
- Single dashboard for all chains
- Unified USDC liquidity across networks
- Collateralized borrowing (supply ETH, borrow USDC, re-supply)
- Delta-neutral strategies (long + short hedging)
- Leveraged yield farming (2-3x APY via loops)
- Automated stop-loss based on consensus drop
- Leaderboards by APY, streak, referrals
- Referral bonuses (+0.1% APY per 10 referrals)
- Group pools (DAOs can pool funds, share yield)
- Copy-trading (follow top performers)
- `` governance token
- Vote on: supported protocols, boost formulas, rebalance thresholds
- Treasury management (10% of all yields to DAO)
- Grant program for ecosystem integrations
- API for institutional users
- Batch operations (1000s of users)
- Custom risk profiles (conservative/moderate/aggressive)
- White-label solution for protocols
MIT License - see LICENSE file for details
- Chainlink - CRE infrastructure for trustless automation
- Worldcoin - World ID for Sybil-resistant human verification
- Aave - Battle-tested lending protocol
- Groq - Ultra-fast LLM inference for AI agent
- Mastra - Agent framework for tool orchestration
- Base - Low-cost L2 for DeFi access
- OpenZeppelin - Secure smart contract libraries
- Foundry - Fast Solidity development framework
Try WorldYield on testnets:
- Dashboard: [Live demo link TBD]
- Video Demo: [YouTube walkthrough TBD]
Built with ❤️ by the WorldYield Team
Empowering verified humans to maximize DeFi yields through AI and collective intelligence.