Security
Overview#
This page summarizes the security properties of the AGDEL protocol, covering the smart contract (SignalMarketplace.sol, Solidity 0.8.24), the backend API (FastAPI), and the keeper bot. The assessment was completed during Phase 8.
Reentrancy Protection#
All functions that transfer tokens use OpenZeppelin's ReentrancyGuard combined with the Checks-Effects-Interactions (CEI) pattern. State updates happen before external calls, and the reentrancy lock prevents re-entry during execution.
| Function | Transfers | Protection |
|---|---|---|
buySignal() | USDC from buyer to contract | ReentrancyGuard + CEI |
resolveSignal() | USDC to maker + protocol | ReentrancyGuard + CEI |
claimRefund() | USDC to buyer | ReentrancyGuard + CEI |
withdrawFees() | USDC to owner | ReentrancyGuard + CEI |
Arithmetic Safety#
Solidity 0.8.24 provides built-in overflow and underflow protection. Multiplication operations that could exceed uint256 use explicit widening. The pro-rata refund calculation has been fuzz-tested and produces maximum rounding dust of less than 1 USDC unit (0.000001 USDC), which is negligible.
Access Control#
| Role | Capabilities | Assignment |
|---|---|---|
| Owner | Pause/unpause, add/remove keepers, withdraw fees | Deployer, transferable |
| Keeper | resolveSignal() only | Added by owner, multiple allowed |
| Maker | createSignal(), cancelSignal() (own signals only) | Any address |
| Buyer | buySignal(), claimRefund() (own purchases only) | Any address |
The pause mechanism is scoped: createSignal() and buySignal() can be paused, but resolveSignal(), claimRefund(), and withdrawFees() cannot. This ensures that funds can always be withdrawn even during a pause.
Commitment Integrity#
The commitment hash is computed as:
commitmentHash = keccak256(makerAddress, targetPrice, direction, salt)Including the maker's address in the hash prevents hash reuse across different makers. The salt is 32 bytes of cryptographic randomness generated server-side. At resolution, the keeper must provide params that produce an identical hash, ensuring the maker cannot change their prediction after listing.
Front-Running Mitigation#
Two mechanisms prevent front-running:
- Commit-reveal: The target price and direction are hidden until after purchase. There is no way to see the prediction from on-chain data before buying.
- Buying cutoff: Each duration has a cutoff period (15s to 30m) before expiry where new purchases are rejected. This prevents last-minute purchases when the outcome is near-certain.
Economic Invariants#
- Total escrow for a signal always equals
costUsdc × buyerCount - On HIT: maker payout (90%) + protocol fee (10%) = total escrow
- On MISS: sum of all refunds (90%) + protocol fee (10%) = total escrow
- Pro-rata refunds are calculated as
(buyerPayment / totalEscrow) × refundPool - Maximum rounding dust per refund is less than 1 USDC unit (< $0.000001)
Backend Security#
Security hardening measures added in Phase 8:
- Timing-safe API key comparison: Uses
hmac.compare_digestto prevent timing attacks - Rate limiting: 10–60 requests/min depending on route sensitivity
- Anti-enumeration: Payload endpoint returns the same 403 error whether the signal doesn't exist or the caller hasn't purchased
- Error sanitization: Generic error messages to clients, full details in server logs only
- Authorization header cap: 2KB limit to prevent oversized header attacks
- Timestamp tolerance: ±5 minutes for EIP-191 signatures, preventing replay attacks beyond that window
USDC Trust Assumptions#
The contract uses SafeERC20 for all USDC interactions. The USDC address is immutable (set at deployment). The protocol trusts that USDC behaves as a standard ERC-20 token. External risks include USDC blacklisting (Circle can freeze specific addresses), which is outside the protocol's control.
Risk Summary#
| Category | Risk Level | Status |
|---|---|---|
| Reentrancy | Low | Mitigated (ReentrancyGuard + CEI) |
| Overflow/Underflow | None | Solidity 0.8.24 checked arithmetic |
| Access Control | Low | Proper role separation |
| Commitment Integrity | Low | Address prefix + 32-byte salt |
| Refund Rounding | Negligible | Sub-cent dust, fuzz tested |
| Front-Running | Low | Commit-reveal + buying cutoff |
| USDC Trust | Low | SafeERC20, immutable address |
No known exploitable vulnerabilities were found during the Phase 8 security review. The contract was analyzed using Slither static analysis and manual review.