{"id":13530331,"url":"https://github.com/transmissions11/solcurity","last_synced_at":"2025-05-15T14:06:14.914Z","repository":{"id":37461843,"uuid":"402241377","full_name":"transmissions11/solcurity","owner":"transmissions11","description":"Opinionated security and code quality standard for Solidity smart contracts.","archived":false,"fork":false,"pushed_at":"2023-07-02T23:04:48.000Z","size":89,"stargazers_count":2119,"open_issues_count":3,"forks_count":275,"subscribers_count":40,"default_branch":"main","last_synced_at":"2025-05-09T23:05:56.158Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/transmissions11.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-09-02T00:32:39.000Z","updated_at":"2025-05-07T07:13:14.000Z","dependencies_parsed_at":"2024-05-10T09:51:39.790Z","dependency_job_id":"4315be7c-bc54-4e4a-a306-881c8ee3aa58","html_url":"https://github.com/transmissions11/solcurity","commit_stats":null,"previous_names":["rari-capital/security-checklist","rari-capital/solcurity"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/transmissions11%2Fsolcurity","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/transmissions11%2Fsolcurity/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/transmissions11%2Fsolcurity/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/transmissions11%2Fsolcurity/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/transmissions11","download_url":"https://codeload.github.com/transmissions11/solcurity/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253540762,"owners_count":21924535,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-01T07:00:48.062Z","updated_at":"2025-05-15T14:06:09.899Z","avatar_url":"https://github.com/transmissions11.png","language":null,"funding_links":[],"categories":["Standards","Others","dApps directory","Programming Languages"],"sub_categories":["Blockchain Security Tools","Solidity"],"readme":"# The Solcurity Standard \n\nOpinionated **security** and **code quality** standard for **Solidity smart contracts**. \n\n_Based off work by [BoringCrypto](https://github.com/sushiswap/bentobox/blob/master/documentation/checks.txt), [Mudit Gupta](https://www.youtube.com/watch?v=LLiJK_VeAvQ), [Runtime Verification](https://github.com/runtimeverification/verified-smart-contracts/wiki/List-of-Security-Vulnerabilities), and [ConsenSys Diligence](https://consensys.github.io/smart-contract-best-practices/attacks/)_.\n\n### General Review Approach:\n- Read the project's docs, specs, and whitepaper to understand what the smart contracts are meant to do.\n- Construct a mental model of what you expect the contracts to look like before checking out the code.\n- Glance over the contracts to get a sense of the project's architecture. Tools like Surya can come in handy.\n- Compare the architecture to your mental model. Look into areas that are surprising.\n- Create a threat model and make a list of theoretical high level attack vectors.\n- Look at areas that can do value exchange. Especially functions like `transfer`, `transferFrom`, `send`, `call`, `delegatecall`, and `selfdestruct`. Walk backward from them to ensure they are secured properly.\n- Look at areas that interface with external contracts and ensure all assumptions about them are valid like share price only increases, etc.\n- Do a generic line-by-line review of the contracts.\n- Do another review from the perspective of every actor in the threat model.\n- Glance over the project's tests + code coverage and look deeper at areas lacking coverage.\n- Run tools like Slither/Solhint and review their output.\n- Look at related projects and their audits to check for any similar issues or oversights.\n\n## Variables\n\n- `V1` - Can it be `internal`?\n- `V2` - Can it be `constant`?\n- `V3` - Can it be `immutable`?\n- `V4` - Is its visibility set? (SWC-108)\n- `V5` - Is the purpose of the variable and other important information documented using natspec?\n- `V6` - Can it be packed with an adjacent storage variable?\n- `V7` - Can it be packed in a struct with more than 1 other variable?\n- `V8` - Use full 256 bit types unless packing with other variables.\n- `V9` - If it's a public array, is a separate function provided to return the full array?\n- `V10` - Only use `private` to intentionally prevent child contracts from accessing the variable, prefer `internal` for flexibility.\n\n## Structs\n\n- `S1` - Is a struct necessary? Can the variable be packed raw in storage?\n- `S2` - Are its fields packed together (if possible)?\n- `S3` - Is the purpose of the struct and all fields documented using natspec?\n\n## Functions\n\n- `F1` - Can it be `external`?\n- `F2` - Should it be `internal`?\n- `F3` - Should it be `payable`?\n- `F4` - Can it be combined with another similar function?\n- `F5` - Validate all parameters are within safe bounds, even if the function can only be called by a trusted users.\n- `F6` - Is the checks before effects pattern followed? (SWC-107)\n- `F7` - Check for front-running possibilities, such as the approve function. (SWC-114)\n- `F8` - Is insufficient gas griefing possible? (SWC-126)\n- `F9` - Are the correct modifiers applied, such as `onlyOwner`/`requiresAuth`?\n- `F10` - Are return values always assigned?\n- `F11` - Write down and test invariants about state before a function can run correctly.\n- `F12` - Write down and test invariants about the return or any changes to state after a function has run.\n- `F13` - Take care when naming functions, because people will assume behavior based on the name.\n- `F14` - If a function is intentionally unsafe (to save gas, etc), use an unwieldy name to draw attention to its risk.\n- `F15` - Are all arguments, return values, side effects and other information documented using natspec?\n- `F16` - If the function allows operating on another user in the system, do not assume `msg.sender` is the user being operated on.\n- `F17` - If the function requires the contract be in an uninitialized state, check an explicit `initialized` variable. Do not use `owner == address(0)` or other similar checks as substitutes.\n- `F18` - Only use `private` to intentionally prevent child contracts from calling the function, prefer `internal` for flexibility.\n- `F19` - Use `virtual` if there are legitimate (and safe) instances where a child contract may wish to override the function's behavior.\n\n## Modifiers\n\n- `M1` - Are no storage updates made (except in a reentrancy lock)?\n- `M2` - Are external calls avoided?\n- `M3` - Is the purpose of the modifier and other important information documented using natspec?\n\n## Code\n\n- `C1` - Using SafeMath or 0.8 checked math? (SWC-101)\n- `C2` - Are any storage slots read multiple times?\n- `C3` - Are any unbounded loops/arrays used that can cause DoS? (SWC-128)\n- `C4` - Use `block.timestamp` only for long intervals. (SWC-116)\n- `C5` - Don't use block.number for elapsed time. (SWC-116)\n- `C7` - Avoid delegatecall wherever possible, especially to external (even if trusted) contracts. (SWC-112)\n- `C8` - Do not update the length of an array while iterating over it.\n- `C9` - Don't use `blockhash()`, etc for randomness. (SWC-120)\n- `C10` - Are signatures protected against replay with a nonce and `block.chainid` (SWC-121)\n- `C11` - Ensure all signatures use EIP-712. (SWC-117 SWC-122)\n- `C12` - Output of `abi.encodePacked()` shouldn't be hashed if using \u003e2 dynamic types. Prefer using `abi.encode()` in general. (SWC-133)\n- `C13` - Careful with assembly, don't use any arbitrary data. (SWC-127)\n- `C14` - Don't assume a specific ETH balance. (SWC-132)\n- `C15` - Avoid insufficient gas griefing. (SWC-126)\n- `C16` - Private data isn't private. (SWC-136)\n- `C17` - Updating a struct/array in memory won't modify it in storage.\n- `C18` - Never shadow state variables. (SWC-119)\n- `C19` - Do not mutate function parameters.\n- `C20` - Is calculating a value on the fly cheaper than storing it?\n- `C21` - Are all state variables read from the correct contract (master vs. clone)?\n- `C22` - Are comparison operators used correctly (`\u003e`, `\u003c`, `\u003e=`, `\u003c=`), especially to prevent off-by-one errors?\n- `C23` - Are logical operators used correctly (`==`, `!=`, `\u0026\u0026`, `||`, `!`), especially to prevent off-by-one errors?\n- `C24` - Always multiply before dividing, unless the multiplication could overflow.\n- `C25` - Are magic numbers replaced by a constant with an intuitive name?\n- `C26` - If the recipient of ETH had a fallback function that reverted, could it cause DoS? (SWC-113)\n- `C27` - Use SafeERC20 or check return values safely.\n- `C28` - Don't use `msg.value` in a loop.\n- `C29` - Don't use `msg.value` if recursive delegatecalls are possible (like if the contract inherits `Multicall`/`Batchable`).\n- `C30` - Don't assume `msg.sender` is always a relevant user.\n- `C31` - Don't use `assert()` unless for fuzzing or formal verification. (SWC-110)\n- `C32` - Don't use `tx.origin` for authorization. (SWC-115)\n- `C33` - Don't use `address.transfer()` or `address.send()`. Use `.call.value(...)(\"\")` instead. (SWC-134)\n- `C34` - When using low-level calls, ensure the contract exists before calling.\n- `C35` - When calling a function with many parameters, use the named argument syntax.\n- `C36` - Do not use assembly for create2. Prefer the modern salted contract creation syntax.\n- `C37` - Do not use assembly to access chainid or contract code/size/hash. Prefer the modern Solidity syntax.\n- `C38` - Use the `delete` keyword when setting a variable to a zero value (`0`, `false`, `\"\"`, etc).\n- `C39` - Comment the \"why\" as much as possible. \n- `C40` - Comment the \"what\" if using obscure syntax or writing unconventional code.\n- `C41` - Comment explanations + example inputs/outputs next to complex and fixed point math.\n- `C42` - Comment explanations wherever optimizations are done, along with an estimate of much gas they save.\n- `C43` - Comment explanations wherever certain optimizations are purposely avoided, along with an estimate of much gas they would/wouldn't save if implemented.\n- `C44` - Use `unchecked` blocks where overflow/underflow is impossible, or where an overflow/underflow is unrealistic on human timescales (counters, etc). Comment explanations wherever `unchecked` is used, along with an estimate of how much gas it saves (if relevant).\n- `C45` - Do not depend on Solidity's arithmetic operator precedence rules. In addition to the use of parentheses to override default operator precedence, parentheses should also be used to emphasise it.\n- `C46` - Expressions passed to logical/comparison operators (`\u0026\u0026`/`||`/`\u003e=`/`==`/etc) should not have side-effects.\n- `C47` - Wherever arithmetic operations are performed that could result in precision loss, ensure it benefits the right actors in the system, and document it with comments. \n- `C48` - Document the reason why a reentrancy lock is necessary whenever it's used with an inline or `@dev` natspec comment.\n- `C49` - When fuzzing functions that only operate on specific numerical ranges use modulo to tighten the fuzzer's inputs (such as `x = x % 10000 + 1` to restrict from 1 to 10,000).\n- `C50` - Use ternary expressions to simplify branching logic wherever possible.\n- `C51` - When operating on more than one address, ask yourself what happens if they're the same.\n\n## External Calls\n\n- `X1` - Is an external contract call actually needed?\n- `X2` - If there is an error, could it cause DoS? Like `balanceOf()` reverting. (SWC-113)\n- `X3` - Would it be harmful if the call reentered into the current function?\n- `X4` - Would it be harmful if the call reentered into another function?\n- `X5` - Is the result checked and errors dealt with? (SWC-104)\n- `X6` - What if it uses all the gas provided?\n- `X7` - Could it cause an out-of-gas in the calling contract if it returns a massive amount of data?\n- `X8` - If you are calling a particular function, do not assume that `success` implies that the function exists (phantom functions).\n\n## Static Calls\n\n- `S1` - Is an external contract call actually needed?\n- `S2` - Is it actually marked as view in the interface?\n- `S3` - If there is an error, could it cause DoS? Like `balanceOf()` reverting. (SWC-113)\n- `S4` - If the call entered an infinite loop, could it cause DoS?\n\n## Events\n\n- `E1` - Should any fields be indexed?\n- `E2` - Is the creator of the relevant action included as an indexed field?\n- `E3` - Do not index dynamic types like strings or bytes.\n- `E4` - Is when the event emitted and all fields documented using natspec?\n- `E5` - Are all users/ids that are operated on in functions that emit the event stored as indexed fields?\n- `E6` - Avoid function calls and evaluation of expressions within event arguments. Their order of evaluation is unpredictable.\n\n## Contract\n\n- `T1` - Use an SPDX license identifier.\n- `T2` - Are events emitted for every storage mutating function?\n- `T3` - Check for correct inheritance, keep it simple and linear. (SWC-125)\n- `T4` - Use a `receive() external payable` function if the contract should accept transferred ETH.\n- `T5` - Write down and test invariants about relationships between stored state.\n- `T6` - Is the purpose of the contract and how it interacts with others documented using natspec?\n- `T7` - The contract should be marked `abstract` if another contract must inherit it to unlock its full functionality.\n- `T8` - Emit an appropriate event for any non-immutable variable set in the constructor that emits an event when mutated elsewhere.\n- `T9` - Avoid over-inheritance as it masks complexity and encourages over-abstraction.\n- `T10` - Always use the named import syntax to explicitly declare which contracts are being imported from another file.\n- `T11` - Group imports by their folder/package. Separate groups with an empty line. Groups of external dependencies should come first, then mock/testing contracts (if relevant), and finally local imports.\n- `T12` - Summarize the purpose and functionality of the contract with a `@notice` natspec comment. Document how the contract interacts with other contracts inside/outside the project in a `@dev` natspec comment.\n\n## Project\n\n- `P1` - Use the right license (you must use GPL if you depend on GPL code, etc).\n- `P2` - Unit test everything.\n- `P3` - Fuzz test as much as possible.\n- `P4` - Use symbolic execution where possible.\n- `P5` - Run Slither/Solhint and review all findings.\n\n## DeFi\n\n- `D1` - Check your assumptions about what other contracts do and return.\n- `D2` - Don't mix internal accounting with actual balances.\n- `D3` - Don't use spot price from an AMM as an oracle.\n- `D4` - Do not trade on AMMs without receiving a price target off-chain or via an oracle.\n- `D5` - Use sanity checks to prevent oracle/price manipulation.\n- `D6` - Watch out for rebasing tokens. If they are unsupported, ensure that property is documented.\n- `D7` - Watch out for ERC-777 tokens. Even a token you trust could preform reentrancy if it's an ERC-777.\n- `D8` - Watch out for fee-on-transfer tokens. If they are unsupported, ensure that property is documented.\n- `D9` - Watch out for tokens that use too many or too few decimals. Ensure the max and min supported values are documented.\n- `D10` - Be careful of relying on the raw token balance of a contract to determine earnings. Contracts which provide a way to recover assets sent directly to them can mess up share price functions that rely on the raw Ether or token balances of an address.\n- `D11` - If your contract is a target for token approvals, do not make arbitrary calls from user input.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftransmissions11%2Fsolcurity","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftransmissions11%2Fsolcurity","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftransmissions11%2Fsolcurity/lists"}