This document outlines the cryptoeconomic guarantees of the ARGOS network.
ARGOS operates on a trust-through-incentives model, where economic game theory and cryptographic enforcement combine to ensure oracle accuracy. The security model leverages three pillars:
- UMA Optimistic Oracle - Cryptoeconomic finality and absolute truth anchor
- Reputation Staking - Economic skin-in-the-game for all participants
- Evolutionary Selection - Continuous filtering of inaccurate strategies
The UMA Optimistic Oracle serves as ARGOS's source of absolute truth. While ARGOS provides instant provisional results, UMA provides delayed but cryptoeconomically guaranteed finality.
UMA Security Guarantees:
- Economic Finality: Proposers and disputers stake bonds, ensuring rational actors cannot profitably lie
- Dispute Resolution: Any party can challenge a proposed result by staking a counter-bond
- Liveness Period: 48-hour window for disputes ensures sufficient time for economic consensus
- Scalable Security: Security scales with bond size (typically $2-10M for high-value queries)
// From contracts/AggregatorCore.sol
address public anchor; // UMA relayer authorized to submit final values
function anchorFinal(uint256 queryId, int256 finalValue)
external onlyAnchorOrOwner {
require(canAnchor(queryId), "NOT_READY_TO_ANCHOR");
Query storage q = queries[queryId];
q.finalValue = finalValue;
q.status = QueryStatus.Anchored;
emit FinalAnchored(queryId, finalValue);
}Security Properties:
- Only designated
anchoraddress can submit final values - Liveness period must expire before anchoring (
canAnchor()check) - Final value is immutable once set
- Event emission enables off-chain verification
The liveness period protects against premature anchoring:
function canAnchor(uint256 queryId) public view returns (bool) {
Query storage q = queries[queryId];
return q.status == QueryStatus.Active
&& block.timestamp >= q.createdAt + q.liveness;
}Attack Scenarios Prevented:
- Premature finalization: Cannot anchor before liveness expires
- Front-running: IONs cannot see UMA result before submitting
- Time-based manipulation: Liveness is blockchain time, not wall-clock time
ARGOS uses a reward-slash asymmetry to incentivize accuracy:
Correct predictions: +10× confidence (binary) or +15× confidence (numeric)
Wrong predictions: -5× confidence (binary) or -4× confidence (numeric)
Rationale: Higher rewards than slashing encourage participation, but slashing prevents spam.
From the settle() function in AggregatorCore.sol:
if (q.qtype == QueryType.Binary) {
if (absError == 0) {
// Correct prediction
reputation[preds[i].node] += 10 * preds[i].confidence;
} else {
// Wrong prediction
uint256 slash = preds[i].confidence * 5;
uint256 current = reputation[preds[i].node];
reputation[preds[i].node] = current > slash ? current - slash : 0;
}
}Security Properties:
- Proportional slashing: Higher confidence = higher penalty for being wrong
- No negative reputation:
current > slash ? current - slash : 0prevents underflow - All-or-nothing: No partial credit for binary queries (correct/incorrect only)
Example Scenario:
Query: "Will BTC hit $100k by Dec 31, 2025?"
Final Truth: YES (1)
Node A: Predicted YES (1) with 90 confidence → +900 reputation ✅
Node B: Predicted NO (0) with 70 confidence → -350 reputation ❌
Node C: Predicted YES (1) with 50 confidence → +500 reputation ✅
else {
// Numeric: tiered rewards based on error magnitude
if (absError <= 1) {
reputation[preds[i].node] += 15 * preds[i].confidence;
} else if (absError <= 5) {
reputation[preds[i].node] += 8 * preds[i].confidence;
} else {
uint256 slash = preds[i].confidence * 4;
uint256 current = reputation[preds[i].node];
reputation[preds[i].node] = current > slash ? current - slash : 0;
}
}Tiered Rewards:
- Very accurate (error ≤ 1): 15× confidence
- Moderately accurate (error ≤ 5): 8× confidence
- Inaccurate (error > 5): -4× confidence
Example Scenario:
Query: "What will SOL price be on Jan 1, 2026?" (Numeric)
Final Truth: 300
Node A: Predicted 301 with 80 confidence → Error = 1 → +1200 reputation ✅
Node B: Predicted 295 with 70 confidence → Error = 5 → +560 reputation ⚠️
Node C: Predicted 350 with 90 confidence → Error = 50 → -360 reputation ❌
In the current demo, reputation is purely numerical. In production:
Future Enhancements:
- Token staking: Reputation multiplies staked tokens for voting weight
- Economic slashing: Wrong predictions forfeit actual stake, not just reputation
- Reputation decay: Inactive nodes lose reputation over time
- Withdrawal delays: Prevent rage-quitting after wrong predictions
Attack: Create many low-quality nodes to outvote honest nodes
Mitigations:
- Reputation weighting: New nodes start with 0 reputation, have minimal influence
- Confidence-based consensus: Weight =
confidence × reputation × stake - One submission per address: Prevents same actor from multi-voting
- Economic barrier (future): Stake requirement creates financial friction
Code Defense:
require(!hasSubmitted[queryId][msg.sender], "ALREADY_SUBMITTED");
hasSubmitted[queryId][msg.sender] = true;Effectiveness: Without reputation, Sybil nodes have ~0% influence on consensus.
Attack: Multiple nodes coordinate to manipulate consensus
Vulnerability: If colluding nodes hold >50% of Σ(confidence × reputation), they can force wrong consensus
Mitigations:
- UMA anchoring: Even if provisional consensus is wrong, final truth prevails
- Slashing deterrent: Colluders lose reputation when UMA corrects them
- Domain specialization (future): Limits collusion to specific query types
- Quadratic weighting (future): Diminishing returns on confidence stacking
Attack Cost Analysis:
To corrupt a query with N honest nodes at 80% confidence avg:
- Attacker needs: Reputation ≥ N × 80 × (avg honest reputation)
- Cost of building reputation: Months of accurate predictions
- Cost of attack: Loss of all built reputation after UMA settlement
Conclusion: Economically irrational for rational attackers.
Attack: See other predictions before submitting, copy high-reputation nodes
Mitigations:
- Blockchain transparency: All submissions are public, no hiding
- Time advantage minimal: Consensus updates after each submission
- UMA final truth: Front-runners still subject to UMA's judgment
Why This Isn't Critical: Copying accurate nodes actually helps consensus accuracy. The network doesn't care how a node arrived at the right answer, only that it did.
Attack: Manipulate underlying data sources (e.g., flash loan price manipulation)
Mitigations:
- Multiple data sources: Diversity in ION strategies (APIs, LLMs, scraping, etc.)
- Outlier detection: Anomalous submissions can be ignored via low confidence
- UMA as referee: If manipulation affects provisional consensus, UMA corrects it
- Liveness period: 48-hour delay prevents real-time manipulation profitability
Example: Flash loan pumps BTC price to $200k for 1 block:
- Some API-based IONs might submit YES
- But: LLM reasoning, sentiment analysis, and smarter IONs submit NO
- Consensus likely leans NO (correctly)
- Even if YES wins provisionally, UMA anchors truth as NO 48h later
- Manipulated-IONs get slashed
Attack: Submit to every query with random guesses to spam the network
Mitigations:
- One submission per address per query:
require(!hasSubmitted[queryId][msg.sender]) - Reputation slashing: Random guesses have ~50% accuracy → net reputation loss
- Gas costs: Every submission costs gas, making spam expensive
- Stake requirements (future): Lock tokens to participate
Gas Cost Analysis:
Submission gas: ~80,000 gas
At 50 gwei: ~0.004 ETH (~$10 at $2500 ETH)
To spam 100 queries: $1000 in gas
Expected ROI: None (random guesses → slashed reputation)
Conclusion: Spam is economically unviable.
Attack: Build reputation slowly with correct predictions, then exploit it with one big wrong prediction
Mitigations:
- Proportional slashing: Exploit costs all built reputation
- Multi-dimensional reputation (future): Domain-specific scores prevent cross-domain exploitation
- Audit trails: All predictions on-chain, detectable patterns
Example:
Attacker spends 6 months building 10,000 reputation
Submits wrong prediction with 100 confidence on high-value query
Provisional consensus influenced (+10k weight)
UMA corrects 48h later
Attacker loses 100 × 5 = 500 reputation (not all 10k, but suffers for wrong answer)
Insight: Slashing is calibrated to hurt but not destroy, encouraging long-term participation.
Capabilities:
modifier onlyOwner() {
require(msg.sender == owner, "NOT_OWNER");
_;
}
// Owner-only functions:
- createQuery() // Create new queries
- setAnchor() // Designate anchor address
- settle() // Trigger reputation updatesSecurity Considerations:
- Owner has significant power (centralized in demo)
- Production: Owner should be a DAO multisig or governance contract
- Risk: Owner can censor queries or delay settlement
Mitigation Roadmap:
- Transfer ownership to multisig (3-of-5 initially)
- Implement governance token for voting
- Fully decentralize query creation (permissionless)
Capabilities:
modifier onlyAnchorOrOwner() {
require(msg.sender == owner || msg.sender == anchor, "NOT_ANCHOR");
_;
}
// Anchor can:
- anchorFinal() // Submit UMA final truthSecurity Properties:
- Anchor is typically a bot that monitors UMA Oracle
- Anchor cannot create queries or settle (lower privilege than owner)
- Anchor can be changed by owner at any time
Trust Assumption: Anchor correctly relays UMA truth without manipulation.
Verification: All FinalAnchored events are publicly auditable. Anyone can verify against UMA's on-chain state.
Capabilities:
- Anyone can submit predictions to active queries (
submitPrediction()is unpermissioned) - One submission per address per query
- No stake requirement in demo (future: must lock tokens)
Security Properties:
- Permissionless participation encourages diversity
- Economic barriers (gas + future stake) prevent pure spam
- Reputation gating ensures quality over time
Solidity 0.8+: Automatic overflow checks
pragma solidity ^0.8.20;All arithmetic operations revert on overflow/underflow without manual SafeMath.
Example:
reputation[preds[i].node] += 10 * preds[i].confidence;
// If this overflows, transaction reverts (safe)Current Status: No external calls in state-changing functions → no reentrancy risk
Functions analyzed:
submitPrediction(): No external callsanchorFinal(): No external callssettle(): No external calls, only internal state updates
Future Consideration: If token staking is added, use ReentrancyGuard from OpenZeppelin.
Comprehensive checks in submitPrediction():
require(q.id != 0, "QUERY_NOT_FOUND");
require(q.status == QueryStatus.Active, "QUERY_NOT_ACTIVE");
require(!hasSubmitted[queryId][msg.sender], "ALREADY_SUBMITTED");
require(confidence > 0, "CONFIDENCE_ZERO");
if (q.qtype == QueryType.Binary) {
require(value == 0 || value == 1, "BINARY_VALUE_INVALID");
require(confidence <= 100, "CONFIDENCE_TOO_HIGH");
}Security Properties:
- Prevents invalid states
- Ensures data integrity
- Provides clear error messages for debugging
Query Lifecycle: Active → Anchored → Settled
enum QueryStatus { Active, Anchored, Settled }
// State transitions are enforced:
submitPrediction: requires Status.Active
anchorFinal: requires Status.Active, sets Status.Anchored
settle: requires Status.Anchored, sets Status.SettledSecurity: Impossible to skip states or reverse transitions.
Storage patterns:
- Use
storagepointers to avoid redundant SLOAD:Query storage q = queries[queryId] - Pack struct fields efficiently (though not critical at demo scale)
- Event emission for off-chain indexing instead of on-chain arrays
Attack prevention: No unbounded loops in critical functions.
Concern: settle() loops through all predictions. For 1000+ predictions, could hit block gas limit.
Future Mitigation: Batch settlement or off-chain computation with Merkle proofs.
Current: Reputation is free to acquire (just predict accurately)
Future: Require token stake to submit predictions
mapping(address => uint256) public stakes;
function submitPrediction(uint256 queryId, int256 value, uint256 confidence) external {
require(stakes[msg.sender] >= MIN_STAKE, "INSUFFICIENT_STAKE");
// ... rest of logic
}
function slash(address node, uint256 amount) internal {
stakes[node] -= amount; // Actual economic loss
}Security Improvement: Makes spam economically impossible, increases attack cost.
Current: Single global reputation score
Future: Separate reputation per domain (crypto, sports, politics, etc.)
mapping(address => mapping(bytes32 => uint256)) public domainReputation;
function submitPrediction(...) {
bytes32 domain = keccak256(bytes(q.category));
uint256 weight = confidence * domainReputation[msg.sender][domain];
}Security Improvement: Prevents cross-domain reputation exploitation.
Current: Reputation is permanent
Future: Decay old reputation, weigh recent performance higher
function getEffectiveReputation(address node) public view returns (uint256) {
uint256 raw = reputation[node];
uint256 decayFactor = computeDecay(lastActive[node], block.timestamp);
return raw * decayFactor / 100;
}Security Improvement: Prevents inactive nodes from coasting on old reputation.
Current: No active adversarial detection
Future: ML-based anomaly detection for suspicious patterns
Signals:
- Sudden reputation surges
- Coordinated submissions (timing analysis)
- Outlier predictions (statistical analysis)
Action: Flagged nodes require higher stake or manual review.
Current: Predictions are public immediately
Future: Commit-reveal scheme to prevent front-running
// Phase 1: Commit
function commitPrediction(uint256 queryId, bytes32 commitment) external;
// Phase 2: Reveal (after commit period ends)
function revealPrediction(uint256 queryId, int256 value, uint256 confidence, bytes32 salt) external;Security Improvement: Eliminates front-running entirely.
All actions emit events for transparency:
event QueryCreated(uint256 indexed queryId, string description, QueryType qtype, uint256 liveness);
event PredictionSubmitted(uint256 indexed queryId, address indexed node, int256 value, uint256 confidence);
event ConsensusUpdated(uint256 indexed queryId, int256 provisional);
event FinalAnchored(uint256 indexed queryId, int256 finalValue);
event Settled(uint256 indexed queryId);Use Cases:
- Build reputation dashboards
- Verify anchor correctness against UMA
- Detect malicious patterns
- Analyze ION strategy effectiveness
Anyone can verify:
- Provisional consensus calculation (recalculate weighted average)
- UMA final truth (check UMA Oracle directly)
- Reputation updates (replay settlement logic)
Tooling (future):
- Blockchain explorer integration
- Automated verification bots
- Reputation API with historical tracking
-
UMA Oracle: ARGOS trusts UMA for final truth
- Justified: UMA has $100M+ TVL, battle-tested, economically secure
-
Anchor Bot: Correctly relays UMA results
- Mitigated: Anyone can verify relay accuracy on-chain
-
Owner: Acts in network's best interest
- Temporary: Will decentralize to DAO governance
-
Ethereum: L1 security and finality
- Standard: Same assumption as all DeFi protocols
Current (Demo Phase):
- ✅ High security (UMA-anchored)
⚠️ Moderate decentralization (owner-controlled)- ✅ High speed (instant provisional)
Future (Production):
- ✅ High security (stake + reputation + UMA)
- ✅ Full decentralization (DAO governance)
- ✅ High speed (unchanged)
ARGOS's security model combines:
- Cryptoeconomic finality via UMA
- Economic incentives via reputation and slashing
- Evolutionary pressure via reputation-weighted consensus
- Access controls via role-based permissions
- Smart contract safety via Solidity 0.8+ and input validation
The system is designed to be:
- Attack-resistant: Economic barriers make manipulation unprofitable
- Self-correcting: UMA anchoring overrides any provisional manipulation
- Evolvable: Reputation system filters out bad actors over time
For implementation details, see Architecture Documentation.
For integration guidance, see API Reference.
For building secure IONs, see ION Developer Guide.