Spaces:
Running
Running
| { | |
| "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" | |
| } | |
| ] | |
| } |