Backend: https://senate-qiog.onrender.com ✅ (running)
Frontend: http://localhost:5174 ✅ (running)
Oracle Address: 0x4C3F5a84041E562928394d63b3E339bE70DBcC17 ✅ (whitelisted)
- Open the app: http://localhost:5174
- Login/Register with your account
- Connect MetaMask:
- Click wallet connect button (if in navbar) or go to Register page
- Make sure you're on Sepolia testnet
- Need test ETH? Get it from Sepolia Faucet
- Need test USDC? Get it from Circle Faucet (select Sepolia + USDC)
Option A: Create New Project
- Go to Dashboard
- Create a new project
- Add team members (their wallet addresses must be filled in their profiles)
Option B: Use Existing Project
- Go to any project you own
- Make sure team members have wallet addresses in their profiles
- Open Project Details page
- Click "Deploy Escrow" button (top right, only visible to project creator)
- Fill in the form:
- Oracle: Auto-filled with
0x4C3F...cC17(✅ our whitelisted oracle) - Arbitrator: Use the same
0x4C3F5a84041E562928394d63b3E339bE70DBcC17or another address - Total Budget: e.g.,
1000USDC - Dispute Window: e.g.,
86400(1 day in seconds) or3600(1 hour for quick testing) - Milestones: Click "Add Milestone" to create 2-3 milestones
- Milestone 1: Budget
300, Deadline unix timestamp (use https://www.unixtimestamp.com/) - Milestone 2: Budget
400, Deadline timestamp - Milestone 3: Budget
300, Deadline timestamp
- Milestone 1: Budget
- Contributors: Auto-filled from team wallets — verify all addresses are valid
- Oracle: Auto-filled with
- Approve USDC:
- Modal will show your USDC balance
- Click "Approve USDC" → MetaMask pops up → Confirm
- Wait for confirmation (~ 10-20 sec)
- Deploy Escrow:
- Click "Deploy Escrow" → MetaMask pops up → Confirm
- Wait for deployment (~ 20-30 sec)
- Transaction hash and escrow address will appear
- Link to Backend:
- Automatically calls backend to save escrow data
- Project page will refresh and show escrow info
✅ Success: You should see:
- "Escrow Active" badge in project header
- "Escrow" card in right column with budget, milestones, contributors
- Milestone timeline with status badges
Backend Route: POST /api/oracle/submit-scores
Option A: Use API directly (recommended for first test)
# Get the escrow address from the project page
export ESCROW_ADDRESS="0x..." # Replace with your deployed escrow
# Submit scores for milestone 0
# Make sure the addresses match your actual contributors
curl -X POST https://senate-qiog.onrender.com/api/oracle/submit-scores \
-H "Content-Type: application/json" \
-d '{
"escrowAddress": "'$ESCROW_ADDRESS'",
"milestoneId": 0,
"members": [
"0xYourContributor1Address",
"0xYourContributor2Address"
],
"scores": [85, 92]
}' | python3 -m json.toolExpected Response:
{
"ok": true,
"txHash": "0x..."
}Option B: Build a UI (if you want)
- Create a button in
ProjectDetail.jsxorDisputePanel.jsx - Call
requestSubmitScores()fromoracleApi.js - Pass escrow address, milestone index, contributor addresses, and scores
✅ Success:
- Transaction confirms on Sepolia
- Milestone status changes from 0 (Pending) → 1 (ScoresSubmitted)
- Contributors can now see their pending withdrawals
- Go to User Dashboard as one of the contributors
- Connect Wallet (same wallet that was in contributors list)
- Check "Payments" card: Should show pending USDC amount
- Scroll to "Pending Payments" section: Should list the project
- Click "Withdraw" → MetaMask pops up → Confirm
- Wait for tx confirmation
- Verify: Amount should appear in your wallet's USDC balance
✅ Success: USDC transferred from escrow to contributor wallet
If you want to test the dispute flow:
- Before dispute window closes, go to ProjectDetail page
- Scroll to DisputePanel (left column, below Tasks)
- Click "Raise Dispute" on a milestone
- Enter reason: e.g., "Scores are incorrect"
- Submit → MetaMask pops up → Confirm
- Wait for confirmation
- Check status: Milestone should now show "In Dispute" (status 2)
To Resolve (as arbitrator):
- Only the arbitrator wallet can call
resolveDispute() - This requires either:
- Frontend button in DisputePanel (not implemented yet)
- Direct contract call via ethers or Etherscan
After dispute window expires (e.g., 1 hour if you set 3600):
- Go to ProjectDetail page
- DisputePanel → Find milestone with status "ScoresSubmitted" and expired dispute window
- Click "Finalize" → MetaMask pops up → Confirm
- Wait for confirmation
- Status changes: Milestone → "Finalized" (status 3)
Or use backend:
curl -X POST https://senate-qiog.onrender.com/api/oracle/finalize \
-H "Content-Type: application/json" \
-d '{
"escrowAddress": "'$ESCROW_ADDRESS'",
"milestoneId": 0
}' | python3 -m json.tool✅ Success: Milestone is now permanently finalized
- Go to Admin Dashboard (if you have admin access)
- Click "Escrows" tab
- Check Oracle Status: Should show configured with address
- Check Escrow List: Should show all deployed escrows with:
- Budget
- Milestone count
- Finalized/disputed counts
- Contributor count
- Etherscan links
- MetaMask connected to Sepolia
- Have test ETH for gas
- Have test USDC (at least 100 for small test)
- Project created with team members
- All team members have wallet addresses in profiles
- Escrow deployed successfully
- Scores submitted for milestone 0
- Contributor can see pending payment
- Contributor can withdraw successfully
- Milestone finalized after dispute window
"Wrong network" error:
- Switch MetaMask to Sepolia testnet (Chain ID: 11155111)
"Insufficient USDC balance":
- Get test USDC from Circle Faucet
- Make sure to select Sepolia + USDC
"Transaction reverted":
- Check browser console for error details
- Common causes:
- Not enough gas (get more ETH)
- Dispute window not expired (can't finalize)
- Milestone already finalized
- Not the oracle/arbitrator/owner
Escrow not showing after deployment:
- Check if
linkEscrowToProjectsucceeded (/api/projects/:id/escrow) - Refresh the page
- Check MongoDB to see if
escrowAddressfield was saved
Oracle endpoints failing:
- Check server logs:
lsof -ti:3000 | xargs kill -9 && cd server && node app.js - Verify
.envhasORACLE_PRIVATE_KEYandSEPOLIA_RPC_URL - Test:
curl https://senate-qiog.onrender.com/api/oracle/status
GET /api/oracle/status
{ "ok": true, "oracle": "0x...", "configured": true }POST /api/oracle/sign
{
"escrowAddress": "0x...",
"milestoneId": 0,
"members": ["0x...", "0x..."],
"scores": [85, 92]
}POST /api/oracle/submit-scores
Same body as /sign, directly submits on-chain
POST /api/oracle/finalize
{
"escrowAddress": "0x...",
"milestoneId": 0
}GET /api/oracle/escrow/:address Returns full escrow data (milestones, contributors, budgets)
GET /api/oracle/escrows Returns list of all escrow addresses from factory
- Sepolia Etherscan: https://sepolia.etherscan.io/
- Factory Contract: https://sepolia.etherscan.io/address/0x7fC3446ae26286EF5668Df02f7C1c96a6a1c458B
- RewardToken: https://sepolia.etherscan.io/address/0x27a90bE82CF59d286634a5A49F384d4B369A1E84
- USDC (Sepolia): https://sepolia.etherscan.io/address/0x1c7D4B196Cb0C7B01d743Fbc6116a902379C7238
- Sepolia Faucet: https://sepoliafaucet.com/
- Circle USDC Faucet: https://faucet.circle.com/
Once basic flow works, you can:
- Add cron jobs to auto-submit scores daily (using
computeDailyScore.py) - Build oracle signature UI for project owners to request score submissions
- Add arbitrator dispute resolution UI
- Implement refund logic for cancelled projects
- Add analytics dashboard for escrow metrics
- Test multi-milestone projects with complex contributor sets
Happy Testing! 🎉