Testnet only. Not audited. These pages describe intended behaviour, not shipped behaviour.

Maynexdocs

Security

Known-unsolved problems, what is out of scope, and how to report a vulnerability.

Not audited

No version of this project has been reviewed by a third party. It targets a testnet. Nothing here should hold value.

Known-unsolved problems

These four are open. They are stated here rather than left in an issue tracker because someone deciding whether to rely on this project needs them in front of them.

These descriptions are drafts

They state the general failure mode each title names. They have not been checked against an implementation, because there is not yet an implementation to check them against.

Approvals move no value

A spend limit that meters native value and ERC-20 transfer calls does not see approve. An approval moves nothing at call time; it grants a third party the right to move tokens later, outside any accounting the module performs. An agent operating well inside its limit can approve an unbounded allowance to an address it controls and drain the account in a separate transaction the module never observes.

increaseAllowance, setApprovalForAll, and Permit2 have the same shape. EIP-2612 permit is worse: it is a signature, so it need not originate from the account at all.

Metering at approval time is the obvious answer and it is wrong. Approving type(uint256).max is a routine gas optimisation, and revocations would have to refund the meter, which lets an agent cycle approve and revoke to reset it. Metering at transfer time is not possible, because the transfer happens through the spender and never re-enters the module.

Consequence

A spend limit alone does not bound what an agent can remove from an account.

Allowlisted routers reach arbitrary destinations

Allowlisting a target address constrains who is called, not what happens. A DEX router is a general-purpose execution engine: recipient addresses, callback targets, and nested calls all arrive as calldata. Allowlisting the router grants reachability to everything the router can reach, which is every address.

Universal-router command encoding, aggregator executor callbacks, and multicall entry points are each sufficient on their own. A recipient field is often enough by itself — the swap is legitimate and the output lands somewhere the agent chose.

Constraining calldata rather than the target moves the problem rather than removing it. It requires a per-router decoder that understands argument semantics, so the allowlist becomes a parser that must track upgrades, and a router changing its encoding silently converts a working constraint into a permissive one.

Window boundary permits double-spend

A fixed window that resets at a boundary permits two windows' worth of spend in an arbitrarily short interval: the full limit immediately before the reset, the full limit immediately after. A daily cap becomes a 2x cap across a few seconds spanning midnight. The mechanism behaves exactly as written; the written behaviour is not the intended one.

A sliding window resolves it and costs storage — per-transfer history, unbounded in the number of transfers, iterated on every check.

A token bucket with continuous refill is cheap and bounded, and changes the meaning of the limit. "100 per day" becomes a refill rate plus a burst capacity, which permits a full-capacity burst at any moment rather than only at a boundary. That may be preferable, but it is a different policy, and any documentation describing a daily cap would then be wrong.

Timelock queue can be flooded

A timelock delays an operation so a human can look at it. The delay is mechanical; the review is not. If queueing is permissionless or cheap, the queue can be filled faster than anyone can read it, and the protection the timelock provides — attention during the delay — degrades while the mechanism continues to report that it is working.

Cancellation does not settle this. If cancelling costs a transaction per item and queueing is batched or cheaper, the economics favour the attacker. Execution paths that iterate the queue add a gas-exhaustion failure on top.

Per-proposer rate limits, bonds, and a permissioned queue each help and each introduce a party who can stall legitimate operations, which is the failure the timelock exists to prevent.

Reporting a vulnerability

Email marketing@maynex.cloud. Do not open a public issue.

Include the file and a commit hash, what an attacker gains, and a reproduction — ideally a failing forge test case. Expect an acknowledgement within five working days; if none arrives, assume the mail was lost and send it again.

Out of scope

The four problems above are known and each already has an issue. A report restating one of them adds nothing. Also out of scope: anything requiring a compromised deployer key, and denial of service against a testnet RPC endpoint.

Disclosure

Once a fix is released, or ninety days have passed, publish freely. Say if you intend to, so these pages can be corrected at the same time rather than after.