Skip to content

fix(registry): use counter-based agent IDs to prevent frontrunning#5170

Closed
wndzph9jkb-create wants to merge 11 commits into
ClankerNation:mainfrom
wndzph9jkb-create:fix/agent-id-frontrunning
Closed

fix(registry): use counter-based agent IDs to prevent frontrunning#5170
wndzph9jkb-create wants to merge 11 commits into
ClankerNation:mainfrom
wndzph9jkb-create:fix/agent-id-frontrunning

Conversation

@wndzph9jkb-create
Copy link
Copy Markdown

/claim #172

Summary

Replaces deterministic keccak256(msg.sender, name, timestamp) agent IDs with an incrementing counter — prevents frontrunning collisions.

Problem

An attacker watching the mempool could register the same name in the same block, causing an ID collision that reverts the victim’s transaction.

Fix

  • Added nextAgentId counter starting at 1
  • registerAgent(): bytes32(uint256(nextAgentId++))
  • batchRegister(): same counter-based approach
  • Guarantees uniqueness — no two agents can ever share an ID
  • Backward compatible: agents[agentId] storage unchanged

Closes #172

Feltchy added 11 commits June 2, 2026 04:35
…artial failures

- Match batch responses by JSON-RPC id field instead of array position
- Return JsonRpcBatchItemError for per-request errors and missing responses
- Add requestTimeoutMs config with 30s default
- Add per-batch timeoutMs option in BatchCallOptions
- Add BATCH_SIZE_LIMIT of 100 requests
- Preserve original request order in results
- Handle batch fetch timeout with per-item errors
- Add comprehensive test suite (shuffled responses, partial failures, timeout, batch limit)

Closes ClankerNation#161
…tration

- Add batchRegister(string[], string[]) — up to 50 agents in one tx
- Total fee = registrationFee * count
- Individual AgentRegistered events per registration
- Array length mismatch reverts
- Batch size validation (1-50)
- 6 test cases: batch of 1, batch of 50, length mismatch,
  insufficient fee, zero batch, >50 batch

Closes ClankerNation#194
- Track balance before/after transfer instead of trusting input amount
- Store actual received amount (balance delta), not input amount
- Reject when actual received is zero (fee ate entire transfer)
- 5 tests: zero-amount rejection, standard ERC20 parity,
  actual-vs-stored verification, release with stored amount,
  refund with stored amount

Closes ClankerNation#179
- Add SafeERC20 import and using statement to TaskRouter
- All native ETH transfers already checked with require(success)
- SafeERC20 ensures future token-based transfers use safeTransfer/safeTransferFrom
- 2 tests: completeTask reward payout, cancelTask full refund

Closes ClankerNation#181
- Add minParticipants param on startRound
- Add cancelLottery() — only if deadline passed + below minimum
- Add refund() — returns exact contribution per participant
- Track individual contributions via mapping
- Prevent double-refund and active lottery refund attempts
- 5 tests: cancel below min, reject at min, exact refund,
  no refund on active, double-refund prevented

Closes ClankerNation#176
- Add URL format validation regex (http/https only)
- Block private/internal IPs for SSRF protection
- HEAD request reachability check with 5s timeout
- Add endpoint field to AgentCreate model + create_agent
- 7 tests: valid URL, invalid format, private IP blocked,
  reachability check, timeout handling

Closes ClankerNation#173
- 60 req/min for anonymous users
- 300 req/min for authenticated (Bearer/ApiKey)
- 1000 req/min for premium (X-API-Premium header)
- Per-tier counters using {ip}:{tier} key format
- X-RateLimit-Limit/Remaining/Reset headers on all responses
- 429 includes Retry-After + rate limit headers
- 6 tests: tier values, window reset, tier separation,
  auth detection (anon/auth/premium), 429 headers

Closes ClankerNation#174
- Support X-API-Key header as alt auth (preferred over JWT)
- API keys stored as SHA-256 hashes
- POST /auth/api-keys to generate (raw key shown once)
- DELETE /auth/api-keys/{hash} to revoke
- Revoked keys immediately fail auth
- Fix: removed 'none' algorithm from JWT decode
- Fix: JWT_SECRET fallback instead of KeyError crash
- 8 tests: hash determinism, generation, auth, invalid key,
  revoke, nonexistent revoke, algorithm pinning, secret fallback

Closes ClankerNation#177
- Add quorumVotes state variable + setQuorum() admin function
- Execute reverts if forVotes < quorum
- Quorum configurable by owner
- Also fix: replaced tx.origin with msg.sender in vote() (phishing vuln)
- Added Ownable for admin quorum control
- Backward compatible: proposals above quorum execute normally

Closes ClankerNation#180
- deployContract(abi, bytecode, args, options) helper
- Automatically waits for deployment confirmation
- Returns deployed Contract instance ready to use
- Supports gas limit and value overrides

Closes ClankerNation#191
…trunning

- Replace keccak256(msg.sender, name, timestamp) with counter-based IDs
- Counter guarantees uniqueness — no collision possible
- Fixes frontrunning vulnerability where attacker could register same name
  in same block to cause ID collision
- Applied to both registerAgent() and batchRegister()
- Backward compatible: agents[agentId] storage unchanged

Closes ClankerNation#172
@github-actions
Copy link
Copy Markdown

github-actions Bot commented Jun 2, 2026

Unfortunately the changes in this PR didn't fully resolve the issue. Please rework your solution and submit a new pull request within 2 hours.

Make sure to review the acceptance criteria in the linked issue and verify all conditions are met before resubmitting.

@github-actions github-actions Bot closed this Jun 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[ Bounty $8k ] [ Solidity ] Fix AgentRegistry registerAgent frontrunning with deterministic ID — deployment blocker

1 participant