Contract audit: Solidity security review by address or source
Contract audit for Solidity and Vyper: give a verified contract address (Ethereum, Base, Arbitrum, Optimism, Polygon) or paste the source, and one call returns security findings by severity with function, line, exploit scenario and fix, who holds the owner and upgrade keys on chain, a score and a Markdown report, in about a minute. Automated review, not a manual audit. Use before deploying, integrating with or buying into a contract.
Inputs
| Name | Type | Description |
|---|---|---|
source | string | Solidity or Vyper source code, or the compiler's standard JSON input, up to 300,000 characters; POST it in a JSON body when it is long. Send this or address |
address | string | Verified contract 0x address (a proxy is followed to its implementation). Send this or source |
chain | string | ethereum (default), base, arbitrum, optimism or polygon; used with address |
context | string | Optional notes for the reviewers, up to 1,000 characters: what the contract is for or what worries you |
Request
Over HTTP, with a card key from /credits:
curl -H "Authorization: Bearer adt_…" "https://tools.funwords.eu/contract/audit?source=pragma%20solidity%20%5E0.8.20%3B%20contract%20Vault%20%7B%20mapping(address%20%3D%3E%20uint256)%20public%20balances%3B%20function%20deposit()%20external%20payable%20%7B%20balances%5Bmsg.sender%5D%20%2B%3D%20msg.value%3B%20%7D%20function%20withdraw()%20external%20%7B%20(bool%20ok%2C%20)%20%3D%20msg.sender.call%7Bvalue%3A%20balances%5Bmsg.sender%5D%7D(%22%22)%3B%20require(ok)%3B%20balances%5Bmsg.sender%5D%20%3D%200%3B%20%7D%20%7D"
Without a key, the same URL answers 402 Payment Required with x402 and MPP terms, so an agent with a wallet pays per call in USDC (Base, Polygon, Arbitrum or Solana over x402; Base or Tempo over MPP) and retries.
Example result
{
"contract": {
"name": "Vault",
"chain": null,
"address": null,
"implementation": null,
"proxyType": null,
"compiler": "^0.8.20",
"language": "Solidity",
"verified": null,
"sourceFrom": "source sent by the caller",
"type": "vault"
},
"verdict": "critical-risk",
"score": 55,
"counts": {
"critical": 1,
"high": 0,
"medium": 0,
"low": 0,
"info": 0
},
"summary": "Vault holds ETH per account. withdraw sends the ETH before it clears the balance, so a deposit can be withdrawn repeatedly.",
"findings": [
{
"id": "F-1",
"severity": "critical",
"title": "State is updated after an external call (reentrancy)",
"category": "reentrancy",
"contract": "Vault",
"function": "withdraw",
"file": "Contract.sol",
"line": 1,
"description": "withdraw makes an external call and only afterwards writes balances.",
"scenario": "A contract re-enters withdraw from its receive function.",
"recommendation": "Write state before the call and add a reentrancy guard.",
"confidence": "high",
"foundBy": [
"static-check",
"reviewer-funds",
"reviewer-logic"
]
}
],
"access": {
"owner": null,
"proxyAdmin": null,
"upgradeable": false,
"paused": null,
"privilegedFunctions": [
{
"contract": "Vault",
"function": "pause",
"guard": "onlyOwner"
}
],
"roles": [
{
"role": "owner",
"powers": [
"pause withdrawals"
]
}
],
"onChain": "not applicable: source was sent without an address"
},
"coverage": {
"filesReviewed": [
"Contract.sol"
],
"filesNotReviewed": [],
"trustedLibraries": [],
"linesOfCode": 1,
"charactersReviewed": 290,
"complete": true,
"reviewers": [
{
"id": "reviewer-logic",
"model": "gpt-oss-120b",
"status": "answered",
"findings": 1,
"discarded": 0
}
],
"secondLook": {
"confirmed": 0,
"refuted": 0,
"uncertain": 0
},
"staticChecks": "1 pattern findings over 2 functions"
},
"method": "Automated review: static checks, on-chain key-holder reads and AI reviewers.",
"limitations": "Not a manual audit and not a guarantee.",
"auditedAt": "2026-11-11T12:00:00.000Z",
"report": "# Smart contract audit: Vault\n\n- **Verdict:** critical risk (score 55/100)"
}
From an AI agent (MCP)
Add the MCP server to Claude, Cursor or any MCP client. This tool is contract_audit, and the first 25 successful calls are free:
https://tools.funwords.eu/mcp