{ "contract_name": "ExampleContract", "file_name": "ExampleContract.sol", "metadata": { "license": "MIT", "solidity_version": "0.8.0", "description": "Example contract demonstrating the template structure", "author": "Example Author" }, "state_variables": [ { "name": "owner", "type": "address", "visibility": "public", "mutability": "", "description": "Address of the contract owner" }, { "name": "balances", "type": "mapping(address => uint256)", "visibility": "internal", "mutability": "", "description": "User token balances" } ], "functions": [ { "name": "transfer", "signature": "transfer(address to, uint256 amount)", "code": "function transfer(address to, uint256 amount) external returns (bool) {\n require(to != address(0), \"INVALID_RECIPIENT\");\n require(balances[msg.sender] >= amount, \"INSUFFICIENT_BALANCE\");\n balances[msg.sender] -= amount;\n balances[to] += amount;\n emit Transfer(msg.sender, to, amount);\n return true;\n}", "comment": "Transfers tokens from caller to recipient", "visibility": "external", "modifiers": [], "parameters": [ { "name": "to", "type": "address", "description": "Recipient address" }, { "name": "amount", "type": "uint256", "description": "Amount to transfer" } ], "returns": "bool - true on success", "output_property": "Decreases caller's balance by amount, increases recipient's balance by amount. Emits Transfer event. Reverts if recipient is zero address or caller has insufficient balance.", "events": [ "Transfer" ], "vulnerable": false, "vulnerability_details": null, "property": null, "property_specification": null }, { "name": "withdraw", "signature": "withdraw(uint256 amount)", "code": "function withdraw(uint256 amount) external {\n require(balances[msg.sender] >= amount, \"INSUFFICIENT_BALANCE\");\n balances[msg.sender] -= amount;\n (bool success, ) = msg.sender.call{value: amount}(\"\");\n require(success, \"TRANSFER_FAILED\");\n}", "comment": "Withdraws ETH from contract", "visibility": "external", "modifiers": [], "parameters": [ { "name": "amount", "type": "uint256", "description": "Amount to withdraw" } ], "returns": "", "output_property": "Transfers amount ETH to caller. Reverts if insufficient balance or ETH transfer fails.", "events": [], "vulnerable": true, "vulnerability_details": { "issue": "Reentrancy vulnerability", "severity": "High", "description": "The withdraw function updates balance after making an external call, allowing reentrancy attacks", "mitigation": "Use checks-effects-interactions pattern: update balance before external call" }, "property": "When a user withdraws x amount of ETH, the user's balance should decrease by x. Due to reentrancy, an attacker can call withdraw recursively before balance is updated, draining more than their balance.", "property_specification": { "precondition": "User balance = B", "operation": "withdraw(amount)", "postcondition": "User balance = B - amount", "actual": "Reentrant calls allow user balance = B - (n * amount) where n > 1" } } ], "structs": [ { "name": "MintLocalVars", "definition": "struct MintLocalVars {\n uint256 previousSupply;\n uint256 nextSupply;\n uint256 amountInRay;\n uint256 newRate;\n uint256 currentAvgRate;\n}", "description": "Local variables used in mint function to avoid stack too deep errors" } ], "modifiers": [ { "name": "onlyOwner", "definition": "require(msg.sender == owner, \"NOT_OWNER\");", "purpose": "Restricts function access to contract owner only" }, { "name": "nonReentrant", "definition": "Inherited from OpenZeppelin ReentrancyGuard", "purpose": "Prevents reentrancy attacks by using a mutex lock" } ], "inheritance": [ "ERC20", "Ownable" ], "call_graph": { "constructor": [ "ERC20.constructor()" ], "transfer": [ "emit Transfer()" ], "withdraw": [ "msg.sender.call()" ] }, "audit_issues": [ { "function": "withdraw", "issue": "Reentrancy vulnerability", "severity": "High", "description": "The withdraw function updates state after making an external call, allowing reentrancy attacks where an attacker can recursively call withdraw before the balance is updated", "status": "Fixed", "mitigation": "Moved balance update before external call (checks-effects-interactions pattern)", "property": "When a user withdraws x amount, the user's balance should decrease by x. Due to reentrancy, an attacker can withdraw multiple times before balance updates, draining more than their balance.", "property_specification": { "precondition": "User balance = B", "operation": "withdraw(amount)", "postcondition": "User balance = B - amount", "actual": "Reentrant calls allow user balance = B - (n * amount) where n > 1" } } ], "events": [ { "name": "Transfer", "parameters": "address indexed from, address indexed to, uint256 amount", "description": "Emitted when tokens are transferred" }, { "name": "Withdrawal", "parameters": "address indexed user, uint256 amount", "description": "Emitted when ETH is withdrawn" } ] }