Convexa has undergone formal security analysis using industry-standard tools. This document summarizes findings and mitigations.
Date: May 3, 2026
Scope: DebateEscrow.sol, ConvictionTracker.sol
Tools: Slither v0.11.5, TruffleHog, pip-audit, npm audit
Status: All critical and high-severity issues FIXED
Issue: DebateEscrow.settleSide() transferred ETH before updating state, enabling reentrancy attacks.
Mitigation: Implemented Checks-Effects-Interactions (CEI) pattern:
- Check all conditions upfront
- Update all state variables BEFORE external calls
- Make external calls last
Code:
// EFFECTS: Update state first
debateActive = false;
userStakes[staker][Side.BULL] = 0;
userStakes[staker][Side.BEAR] = 0;
// INTERACT: External calls last
(bool sent, ) = payable(staker).call{value: payout}("");Status: ✓ Fixed and verified
Issue: Constructor and setter functions didn't validate address parameters.
Mitigation: Added explicit zero-address checks:
require(_settlementExecutor != address(0), "Invalid executor");
require(newJudgeAgent != address(0), "Invalid judge");Status: ✓ Fixed
Issue: Judge could set conviction scores outside valid range (-100 to +100).
Mitigation: Added range validation:
require(conviction >= -100 && conviction <= 100, "Invalid conviction");Status: ✓ Fixed
Both contracts use role-based access control:
| Function | Access Control | Risk |
|---|---|---|
| settleSide() | Only executor | Trusted KeeperHub executor |
| recordVerdict() | Only judge agent | Trusted judge agent address |
| updateJudgeAgent() | Only owner | Trusted deployer |
All critical functions require explicit permissions. Unauthorized calls revert.
- Staked ETH locked in contract until settlement
- Settlement transfers happen in CEI pattern
- Re-entrancy guards via state updates before calls
- Only ETH accepted for staking (no ERC20 complexity)
- Uniswap integration uses production-grade token routing
Both contracts verified onchain:
- DebateEscrow: Blockscout
- ConvictionTracker: Blockscout
Source code matches deployed bytecode.
Run audit:
pip-auditAll dependencies pinned to specific versions. No known vulnerabilities in locked set.
Run audit:
cd contracts && npm auditNo high-severity vulnerabilities. Some medium-severity advisories for optional dev dependencies.
DEPLOYER_PRIVATE_KEY: Used only for contract deployment (once)AGENT_WALLET_PRIVATE_KEY: Used only for settlement transactions (KeeperHub executor)- Never hardcoded; loaded from
.env
- All keys loaded from
.envat runtime .envexcluded from version control (.gitignore)- Testnet-only keys (no mainnet credentials in repo)
Scan repository for exposed secrets:
trufflehog filesystem . --debugResult: No credentials found in committed files.
Test critical security functions:
cd contracts && npx hardhat testTest end-to-end security:
pytest tests/security/Tests cover:
- Reentrancy prevention
- Access control enforcement
- Input validation
- Token handling
-
Testnet Only: Contracts deployed on Unichain Sepolia testnet. Not audited for mainnet use.
-
Agent Trust: System assumes judge agent (Groq LLM) produces honest verdicts. Judge agent is controlled by system operator.
-
KeeperHub Trust: System assumes KeeperHub executor is trusted to broadcast transactions fairly.
-
Oracle Risk: Market data from Uniswap API trusted as-is (no price oracle). Large price movements could cause unexpected slippage.
✓ Reentrancy protection (CEI pattern)
✓ Zero-address validation
✓ Input validation (conviction range)
✓ Access control (role-based)
✓ Token handling (only ETH, no ERC20)
✓ Private key not hardcoded
✓ No exposed secrets in repo
✓ Dependencies audited
✓ Contracts verified onchain
✓ Tests pass (unit + integration)
If you discover a security issue:
- Do not open a public issue on GitHub
- Email security concerns to the maintainers
- Provide reproduction steps if possible
- Allow time for remediation before public disclosure