Smart Contract Security Scan
Date: 2026-05-17 - Brain task #8906 - Repo: myaitoken/myai-contracts-base
Scope
Three deployed contracts on Base (target network):MyAIEscrow.sol, MyAIReputation.sol,MyAIGovernance.sol. 408 nSLOC total, Solidity 0.8.20, OpenZeppelin Contracts 5.x.
Tools
- Slither - Trail of Bits static analyzer (97-101 detectors per contract run, depending on imports).
- Aderyn 0.6.8 - Cyfrin Rust-based static analyzer (88 detectors).
- Mythril - skipped: symbolic execution times exceeded budget on the multi-call paths.
Findings summary (pre-fix)
| Severity | Count | Source |
|---|---|---|
| High | 2 | Slither + Aderyn (reentrancy-no-eth) |
| Medium | 2 | Slither (low-level-call in Governance.execute without nonReentrant); follow-up: quorumBps never enforced (fixed 2026-05-17, commit def347b) |
| Low / Info | 15+ | Aderyn + Slither (centralization, pragma, naming, etc.) |
Findings + remediation
H-1 - Reentrancy: state change after external call (MyAIEscrow.lockPayment)
State written after transferFrom. Protected bynonReentrant guard, but reorder still recommended.Fixed by writing escrows[jobId] and pushing to escrowIds before the token pull (CEI).
H-1 - Reentrancy: state change after external call (MyAIReputation.stake)
Had no reentrancy guard at all. Fixed by inheritingReentrancyGuard, adding nonReentrant tostake(), and reordering the state updates beforesafeTransferFrom.
M-1 - Low-level call in Governance.execute without reentrancy guard
p.target.call(p.callData) can re-enter back into Governance. Fixed by addingnonReentrant to execute() and markingreputation immutable.
M-2 - quorumBps declared but never enforced (added 2026-05-17)
MyAIGovernance.quorumBps = 1000 (10%) was declared as state but finalize() and execute()only checked votesFor > votesAgainst. A proposal could pass with a single voter regardless of turnout.Quorum bug fixed in commit def347b on 2026-05-17: propose() now snapshots total eligible voting weight, and finalize() reverts with custom error QuorumNotMet(participationBps, requiredBps)when turnout is below quorumBps. Four new unit tests (Q1-Q4) cover met / not-met / exactly-met / snapshot-stable; full suite: 70/70 passing.
L - Unsafe ERC20 operations (multiple)
All transfer / transferFrom calls migrated to OpenZeppelin SafeERC20. Supports tokens that do not return bool.
L - Missing zero-address checks (constructors + setters)
Added require(_x != address(0), ...) to all three constructors and setCoordinator / setTreasury.
L - State change without event (MyAIReputation.setCoordinator)
Added CoordinatorUpdated event and emit on change.setEscrowTimeout likewise emitsEscrowTimeoutUpdated and is bounded to [5min, 30d].
L - Unspecific pragma
Pinned all three contracts from ^0.8.20 to0.8.20.
Correctness bug found - latencyScore uses per-call latency
Not flagged by tools but caught during manual triage:recordCompletion recomputed reputation using thelast call's latencyMs rather than the running avgLatencyMs, making the latency component biased to whatever the most recent call happened to be. Fixed to use p.avgLatencyMs.
Accepted risks (not fixed)
- Centralization (owner / coordinator): Owner can pause Escrow, change feeBps (capped 10%), change coordinator and treasury. Coordinator can release and refund payments. This is intentional in v1; governance handover is on the roadmap.
- Block.timestamp comparisons: Used for escrow expiry, voting windows, and slash cooldown. Miner-manipulability window is ~12s on Base and never affects asset distribution (only when an already-locked escrow can be claimed back). Accepted.
- strict-equality registeredAt == 0: Intentional marker for "never seen".
Post-fix scan
- MyAIEscrow.sol - Slither: 0 results (filtering pragma/naming/event/timestamp info).
- MyAIGovernance.sol (incl. transitively imported MyAIReputation) - Slither: 2 informational (divide-before-multiply in reputation math, strict-equality on registeredAt). Both accepted.
- No High or Medium findings remain.
Fix commit
myaitoken/myai-contracts-base @ 463629a - security: fix H/M findings from Slither+Aderyn scan (#8906)
Disclaimer
Static analysis is not a substitute for a manual audit. We will commission a third-party manual audit prior to mainnet deployment of these contracts. Findings here are produced by automated tools (Slither, Aderyn) and triaged by the MyAi team.