├── .github └── workflows │ └── main.yml ├── .gitignore ├── LICENSE ├── README.md ├── entries ├── CNAME ├── docs │ ├── SWC-100.md │ ├── SWC-101.md │ ├── SWC-102.md │ ├── SWC-103.md │ ├── SWC-104.md │ ├── SWC-105.md │ ├── SWC-106.md │ ├── SWC-107.md │ ├── SWC-108.md │ ├── SWC-109.md │ ├── SWC-110.md │ ├── SWC-111.md │ ├── SWC-112.md │ ├── SWC-113.md │ ├── SWC-114.md │ ├── SWC-115.md │ ├── SWC-116.md │ ├── SWC-117.md │ ├── SWC-118.md │ ├── SWC-119.md │ ├── SWC-120.md │ ├── SWC-121.md │ ├── SWC-122.md │ ├── SWC-123.md │ ├── SWC-124.md │ ├── SWC-125.md │ ├── SWC-126.md │ ├── SWC-127.md │ ├── SWC-128.md │ ├── SWC-129.md │ ├── SWC-130.md │ ├── SWC-131.md │ ├── SWC-132.md │ ├── SWC-133.md │ ├── SWC-134.md │ ├── SWC-135.md │ └── SWC-136.md └── index.md ├── mkdocs.yml └── requirements.txt /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: Build, and deploy 2 | on: [push, pull_request] 3 | 4 | jobs: 5 | build: 6 | name: Test and deploy 7 | runs-on: ubuntu-latest 8 | env: 9 | SHOULD_DEPLOY: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' }} 10 | steps: 11 | - name: Clone the repository 12 | uses: actions/checkout@v2 13 | - name: Install Python 3.11 14 | uses: actions/setup-python@v2 15 | with: 16 | python-version: 3.11 17 | cache: 'pip' 18 | - name: Install requirements 19 | run: pip install -r requirements.txt 20 | - name: Build the site with mkdocs 21 | run: mkdocs build 22 | - name: Deploy to Github Pages 23 | if: fromJSON(env.SHOULD_DEPLOY) 24 | run: mkdocs gh-deploy --force 25 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .solhint.json 2 | .solium* 3 | *~ 4 | .DS_Store 5 | node_modules/ 6 | .vscode/ 7 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018-present Smart Contract Weakness Classification Registry 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # This registry is no longer actively maintained 2 | 3 | ## New SWC entries have not not been added since 2020 4 | 5 | This registry has not been significantly updated since 2020, and is no longer actively maintained. While some maintenance may be done 6 | to enhance or clarify the status of the current content, and pointers will be added to new work that is maintained such as the 7 | [EEA EthTrust Security Levels Specification](https://entethalliance.org/specs/ethtrust-sl/), new SWCs are no longer being added, 8 | and readers should check external sources to clarify the relevance of existing content. 9 | 10 | All the vulnerabilities described in this repository were incorporated into version 1 of the **[EEA EthTrust Security Levels specification](https://entethalliance.org/specs/ethtrust-sl)**, published in August 2022 11 | 12 | The [EEA EthTrust Security Levels](https://entethalliance.org/groups/ethtrust) project is actively maintained. 13 | The **[Editor's draft for a new version](https://entethalliance.github.io/eta-registry/security-levels-spec.html)** is publicly available. 14 | 15 | [EthTrust Security Leveles Version 2](https://entethalliance.org/specs/ethtrust-sl/v2) was published in December 2023, with publication of version 3 expected in early 2025. 16 | 17 | Another project that has been maintained over a number of years is the [Smart Contract Security Verification Standard](https://github.com/ComposableSecurity/SCSVS). 18 | 19 | The EthTrust specification is specific to Solidity code, and aims to comprehensively identify vulnerabilities that need to be checked for, and if present eliminated. The SCSVS is a more general development guideline for security testing and remediation, applicable to a large range of projects. 20 | 21 | # Smart Contract Weakness Classification Registry 22 | 23 | The Smart Contract Weakness Classification Registry (SWC Registry) is an implementation of the weakness classification scheme proposed in [EIP-1470](https://github.com/ethereum/EIPs/issues/1469). It is loosely aligned to the terminologies and structure used in the Common Weakness Enumeration ([CWE](https://cwe.mitre.org)) while overlaying a wide range of weakness variants that are specific to smart contracts. 24 | 25 | The goals of this project were as follows: 26 | 27 | - Provide a straightforward way to classify security issues in smart contract systems. 28 | - Define a common language for describing security issues in smart contract systems' architecture, design, or code. 29 | - Serve as a way to train and increase performance for smart contract security analysis tools. 30 | 31 | 32 | 33 | ### Scope of Weaknesses 34 | 35 | SWCs are concerned with weaknesses that can be identified within Solidity code of a smart contract. 36 | Weaknesses in 'smart contract adjacent' code are not covered by this registry of Weaknesses. 37 | For example, the [gas siphoning attack](https://github.com/SmartContractSecurity/SWC-registry/pull/140) occurs in wallet code, 38 | and should be protected against in wallet code. 39 | -------------------------------------------------------------------------------- /entries/CNAME: -------------------------------------------------------------------------------- 1 | swcregistry.io 2 | -------------------------------------------------------------------------------- /entries/docs/SWC-100.md: -------------------------------------------------------------------------------- 1 | # Please note, this content is no longer actively maintained. 2 | 3 | The content of the SWC registry has not been thoroughly updated since 2020. It is known to be incomplete and may contain errors as well as crucial omissions. 4 | 5 | For currently maintained guidance on known Smart Contract vulnerabilities written primarily as guidance for security reviewers, please see the 6 | [EEA EthTrust Security Levels specification](https://entethalliance.org/specs/ethtrust-sl). As well as the latest release version, an 7 | [Editor's draft](https://entethalliance.github.io/eta-registry/security-levels-spec.html) is available, 8 | that represents the latest work of the group developing the specification. 9 | 10 | General guidance for developers on what to consider to ensure security, that is currently maintained, is also available through the 11 | [Smart Contract Security Verification Standard (SCSVS)](https://github.com/ComposableSecurity/SCSVS). 12 | 13 | # Title 14 | 15 | Function Default Visibility 16 | 17 | ## Relationships 18 | 19 | - [CWE-710: Improper Adherence to Coding Standards](https://cwe.mitre.org/data/definitions/710.html) 20 | - EthTrust Security Levels: 21 | - [**[Q] Code Linting**](https://entethalliance.org/specs/ethtrust-sl/#req-3-linted) 22 | 23 | ## Description 24 | 25 | Functions that do not have a function visibility type specified are `public` by default. This can lead to a vulnerability if a developer forgot to set the visibility and a malicious user is able to make unauthorized or unintended state changes. 26 | 27 | ## Remediation 28 | 29 | Functions can be specified as being `external`, `public`, `internal` or `private`. It is recommended to make a conscious decision on which visibility type is appropriate for a function. This can dramatically reduce the attack surface of a contract system. 30 | 31 | ## References 32 | 33 | - [Ethereum Smart Contract Best Practices - Visibility](https://consensys.github.io/smart-contract-best-practices/development-recommendations/solidity-specific/visibility/) 34 | - [SigmaPrime - Visibility](https://github.com/sigp/solidity-security-blog#visibility) 35 | 36 | ## Samples 37 | 38 | ### visibility_not_set.sol 39 | 40 | ```solidity 41 | /* 42 | * @source: https://github.com/sigp/solidity-security-blog#visibility 43 | * @author: SigmaPrime 44 | * Modified by Gerhard Wagner 45 | */ 46 | 47 | pragma solidity ^0.4.24; 48 | 49 | contract HashForEther { 50 | 51 | function withdrawWinnings() { 52 | // Winner if the last 8 hex characters of the address are 0. 53 | require(uint32(msg.sender) == 0); 54 | _sendWinnings(); 55 | } 56 | 57 | function _sendWinnings() { 58 | msg.sender.transfer(this.balance); 59 | } 60 | } 61 | 62 | ``` 63 | 64 | #### Comments 65 | 66 | The function declarations in lines 11 and 17 do not set the visibility of the functions. At least for Solidity 0.4.24 67 | (as specified in the `pragma` statement), this means they will default to being treated as `public`. 68 | This allows anyone to call the `_sendWinings()` function and take the money. 69 | 70 | Instead, the fixed version below restricts the `_sendWinnings()` function visibility to `internal`, 71 | so it can only be activated by the `WithdrawWinnings()` function that enforces a check 72 | whether the sender actually met the presumed conditions to receive the money. 73 | 74 | ### visibility_not_set_fixed.sol 75 | 76 | ```solidity 77 | /* 78 | * @source: https://github.com/sigp/solidity-security-blog#visibility 79 | * @author: SigmaPrime 80 | * Modified by Gerhard Wagner 81 | */ 82 | 83 | pragma solidity ^0.4.24; 84 | 85 | contract HashForEther { 86 | 87 | function withdrawWinnings() public { 88 | // Winner if the last 8 hex characters of the address are 0. 89 | require(uint32(msg.sender) == 0); 90 | _sendWinnings(); 91 | } 92 | 93 | function _sendWinnings() internal{ 94 | msg.sender.transfer(this.balance); 95 | } 96 | } 97 | 98 | ``` 99 | -------------------------------------------------------------------------------- /entries/docs/SWC-102.md: -------------------------------------------------------------------------------- 1 | # Please note, this content is no longer actively maintained. 2 | 3 | The content of the SWC registry has not been thoroughly updated since 2020. It is known to be incomplete and may contain errors as well as crucial omissions. 4 | 5 | For currently maintained guidance on known Smart Contract vulnerabilities written primarily as guidance for security reviewers, please see the 6 | [EEA EthTrust Security Levels specification](https://entethalliance.org/specs/ethtrust-sl). As well as the latest release version, an 7 | [Editor's draft](https://entethalliance.github.io/eta-registry/security-levels-spec.html) is available, 8 | that represents the latest work of the group developing the specification. 9 | 10 | General guidance for developers on what to consider to ensure security, that is currently maintained, is also available through the 11 | [Smart Contract Security Verification Standard (SCSVS)](https://github.com/ComposableSecurity/SCSVS). 12 | 13 | # Title 14 | 15 | Outdated Compiler Version 16 | 17 | ## Relationships 18 | 19 | - [CWE-937: Using Components with Known Vulnerabilities](http://cwe.mitre.org/data/definitions/937.html) 20 | - EEA EthTrust Security Levels: 21 | - [**Level [S]** Improved Compilers](https://entethalliance.org/specs/ethtrust-sl/#sec-1-compile-improvements) 22 | - [**Level [S]** Compiler Security Bugs](https://entethalliance.org/specs/ethtrust-sl/#sec-1-compiler-bugs) 23 | - [**Level [M]** Compiler Bugs and Overriding Requirements](https://entethalliance.org/specs/ethtrust-sl/#sec-level-2-compiler-bugs) 24 | - [**Recommended Practice** Use the Latest Compiler](https://entethalliance.org/specs/ethtrust-sl/#req-R-use-latest-compiler) 25 | 26 | ## Description 27 | 28 | Using an outdated compiler version can be problematic especially if there are publicly disclosed bugs and issues that affect the current compiler version. 29 | 30 | ## Remediation 31 | 32 | It is recommended to use a recent version of the Solidity compiler. 33 | 34 | ## References 35 | 36 | - [Solidity Release Notes](https://github.com/ethereum/solidity/releases) 37 | - [Etherscan Solidity Bug Info](https://etherscan.io/solcbuginfo) 38 | 39 | ## Samples 40 | 41 | ### version_0_4_13.sol 42 | 43 | ```solidity 44 | pragma solidity 0.4.13; 45 | 46 | contract OutdatedCompilerVersion { 47 | uint public x = 1; 48 | } 49 | 50 | ``` 51 | 52 | #### Comments 53 | 54 | As of August 2023 the current version of the compiler is 0.8.21. There are several dozen compiler bugs that have been fixed between that and version 0.4.13, 55 | each of which can lead to data being corrupted, contracts not functioning as expected, or unexpected vulnerabilities in contracts. 56 | There have also been significant improvements in compiler capabilities to protect against errors. 57 | 58 | See also the sections [**Level [S]** Compiler Security Bugs](https://entethalliance.org/specs/ethtrust-sl/#sec-1-compiler-bugs), 59 | [**Level [S]** Improved Compilers](https://entethalliance.org/specs/ethtrust-sl/#sec-1-compile-improvements), and 60 | [**Level [M]** Compiler Bugs and Overriding Requirements](https://entethalliance.org/specs/ethtrust-sl/#sec-level-2-compiler-bugs) 61 | -------------------------------------------------------------------------------- /entries/docs/SWC-103.md: -------------------------------------------------------------------------------- 1 | # Please note, this content is no longer actively maintained. 2 | 3 | The content of the SWC registry has not been thoroughly updated since 2020. It is known to be incomplete and may contain errors as well as crucial omissions. 4 | 5 | For currently maintained guidance on known Smart Contract vulnerabilities written primarily as guidance for security reviewers, please see the 6 | [EEA EthTrust Security Levels specification](https://entethalliance.org/specs/ethtrust-sl). As well as the latest release version, an 7 | [Editor's draft](https://entethalliance.github.io/eta-registry/security-levels-spec.html) is available, 8 | that represents the latest work of the group developing the specification. 9 | 10 | General guidance for developers on what to consider to ensure security, that is currently maintained, is also available through the 11 | [Smart Contract Security Verification Standard (SCSVS)](https://github.com/ComposableSecurity/SCSVS). 12 | 13 | # Title 14 | 15 | Floating Pragma 16 | 17 | ## Relationships 18 | 19 | - [CWE-664: Improper Control of a Resource Through its Lifetime](https://cwe.mitre.org/data/definitions/664.html) 20 | - EEA EthTrust Security Levels: 21 | - [**Level [S]** Improved Compilers](https://entethalliance.org/specs/ethtrust-sl/#sec-1-compile-improvements) 22 | - [**Level [S]** Compiler Security Bugs](https://entethalliance.org/specs/ethtrust-sl/#sec-1-compiler-bugs) 23 | - [**Level [M]** Compiler Bugs and Overriding Requirements](https://entethalliance.org/specs/ethtrust-sl/#sec-level-2-compiler-bugs) 24 | - [**Recommended Practice** Use the Latest Compiler](https://entethalliance.org/specs/ethtrust-sl/#req-R-use-latest-compiler) 25 | 26 | ## Description 27 | 28 | Contracts should be deployed with the same compiler version and flags that they have been tested with thoroughly. Locking the pragma helps to ensure that contracts do not accidentally get deployed using, for example, an outdated compiler version that might introduce bugs that affect the contract system negatively. 29 | 30 | ## Remediation 31 | 32 | Lock the pragma version and also consider known bugs (https://github.com/ethereum/solidity/releases) for the compiler version that is chosen. 33 | 34 | Pragma statements can be allowed to float when a contract is intended for consumption by other developers, as in the case with contracts in a library or EthPM package. Otherwise, the developer would need to manually update the pragma in order to compile locally. 35 | 36 | ## References 37 | 38 | - [Ethereum Smart Contract Best Practices - Locking Pragmas](https://consensys.github.io/smart-contract-best-practices/development-recommendations/solidity-specific/locking-pragmas/) 39 | 40 | ## Samples 41 | 42 | ### floating_pragma.sol 43 | 44 | ```solidity 45 | pragma solidity ^0.4.0; 46 | 47 | contract PragmaNotLocked { 48 | uint public x = 1; 49 | } 50 | 51 | ``` 52 | 53 | ### floating_pragma_fixed.sol 54 | 55 | ```solidity 56 | pragma solidity 0.4.25; 57 | 58 | contract PragmaFixed { 59 | uint public x = 1; 60 | } 61 | 62 | ``` 63 | 64 | ### no_pragma.sol 65 | 66 | ```solidity 67 | 68 | contract PragmaNotLocked { 69 | uint public x = 1; 70 | } 71 | 72 | ``` 73 | 74 | ### semver_floating_pragma.sol 75 | 76 | ```solidity 77 | pragma solidity >=0.4.0 < 0.6.0; 78 | pragma solidity >=0.4.0<0.6.0; 79 | pragma solidity >=0.4.14 <0.6.0; 80 | pragma solidity >0.4.13 <0.6.0; 81 | pragma solidity 0.4.24 - 0.5.2; 82 | pragma solidity >=0.4.24 <=0.5.3 ~0.4.20; 83 | pragma solidity <0.4.26; 84 | pragma solidity ~0.4.20; 85 | pragma solidity ^0.4.14; 86 | pragma solidity 0.4.*; 87 | pragma solidity 0.*; 88 | pragma solidity *; 89 | pragma solidity 0.4; 90 | pragma solidity 0; 91 | 92 | contract SemVerFloatingPragma { 93 | } 94 | 95 | ``` 96 | 97 | ### semver_floating_pragma_fixed.sol 98 | 99 | ```solidity 100 | pragma solidity 0.4.25; 101 | // or 102 | pragma solidity =0.4.25; 103 | 104 | contract SemVerFloatingPragmaFixed { 105 | } 106 | 107 | ``` 108 | -------------------------------------------------------------------------------- /entries/docs/SWC-104.md: -------------------------------------------------------------------------------- 1 | # Please note, this content is no longer actively maintained. 2 | 3 | The content of the SWC registry has not been thoroughly updated since 2020. It is known to be incomplete and may contain errors as well as crucial omissions. 4 | 5 | For currently maintained guidance on known Smart Contract vulnerabilities written primarily as guidance for security reviewers, please see the 6 | [EEA EthTrust Security Levels specification](https://entethalliance.org/specs/ethtrust-sl). As well as the latest release version, an 7 | [Editor's draft](https://entethalliance.github.io/eta-registry/security-levels-spec.html) is available, 8 | that represents the latest work of the group developing the specification. 9 | 10 | General guidance for developers on what to consider to ensure security, that is currently maintained, is also available through the 11 | [Smart Contract Security Verification Standard (SCSVS)](https://github.com/ComposableSecurity/SCSVS). 12 | 13 | # Title 14 | 15 | Unchecked Call Return Value 16 | 17 | ## Relationships 18 | 19 | - [CWE-252: Unchecked Return Value](https://cwe.mitre.org/data/definitions/252.html) 20 | - EthTrust Security Levels: 21 | - [**[M] Handle External Call Returns**](https://entethalliance.github.io/eta-registry/security-levels-spec.html#req-2-handle-return) 22 | 23 | ## Description 24 | 25 | The return value of a message call is not checked. Execution will resume even if the called contract throws an exception. If the call fails accidentally or an attacker forces the call to fail, this may cause unexpected behaviour in the subsequent program logic. 26 | 27 | ## Remediation 28 | 29 | If you choose to use low-level call methods, make sure to handle the possibility that the call will fail by checking the return value. 30 | 31 | ## References 32 | 33 | - [Ethereum Smart Contract Best Practices - Handle errors in external calls](https://consensys.github.io/smart-contract-best-practices/development-recommendations/general/external-calls/#handle-errors-in-external-calls) 34 | 35 | ## Samples 36 | 37 | ### unchecked_return_value.sol 38 | 39 | ```solidity 40 | pragma solidity 0.4.25; 41 | 42 | contract ReturnValue { 43 | 44 | function callchecked(address callee) public { 45 | require(callee.call()); 46 | } 47 | 48 | function callnotchecked(address callee) public { 49 | callee.call(); 50 | } 51 | } 52 | 53 | ``` 54 | -------------------------------------------------------------------------------- /entries/docs/SWC-105.md: -------------------------------------------------------------------------------- 1 | # Please note, this content is no longer actively maintained. 2 | 3 | The content of the SWC registry has not been thoroughly updated since 2020. It is known to be incomplete and may contain errors as well as crucial omissions. 4 | 5 | For currently maintained guidance on known Smart Contract vulnerabilities written primarily as guidance for security reviewers, please see the 6 | [EEA EthTrust Security Levels specification](https://entethalliance.org/specs/ethtrust-sl). As well as the latest release version, an 7 | [Editor's draft](https://entethalliance.github.io/eta-registry/security-levels-spec.html) is available, 8 | that represents the latest work of the group developing the specification. 9 | 10 | General guidance for developers on what to consider to ensure security, that is currently maintained, is also available through the 11 | [Smart Contract Security Verification Standard (SCSVS)](https://github.com/ComposableSecurity/SCSVS). 12 | 13 | # Title 14 | 15 | Unprotected Ether Withdrawal 16 | 17 | ## Relationships 18 | 19 | - [CWE-284: Improper Access Control](https://cwe.mitre.org/data/definitions/284.html) 20 | - EthTrust Security Levels: 21 | - [**[M] Protect Self-destruction**](https://entethalliance.github.io/eta-registry/security-levels-spec.html#req-2-self-destruct) 22 | - [**[Q] Enforce Least Privilege**](https://entethalliance.github.io/eta-registry/security-levels-spec.html#req-3-access-control) 23 | 24 | ## Description 25 | 26 | Due to missing or insufficient access controls, malicious parties can withdraw some or all Ether from the contract account. 27 | 28 | This bug is sometimes caused by unintentionally exposing initialization functions. By wrongly naming a function intended to be a constructor, the constructor code ends up in the runtime byte code and can be called by anyone to re-initialize the contract. 29 | 30 | ## Remediation 31 | 32 | Implement controls so withdrawals can only be triggered by authorized parties or according to the specs of the smart contract system. 33 | 34 | ## References 35 | 36 | - [Rubixi smart contract](https://etherscan.io/address/0xe82719202e5965Cf5D9B6673B7503a3b92DE20be#code) 37 | 38 | ## Samples 39 | 40 | ### tokensalechallenge.sol 41 | 42 | ```solidity 43 | /* 44 | * @source: https://capturetheether.com/challenges/math/token-sale/ 45 | * @author: Steve Marx 46 | */ 47 | 48 | pragma solidity ^0.4.21; 49 | 50 | contract TokenSaleChallenge { 51 | mapping(address => uint256) public balanceOf; 52 | uint256 constant PRICE_PER_TOKEN = 1 ether; 53 | 54 | function TokenSaleChallenge(address _player) public payable { 55 | require(msg.value == 1 ether); 56 | } 57 | 58 | function isComplete() public view returns (bool) { 59 | return address(this).balance < 1 ether; 60 | } 61 | 62 | function buy(uint256 numTokens) public payable { 63 | require(msg.value == numTokens * PRICE_PER_TOKEN); 64 | 65 | balanceOf[msg.sender] += numTokens; 66 | } 67 | 68 | function sell(uint256 numTokens) public { 69 | require(balanceOf[msg.sender] >= numTokens); 70 | 71 | balanceOf[msg.sender] -= numTokens; 72 | msg.sender.transfer(numTokens * PRICE_PER_TOKEN); 73 | } 74 | } 75 | ``` 76 | 77 | ### rubixi.sol 78 | 79 | ```solidity 80 | pragma solidity ^0.4.22; 81 | 82 | contract Rubixi { 83 | 84 | //Declare variables for storage critical to contract 85 | uint private balance = 0; 86 | uint private collectedFees = 0; 87 | uint private feePercent = 10; 88 | uint private pyramidMultiplier = 300; 89 | uint private payoutOrder = 0; 90 | 91 | address private creator; 92 | 93 | //Sets creator 94 | function DynamicPyramid() { 95 | creator = msg.sender; 96 | } 97 | 98 | modifier onlyowner { 99 | if (msg.sender == creator) _; 100 | } 101 | 102 | struct Participant { 103 | address etherAddress; 104 | uint payout; 105 | } 106 | 107 | Participant[] private participants; 108 | 109 | //Fallback function 110 | function() { 111 | init(); 112 | } 113 | 114 | //init function run on fallback 115 | function init() private { 116 | //Ensures only tx with value of 1 ether or greater are processed and added to pyramid 117 | if (msg.value < 1 ether) { 118 | collectedFees += msg.value; 119 | return; 120 | } 121 | 122 | uint _fee = feePercent; 123 | //50% fee rebate on any ether value of 50 or greater 124 | if (msg.value >= 50 ether) _fee /= 2; 125 | 126 | addPayout(_fee); 127 | } 128 | 129 | //Function called for valid tx to the contract 130 | function addPayout(uint _fee) private { 131 | //Adds new address to participant array 132 | participants.push(Participant(msg.sender, (msg.value * pyramidMultiplier) / 100)); 133 | 134 | //These statements ensure a quicker payout system to later pyramid entrants, so the pyramid has a longer lifespan 135 | if (participants.length == 10) pyramidMultiplier = 200; 136 | else if (participants.length == 25) pyramidMultiplier = 150; 137 | 138 | // collect fees and update contract balance 139 | balance += (msg.value * (100 - _fee)) / 100; 140 | collectedFees += (msg.value * _fee) / 100; 141 | 142 | //Pays earlier participiants if balance sufficient 143 | while (balance > participants[payoutOrder].payout) { 144 | uint payoutToSend = participants[payoutOrder].payout; 145 | participants[payoutOrder].etherAddress.send(payoutToSend); 146 | 147 | balance -= participants[payoutOrder].payout; 148 | payoutOrder += 1; 149 | } 150 | } 151 | 152 | //Fee functions for creator 153 | function collectAllFees() onlyowner { 154 | if (collectedFees == 0) throw; 155 | 156 | creator.send(collectedFees); 157 | collectedFees = 0; 158 | } 159 | 160 | function collectFeesInEther(uint _amt) onlyowner { 161 | _amt *= 1 ether; 162 | if (_amt > collectedFees) collectAllFees(); 163 | 164 | if (collectedFees == 0) throw; 165 | 166 | creator.send(_amt); 167 | collectedFees -= _amt; 168 | } 169 | 170 | function collectPercentOfFees(uint _pcent) onlyowner { 171 | if (collectedFees == 0 || _pcent > 100) throw; 172 | 173 | uint feesToCollect = collectedFees / 100 * _pcent; 174 | creator.send(feesToCollect); 175 | collectedFees -= feesToCollect; 176 | } 177 | 178 | //Functions for changing variables related to the contract 179 | function changeOwner(address _owner) onlyowner { 180 | creator = _owner; 181 | } 182 | 183 | function changeMultiplier(uint _mult) onlyowner { 184 | if (_mult > 300 || _mult < 120) throw; 185 | 186 | pyramidMultiplier = _mult; 187 | } 188 | 189 | function changeFeePercentage(uint _fee) onlyowner { 190 | if (_fee > 10) throw; 191 | 192 | feePercent = _fee; 193 | } 194 | 195 | //Functions to provide information to end-user using JSON interface or other interfaces 196 | function currentMultiplier() constant returns(uint multiplier, string info) { 197 | multiplier = pyramidMultiplier; 198 | info = 'This multiplier applies to you as soon as transaction is received, may be lowered to hasten payouts or increased if payouts are fast enough. Due to no float or decimals, multiplier is x100 for a fractional multiplier e.g. 250 is actually a 2.5x multiplier. Capped at 3x max and 1.2x min.'; 199 | } 200 | 201 | function currentFeePercentage() constant returns(uint fee, string info) { 202 | fee = feePercent; 203 | info = 'Shown in % form. Fee is halved(50%) for amounts equal or greater than 50 ethers. (Fee may change, but is capped to a maximum of 10%)'; 204 | } 205 | 206 | function currentPyramidBalanceApproximately() constant returns(uint pyramidBalance, string info) { 207 | pyramidBalance = balance / 1 ether; 208 | info = 'All balance values are measured in Ethers, note that due to no decimal placing, these values show up as integers only, within the contract itself you will get the exact decimal value you are supposed to'; 209 | } 210 | 211 | function nextPayoutWhenPyramidBalanceTotalsApproximately() constant returns(uint balancePayout) { 212 | balancePayout = participants[payoutOrder].payout / 1 ether; 213 | } 214 | 215 | function feesSeperateFromBalanceApproximately() constant returns(uint fees) { 216 | fees = collectedFees / 1 ether; 217 | } 218 | 219 | function totalParticipants() constant returns(uint count) { 220 | count = participants.length; 221 | } 222 | 223 | function numberOfParticipantsWaitingForPayout() constant returns(uint count) { 224 | count = participants.length - payoutOrder; 225 | } 226 | 227 | function participantDetails(uint orderInPyramid) constant returns(address Address, uint Payout) { 228 | if (orderInPyramid <= participants.length) { 229 | Address = participants[orderInPyramid].etherAddress; 230 | Payout = participants[orderInPyramid].payout / 1 ether; 231 | } 232 | } 233 | } 234 | 235 | ``` 236 | 237 | ### multiowned_not_vulnerable.sol 238 | 239 | ```solidity 240 | pragma solidity ^0.4.23; 241 | 242 | /** 243 | * @title MultiOwnable 244 | */ 245 | contract MultiOwnable { 246 | address public root; 247 | mapping (address => address) public owners; // owner => parent of owner 248 | 249 | /** 250 | * @dev The Ownable constructor sets the original `owner` of the contract to the sender 251 | * account. 252 | */ 253 | constructor() public { 254 | root = msg.sender; 255 | owners[root] = root; 256 | } 257 | 258 | /** 259 | * @dev Throws if called by any account other than the owner. 260 | */ 261 | modifier onlyOwner() { 262 | require(owners[msg.sender] != 0); 263 | _; 264 | } 265 | 266 | /** 267 | * @dev Adding new owners 268 | * Note that the "onlyOwner" modifier is used here. 269 | */ 270 | function newOwner(address _owner) onlyOwner external returns (bool) { 271 | require(_owner != 0); 272 | owners[_owner] = msg.sender; 273 | return true; 274 | } 275 | 276 | /** 277 | * @dev Deleting owners 278 | */ 279 | function deleteOwner(address _owner) onlyOwner external returns (bool) { 280 | require(owners[_owner] == msg.sender || (owners[_owner] != 0 && msg.sender == root)); 281 | owners[_owner] = 0; 282 | return true; 283 | } 284 | } 285 | 286 | contract TestContract is MultiOwnable { 287 | 288 | function withdrawAll() onlyOwner { 289 | msg.sender.transfer(this.balance); 290 | } 291 | 292 | function() payable { 293 | } 294 | 295 | } 296 | 297 | ``` 298 | 299 | ### multiowned_vulnerable.sol 300 | 301 | ```solidity 302 | pragma solidity ^0.4.23; 303 | 304 | /** 305 | * @title MultiOwnable 306 | */ 307 | contract MultiOwnable { 308 | address public root; 309 | mapping (address => address) public owners; // owner => parent of owner 310 | 311 | /** 312 | * @dev The Ownable constructor sets the original `owner` of the contract to the sender 313 | * account. 314 | */ 315 | constructor() public { 316 | root = msg.sender; 317 | owners[root] = root; 318 | } 319 | 320 | /** 321 | * @dev Throws if called by any account other than the owner. 322 | */ 323 | modifier onlyOwner() { 324 | require(owners[msg.sender] != 0); 325 | _; 326 | } 327 | 328 | /** 329 | * @dev Adding new owners 330 | * Note that the "onlyOwner" modifier is missing here. 331 | */ 332 | function newOwner(address _owner) external returns (bool) { 333 | require(_owner != 0); 334 | owners[_owner] = msg.sender; 335 | return true; 336 | } 337 | 338 | /** 339 | * @dev Deleting owners 340 | */ 341 | function deleteOwner(address _owner) onlyOwner external returns (bool) { 342 | require(owners[_owner] == msg.sender || (owners[_owner] != 0 && msg.sender == root)); 343 | owners[_owner] = 0; 344 | return true; 345 | } 346 | } 347 | 348 | contract TestContract is MultiOwnable { 349 | 350 | function withdrawAll() onlyOwner { 351 | msg.sender.transfer(this.balance); 352 | } 353 | 354 | function() payable { 355 | } 356 | 357 | } 358 | ``` 359 | 360 | ### simple_ether_drain.sol 361 | 362 | ```solidity 363 | pragma solidity ^0.4.22; 364 | 365 | contract SimpleEtherDrain { 366 | 367 | function withdrawAllAnyone() { 368 | msg.sender.transfer(this.balance); 369 | } 370 | 371 | function () public payable { 372 | } 373 | 374 | } 375 | 376 | ``` 377 | 378 | ### wallet_01_ok.sol 379 | 380 | ```solidity 381 | pragma solidity ^0.4.24; 382 | 383 | /* User can add pay in and withdraw Ether. 384 | Nobody can withdraw more Ether than they paid in. 385 | */ 386 | 387 | contract Wallet { 388 | address creator; 389 | 390 | mapping(address => uint256) balances; 391 | 392 | constructor() public { 393 | creator = msg.sender; 394 | } 395 | 396 | function deposit() public payable { 397 | assert(balances[msg.sender] + msg.value > balances[msg.sender]); 398 | balances[msg.sender] += msg.value; 399 | } 400 | 401 | function withdraw(uint256 amount) public { 402 | require(amount <= balances[msg.sender]); 403 | msg.sender.transfer(amount); 404 | balances[msg.sender] -= amount; 405 | } 406 | 407 | function refund() public { 408 | msg.sender.transfer(balances[msg.sender]); 409 | balances[msg.sender] = 0; 410 | } 411 | 412 | // In an emergency the owner can migrate allfunds to a different address. 413 | 414 | function migrateTo(address to) public { 415 | require(creator == msg.sender); 416 | to.transfer(this.balance); 417 | } 418 | 419 | } 420 | 421 | ``` 422 | 423 | ### wallet_02_refund_nosub.sol 424 | 425 | ```solidity 426 | pragma solidity ^0.4.24; 427 | 428 | /* User can add pay in and withdraw Ether. 429 | Unfortunately the developer forgot set the user's balance to 0 when refund() is called. 430 | An attacker can pay in a small amount of Ether and call refund() repeatedly to empty the contract. 431 | */ 432 | 433 | contract Wallet { 434 | address creator; 435 | 436 | mapping(address => uint256) balances; 437 | 438 | constructor() public { 439 | creator = msg.sender; 440 | } 441 | 442 | function deposit() public payable { 443 | assert(balances[msg.sender] + msg.value > balances[msg.sender]); 444 | balances[msg.sender] += msg.value; 445 | } 446 | 447 | function withdraw(uint256 amount) public { 448 | require(amount <= balances[msg.sender]); 449 | msg.sender.transfer(amount); 450 | balances[msg.sender] -= amount; 451 | } 452 | 453 | function refund() public { 454 | msg.sender.transfer(balances[msg.sender]); 455 | } 456 | 457 | // In an emergency the owner can migrate allfunds to a different address. 458 | 459 | function migrateTo(address to) public { 460 | require(creator == msg.sender); 461 | to.transfer(this.balance); 462 | } 463 | 464 | } 465 | 466 | ``` 467 | 468 | ### wallet_03_wrong_constructor.sol 469 | 470 | ```solidity 471 | pragma solidity ^0.4.24; 472 | 473 | /* User can add pay in and withdraw Ether. 474 | The constructor is wrongly named, so anyone can become 'creator' and withdraw all funds. 475 | */ 476 | 477 | contract Wallet { 478 | address creator; 479 | 480 | mapping(address => uint256) balances; 481 | 482 | function initWallet() public { 483 | creator = msg.sender; 484 | } 485 | 486 | function deposit() public payable { 487 | assert(balances[msg.sender] + msg.value > balances[msg.sender]); 488 | balances[msg.sender] += msg.value; 489 | } 490 | 491 | function withdraw(uint256 amount) public { 492 | require(amount <= balances[msg.sender]); 493 | msg.sender.transfer(amount); 494 | balances[msg.sender] -= amount; 495 | } 496 | 497 | // In an emergency the owner can migrate allfunds to a different address. 498 | 499 | function migrateTo(address to) public { 500 | require(creator == msg.sender); 501 | to.transfer(this.balance); 502 | } 503 | 504 | } 505 | 506 | ``` 507 | 508 | ### wallet_04_confused_sign.sol 509 | 510 | ```solidity 511 | pragma solidity ^0.4.24; 512 | 513 | /* User can add pay in and withdraw Ether. 514 | Unfortunately, the developer was drunk and used the wrong comparison operator in "withdraw()" 515 | Anybody can withdraw arbitrary amounts of Ether :() 516 | */ 517 | 518 | contract Wallet { 519 | address creator; 520 | 521 | mapping(address => uint256) balances; 522 | 523 | constructor() public { 524 | creator = msg.sender; 525 | } 526 | 527 | function deposit() public payable { 528 | assert(balances[msg.sender] + msg.value > balances[msg.sender]); 529 | balances[msg.sender] += msg.value; 530 | } 531 | 532 | function withdraw(uint256 amount) public { 533 | require(amount >= balances[msg.sender]); 534 | msg.sender.transfer(amount); 535 | balances[msg.sender] -= amount; 536 | } 537 | 538 | // In an emergency the owner can migrate allfunds to a different address. 539 | 540 | function migrateTo(address to) public { 541 | require(creator == msg.sender); 542 | to.transfer(this.balance); 543 | } 544 | 545 | } 546 | 547 | ``` 548 | -------------------------------------------------------------------------------- /entries/docs/SWC-106.md: -------------------------------------------------------------------------------- 1 | # Please note, this content is no longer actively maintained. 2 | 3 | The content of the SWC registry has not been thoroughly updated since 2020. It is known to be incomplete and may contain errors as well as crucial omissions. 4 | 5 | For currently maintained guidance on known Smart Contract vulnerabilities written primarily as guidance for security reviewers, please see the 6 | [EEA EthTrust Security Levels specification](https://entethalliance.org/specs/ethtrust-sl). As well as the latest release version, an 7 | [Editor's draft](https://entethalliance.github.io/eta-registry/security-levels-spec.html) is available, 8 | that represents the latest work of the group developing the specification. 9 | 10 | General guidance for developers on what to consider to ensure security, that is currently maintained, is also available through the 11 | [Smart Contract Security Verification Standard (SCSVS)](https://github.com/ComposableSecurity/SCSVS). 12 | 13 | # Title 14 | 15 | Unprotected SELFDESTRUCT Instruction 16 | 17 | ## Relationships 18 | 19 | - [CWE-284: Improper Access Control](https://cwe.mitre.org/data/definitions/284.html) 20 | - EthTrust Security Levels: 21 | - [**[M] Protect Self-destruction**](https://entethalliance.github.io/eta-registry/security-levels-spec.html#req-2-self-destruct) 22 | - [**[Q] Enforce Least Privilege**](https://entethalliance.github.io/eta-registry/security-levels-spec.html#req-3-access-control) 23 | 24 | ## Description 25 | 26 | Due to missing or insufficient access controls, malicious parties can self-destruct the contract. 27 | 28 | ## Remediation 29 | 30 | Consider removing the self-destruct functionality unless it is absolutely required. If there is a valid use-case, it is recommended to implement a multisig scheme so that multiple parties must approve the self-destruct action. 31 | 32 | ## References 33 | 34 | - [Parity "I accidentally killed it" bug](https://www.parity.io/a-postmortem-on-the-parity-multi-sig-library-self-destruct/) 35 | 36 | ## Samples 37 | 38 | ### WalletLibrary.sol 39 | 40 | ```solidity 41 | //sol Wallet 42 | // Multi-sig, daily-limited account proxy/wallet. 43 | // @authors: 44 | // Gav Wood 45 | // inheritable "property" contract that enables methods to be protected by requiring the acquiescence of either a 46 | // single, or, crucially, each of a number of, designated owners. 47 | // usage: 48 | // use modifiers onlyowner (just own owned) or onlymanyowners(hash), whereby the same hash must be provided by 49 | // some number (specified in constructor) of the set of owners (specified in the constructor, modifiable) before the 50 | // interior is executed. 51 | 52 | pragma solidity ^0.4.9; 53 | 54 | contract WalletEvents { 55 | // EVENTS 56 | 57 | // this contract only has six types of events: it can accept a confirmation, in which case 58 | // we record owner and operation (hash) alongside it. 59 | event Confirmation(address owner, bytes32 operation); 60 | event Revoke(address owner, bytes32 operation); 61 | 62 | // some others are in the case of an owner changing. 63 | event OwnerChanged(address oldOwner, address newOwner); 64 | event OwnerAdded(address newOwner); 65 | event OwnerRemoved(address oldOwner); 66 | 67 | // the last one is emitted if the required signatures change 68 | event RequirementChanged(uint newRequirement); 69 | 70 | // Funds has arrived into the wallet (record how much). 71 | event Deposit(address _from, uint value); 72 | // Single transaction going out of the wallet (record who signed for it, how much, and to whom it's going). 73 | event SingleTransact(address owner, uint value, address to, bytes data, address created); 74 | // Multi-sig transaction going out of the wallet (record who signed for it last, the operation hash, how much, and to whom it's going). 75 | event MultiTransact(address owner, bytes32 operation, uint value, address to, bytes data, address created); 76 | // Confirmation still needed for a transaction. 77 | event ConfirmationNeeded(bytes32 operation, address initiator, uint value, address to, bytes data); 78 | } 79 | 80 | contract WalletAbi { 81 | // Revokes a prior confirmation of the given operation 82 | function revoke(bytes32 _operation) external; 83 | 84 | // Replaces an owner `_from` with another `_to`. 85 | function changeOwner(address _from, address _to) external; 86 | 87 | function addOwner(address _owner) external; 88 | 89 | function removeOwner(address _owner) external; 90 | 91 | function changeRequirement(uint _newRequired) external; 92 | 93 | function isOwner(address _addr) constant returns (bool); 94 | 95 | function hasConfirmed(bytes32 _operation, address _owner) external constant returns (bool); 96 | 97 | // (re)sets the daily limit. needs many of the owners to confirm. doesn't alter the amount already spent today. 98 | function setDailyLimit(uint _newLimit) external; 99 | 100 | function execute(address _to, uint _value, bytes _data) external returns (bytes32 o_hash); 101 | function confirm(bytes32 _h) returns (bool o_success); 102 | } 103 | 104 | contract WalletLibrary is WalletEvents { 105 | // TYPES 106 | 107 | // struct for the status of a pending operation. 108 | struct PendingState { 109 | uint yetNeeded; 110 | uint ownersDone; 111 | uint index; 112 | } 113 | 114 | // Transaction structure to remember details of transaction lest it need be saved for a later call. 115 | struct Transaction { 116 | address to; 117 | uint value; 118 | bytes data; 119 | } 120 | 121 | // MODIFIERS 122 | 123 | // simple single-sig function modifier. 124 | modifier onlyowner { 125 | if (isOwner(msg.sender)) 126 | _; 127 | } 128 | // multi-sig function modifier: the operation must have an intrinsic hash in order 129 | // that later attempts can be realised as the same underlying operation and 130 | // thus count as confirmations. 131 | modifier onlymanyowners(bytes32 _operation) { 132 | if (confirmAndCheck(_operation)) 133 | _; 134 | } 135 | 136 | // METHODS 137 | 138 | // gets called when no other function matches 139 | function() payable { 140 | // just being sent some cash? 141 | if (msg.value > 0) 142 | Deposit(msg.sender, msg.value); 143 | } 144 | 145 | // constructor is given number of sigs required to do protected "onlymanyowners" transactions 146 | // as well as the selection of addresses capable of confirming them. 147 | function initMultiowned(address[] _owners, uint _required) only_uninitialized { 148 | m_numOwners = _owners.length + 1; 149 | m_owners[1] = uint(msg.sender); 150 | m_ownerIndex[uint(msg.sender)] = 1; 151 | for (uint i = 0; i < _owners.length; ++i) 152 | { 153 | m_owners[2 + i] = uint(_owners[i]); 154 | m_ownerIndex[uint(_owners[i])] = 2 + i; 155 | } 156 | m_required = _required; 157 | } 158 | 159 | // Revokes a prior confirmation of the given operation 160 | function revoke(bytes32 _operation) external { 161 | uint ownerIndex = m_ownerIndex[uint(msg.sender)]; 162 | // make sure they're an owner 163 | if (ownerIndex == 0) return; 164 | uint ownerIndexBit = 2**ownerIndex; 165 | var pending = m_pending[_operation]; 166 | if (pending.ownersDone & ownerIndexBit > 0) { 167 | pending.yetNeeded++; 168 | pending.ownersDone -= ownerIndexBit; 169 | Revoke(msg.sender, _operation); 170 | } 171 | } 172 | 173 | // Replaces an owner `_from` with another `_to`. 174 | function changeOwner(address _from, address _to) onlymanyowners(sha3(msg.data)) external { 175 | if (isOwner(_to)) return; 176 | uint ownerIndex = m_ownerIndex[uint(_from)]; 177 | if (ownerIndex == 0) return; 178 | 179 | clearPending(); 180 | m_owners[ownerIndex] = uint(_to); 181 | m_ownerIndex[uint(_from)] = 0; 182 | m_ownerIndex[uint(_to)] = ownerIndex; 183 | OwnerChanged(_from, _to); 184 | } 185 | 186 | function addOwner(address _owner) onlymanyowners(sha3(msg.data)) external { 187 | if (isOwner(_owner)) return; 188 | 189 | clearPending(); 190 | if (m_numOwners >= c_maxOwners) 191 | reorganizeOwners(); 192 | if (m_numOwners >= c_maxOwners) 193 | return; 194 | m_numOwners++; 195 | m_owners[m_numOwners] = uint(_owner); 196 | m_ownerIndex[uint(_owner)] = m_numOwners; 197 | OwnerAdded(_owner); 198 | } 199 | 200 | function removeOwner(address _owner) onlymanyowners(sha3(msg.data)) external { 201 | uint ownerIndex = m_ownerIndex[uint(_owner)]; 202 | if (ownerIndex == 0) return; 203 | if (m_required > m_numOwners - 1) return; 204 | 205 | m_owners[ownerIndex] = 0; 206 | m_ownerIndex[uint(_owner)] = 0; 207 | clearPending(); 208 | reorganizeOwners(); //make sure m_numOwner is equal to the number of owners and always points to the optimal free slot 209 | OwnerRemoved(_owner); 210 | } 211 | 212 | function changeRequirement(uint _newRequired) onlymanyowners(sha3(msg.data)) external { 213 | if (_newRequired > m_numOwners) return; 214 | m_required = _newRequired; 215 | clearPending(); 216 | RequirementChanged(_newRequired); 217 | } 218 | 219 | // Gets an owner by 0-indexed position (using numOwners as the count) 220 | function getOwner(uint ownerIndex) external constant returns (address) { 221 | return address(m_owners[ownerIndex + 1]); 222 | } 223 | 224 | function isOwner(address _addr) constant returns (bool) { 225 | return m_ownerIndex[uint(_addr)] > 0; 226 | } 227 | 228 | function hasConfirmed(bytes32 _operation, address _owner) external constant returns (bool) { 229 | var pending = m_pending[_operation]; 230 | uint ownerIndex = m_ownerIndex[uint(_owner)]; 231 | 232 | // make sure they're an owner 233 | if (ownerIndex == 0) return false; 234 | 235 | // determine the bit to set for this owner. 236 | uint ownerIndexBit = 2**ownerIndex; 237 | return !(pending.ownersDone & ownerIndexBit == 0); 238 | } 239 | 240 | // constructor - stores initial daily limit and records the present day's index. 241 | function initDaylimit(uint _limit) only_uninitialized { 242 | m_dailyLimit = _limit; 243 | m_lastDay = today(); 244 | } 245 | // (re)sets the daily limit. needs many of the owners to confirm. doesn't alter the amount already spent today. 246 | function setDailyLimit(uint _newLimit) onlymanyowners(sha3(msg.data)) external { 247 | m_dailyLimit = _newLimit; 248 | } 249 | // resets the amount already spent today. needs many of the owners to confirm. 250 | function resetSpentToday() onlymanyowners(sha3(msg.data)) external { 251 | m_spentToday = 0; 252 | } 253 | 254 | // throw unless the contract is not yet initialized. 255 | modifier only_uninitialized { if (m_numOwners > 0) throw; _; } 256 | 257 | // constructor - just pass on the owner array to the multiowned and 258 | // the limit to daylimit 259 | function initWallet(address[] _owners, uint _required, uint _daylimit) only_uninitialized { 260 | initDaylimit(_daylimit); 261 | initMultiowned(_owners, _required); 262 | } 263 | 264 | // kills the contract sending everything to `_to`. 265 | function kill(address _to) onlymanyowners(sha3(msg.data)) external { 266 | suicide(_to); 267 | } 268 | 269 | // Outside-visible transact entry point. Executes transaction immediately if below daily spend limit. 270 | // If not, goes into multisig process. We provide a hash on return to allow the sender to provide 271 | // shortcuts for the other confirmations (allowing them to avoid replicating the _to, _value 272 | // and _data arguments). They still get the option of using them if they want, anyways. 273 | function execute(address _to, uint _value, bytes _data) external onlyowner returns (bytes32 o_hash) { 274 | // first, take the opportunity to check that we're under the daily limit. 275 | if ((_data.length == 0 && underLimit(_value)) || m_required == 1) { 276 | // yes - just execute the call. 277 | address created; 278 | if (_to == 0) { 279 | created = create(_value, _data); 280 | } else { 281 | if (!_to.call.value(_value)(_data)) 282 | throw; 283 | } 284 | SingleTransact(msg.sender, _value, _to, _data, created); 285 | } else { 286 | // determine our operation hash. 287 | o_hash = sha3(msg.data, block.number); 288 | // store if it's new 289 | if (m_txs[o_hash].to == 0 && m_txs[o_hash].value == 0 && m_txs[o_hash].data.length == 0) { 290 | m_txs[o_hash].to = _to; 291 | m_txs[o_hash].value = _value; 292 | m_txs[o_hash].data = _data; 293 | } 294 | if (!confirm(o_hash)) { 295 | ConfirmationNeeded(o_hash, msg.sender, _value, _to, _data); 296 | } 297 | } 298 | } 299 | 300 | function create(uint _value, bytes _code) internal returns (address o_addr) { 301 | /* 302 | assembly { 303 | o_addr := create(_value, add(_code, 0x20), mload(_code)) 304 | jumpi(invalidJumpLabel, iszero(extcodesize(o_addr))) 305 | } 306 | */ 307 | } 308 | 309 | // confirm a transaction through just the hash. we use the previous transactions map, m_txs, in order 310 | // to determine the body of the transaction from the hash provided. 311 | function confirm(bytes32 _h) onlymanyowners(_h) returns (bool o_success) { 312 | if (m_txs[_h].to != 0 || m_txs[_h].value != 0 || m_txs[_h].data.length != 0) { 313 | address created; 314 | if (m_txs[_h].to == 0) { 315 | created = create(m_txs[_h].value, m_txs[_h].data); 316 | } else { 317 | if (!m_txs[_h].to.call.value(m_txs[_h].value)(m_txs[_h].data)) 318 | throw; 319 | } 320 | 321 | MultiTransact(msg.sender, _h, m_txs[_h].value, m_txs[_h].to, m_txs[_h].data, created); 322 | delete m_txs[_h]; 323 | return true; 324 | } 325 | } 326 | 327 | // INTERNAL METHODS 328 | 329 | function confirmAndCheck(bytes32 _operation) internal returns (bool) { 330 | // determine what index the present sender is: 331 | uint ownerIndex = m_ownerIndex[uint(msg.sender)]; 332 | // make sure they're an owner 333 | if (ownerIndex == 0) return; 334 | 335 | var pending = m_pending[_operation]; 336 | // if we're not yet working on this operation, switch over and reset the confirmation status. 337 | if (pending.yetNeeded == 0) { 338 | // reset count of confirmations needed. 339 | pending.yetNeeded = m_required; 340 | // reset which owners have confirmed (none) - set our bitmap to 0. 341 | pending.ownersDone = 0; 342 | pending.index = m_pendingIndex.length++; 343 | m_pendingIndex[pending.index] = _operation; 344 | } 345 | // determine the bit to set for this owner. 346 | uint ownerIndexBit = 2**ownerIndex; 347 | // make sure we (the message sender) haven't confirmed this operation previously. 348 | if (pending.ownersDone & ownerIndexBit == 0) { 349 | Confirmation(msg.sender, _operation); 350 | // ok - check if count is enough to go ahead. 351 | if (pending.yetNeeded <= 1) { 352 | // enough confirmations: reset and run interior. 353 | delete m_pendingIndex[m_pending[_operation].index]; 354 | delete m_pending[_operation]; 355 | return true; 356 | } 357 | else 358 | { 359 | // not enough: record that this owner in particular confirmed. 360 | pending.yetNeeded--; 361 | pending.ownersDone |= ownerIndexBit; 362 | } 363 | } 364 | } 365 | 366 | function reorganizeOwners() private { 367 | uint free = 1; 368 | while (free < m_numOwners) 369 | { 370 | while (free < m_numOwners && m_owners[free] != 0) free++; 371 | while (m_numOwners > 1 && m_owners[m_numOwners] == 0) m_numOwners--; 372 | if (free < m_numOwners && m_owners[m_numOwners] != 0 && m_owners[free] == 0) 373 | { 374 | m_owners[free] = m_owners[m_numOwners]; 375 | m_ownerIndex[m_owners[free]] = free; 376 | m_owners[m_numOwners] = 0; 377 | } 378 | } 379 | } 380 | 381 | // checks to see if there is at least `_value` left from the daily limit today. if there is, subtracts it and 382 | // returns true. otherwise just returns false. 383 | function underLimit(uint _value) internal onlyowner returns (bool) { 384 | // reset the spend limit if we're on a different day to last time. 385 | if (today() > m_lastDay) { 386 | m_spentToday = 0; 387 | m_lastDay = today(); 388 | } 389 | // check to see if there's enough left - if so, subtract and return true. 390 | // overflow protection // dailyLimit check 391 | if (m_spentToday + _value >= m_spentToday && m_spentToday + _value <= m_dailyLimit) { 392 | m_spentToday += _value; 393 | return true; 394 | } 395 | return false; 396 | } 397 | 398 | // determines today's index. 399 | function today() private constant returns (uint) { return now / 1 days; } 400 | 401 | function clearPending() internal { 402 | uint length = m_pendingIndex.length; 403 | 404 | for (uint i = 0; i < length; ++i) { 405 | delete m_txs[m_pendingIndex[i]]; 406 | 407 | if (m_pendingIndex[i] != 0) 408 | delete m_pending[m_pendingIndex[i]]; 409 | } 410 | 411 | delete m_pendingIndex; 412 | } 413 | 414 | // FIELDS 415 | address constant _walletLibrary = 0xcafecafecafecafecafecafecafecafecafecafe; 416 | 417 | // the number of owners that must confirm the same operation before it is run. 418 | uint public m_required; 419 | // pointer used to find a free slot in m_owners 420 | uint public m_numOwners; 421 | 422 | uint public m_dailyLimit; 423 | uint public m_spentToday; 424 | uint public m_lastDay; 425 | 426 | // list of owners 427 | uint[256] m_owners; 428 | 429 | uint constant c_maxOwners = 250; 430 | // index on the list of owners to allow reverse lookup 431 | mapping(uint => uint) m_ownerIndex; 432 | // the ongoing operations. 433 | mapping(bytes32 => PendingState) m_pending; 434 | bytes32[] m_pendingIndex; 435 | 436 | // pending transactions we have at present. 437 | mapping (bytes32 => Transaction) m_txs; 438 | } 439 | 440 | ``` 441 | 442 | ### simple_suicide.sol 443 | 444 | ```solidity 445 | pragma solidity ^0.4.22; 446 | 447 | contract SimpleSuicide { 448 | 449 | function sudicideAnyone() { 450 | selfdestruct(msg.sender); 451 | } 452 | 453 | } 454 | 455 | ``` 456 | 457 | ### suicide_multitx_feasible.sol 458 | 459 | ```solidity 460 | pragma solidity ^0.4.23; 461 | 462 | contract SuicideMultiTxFeasible { 463 | uint256 private initialized = 0; 464 | uint256 public count = 1; 465 | 466 | function init() public { 467 | initialized = 1; 468 | } 469 | 470 | function run(uint256 input) { 471 | if (initialized == 0) { 472 | return; 473 | } 474 | 475 | selfdestruct(msg.sender); 476 | } 477 | } 478 | 479 | ``` 480 | 481 | ### suicide_multitx_infeasible.sol 482 | 483 | ```solidity 484 | pragma solidity ^0.4.23; 485 | 486 | contract SuicideMultiTxFeasible { 487 | uint256 private initialized = 0; 488 | uint256 public count = 1; 489 | 490 | function init() public { 491 | initialized = 1; 492 | } 493 | 494 | function run(uint256 input) { 495 | if (initialized != 2) { 496 | return; 497 | } 498 | 499 | selfdestruct(msg.sender); 500 | } 501 | } 502 | 503 | ``` 504 | -------------------------------------------------------------------------------- /entries/docs/SWC-107.md: -------------------------------------------------------------------------------- 1 | # Please note, this content is no longer actively maintained. 2 | 3 | The content of the SWC registry has not been thoroughly updated since 2020. It is known to be incomplete and may contain errors as well as crucial omissions. 4 | 5 | For currently maintained guidance on known Smart Contract vulnerabilities written primarily as guidance for security reviewers, please see the 6 | [EEA EthTrust Security Levels specification](https://entethalliance.org/specs/ethtrust-sl). As well as the latest release version, an 7 | [Editor's draft](https://entethalliance.github.io/eta-registry/security-levels-spec.html) is available, 8 | that represents the latest work of the group developing the specification. 9 | 10 | General guidance for developers on what to consider to ensure security, that is currently maintained, is also available through the 11 | [Smart Contract Security Verification Standard (SCSVS)](https://github.com/ComposableSecurity/SCSVS). 12 | 13 | # Title 14 | 15 | Reentrancy 16 | 17 | ## Relationships 18 | 19 | [CWE-841: Improper Enforcement of Behavioral Workflow](https://cwe.mitre.org/data/definitions/841.html) 20 | 21 | ## Description 22 | 23 | One of the major dangers of calling external contracts is that they can take over the control flow. In the reentrancy attack (a.k.a. recursive call attack), a malicious contract calls back into the calling contract before the first invocation of the function is finished. This may cause the different invocations of the function to interact in undesirable ways. 24 | 25 | ## Remediation 26 | 27 | The best practices to avoid Reentrancy weaknesses are: 28 | 29 | - Make sure all internal state changes are performed before the call is executed. This is known as the [Checks-Effects-Interactions pattern](https://solidity.readthedocs.io/en/latest/security-considerations.html#use-the-checks-effects-interactions-pattern) 30 | - Use a reentrancy lock (ie. [OpenZeppelin's ReentrancyGuard](https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/security/ReentrancyGuard.sol)). 31 | 32 | ## References 33 | 34 | - [Ethereum Smart Contract Best Practices - Reentrancy](https://consensys.github.io/smart-contract-best-practices/attacks/reentrancy/) 35 | 36 | ## Samples 37 | 38 | ### modifier_reentrancy.sol 39 | 40 | ```solidity 41 | pragma solidity ^0.5.0; 42 | 43 | contract ModifierEntrancy { 44 | 45 | mapping (address => uint) public tokenBalance; 46 | string constant name = "Nu Token"; 47 | Bank bank; 48 | 49 | constructor() public{ 50 | bank = new Bank(); 51 | } 52 | 53 | //If a contract has a zero balance and supports the token give them some token 54 | function airDrop() hasNoBalance supportsToken public{ 55 | tokenBalance[msg.sender] += 20; 56 | } 57 | 58 | //Checks that the contract responds the way we want 59 | modifier supportsToken() { 60 | require(keccak256(abi.encodePacked("Nu Token")) == bank.supportsToken()); 61 | _; 62 | } 63 | 64 | //Checks that the caller has a zero balance 65 | modifier hasNoBalance { 66 | require(tokenBalance[msg.sender] == 0); 67 | _; 68 | } 69 | } 70 | 71 | contract Bank{ 72 | 73 | function supportsToken() external returns(bytes32) { 74 | return keccak256(abi.encodePacked("Nu Token")); 75 | } 76 | 77 | } 78 | 79 | ``` 80 | 81 | ### modifier_reentrancy_fixed.sol 82 | 83 | ```solidity 84 | pragma solidity ^0.5.0; 85 | 86 | contract ModifierEntrancy { 87 | mapping (address => uint) public tokenBalance; 88 | string constant name = "Nu Token"; 89 | Bank bank; 90 | constructor() public{ 91 | bank = new Bank(); 92 | } 93 | 94 | //If a contract has a zero balance and supports the token give them some token 95 | function airDrop() supportsToken hasNoBalance public{ // In the fixed version supportsToken comes before hasNoBalance 96 | tokenBalance[msg.sender] += 20; 97 | } 98 | 99 | //Checks that the contract responds the way we want 100 | modifier supportsToken() { 101 | require(keccak256(abi.encodePacked("Nu Token")) == bank.supportsToken()); 102 | _; 103 | } 104 | //Checks that the caller has a zero balance 105 | modifier hasNoBalance { 106 | require(tokenBalance[msg.sender] == 0); 107 | _; 108 | } 109 | } 110 | 111 | contract Bank{ 112 | 113 | function supportsToken() external returns(bytes32){ 114 | return(keccak256(abi.encodePacked("Nu Token"))); 115 | } 116 | } 117 | 118 | ``` 119 | 120 | ### simple_dao.sol 121 | 122 | ```solidity 123 | /* 124 | * @source: http://blockchain.unica.it/projects/ethereum-survey/attacks.html#simpledao 125 | * @author: Atzei N., Bartoletti M., Cimoli T 126 | * Modified by Josselin Feist 127 | */ 128 | pragma solidity 0.4.24; 129 | 130 | contract SimpleDAO { 131 | mapping (address => uint) public credit; 132 | 133 | function donate(address to) payable public{ 134 | credit[to] += msg.value; 135 | } 136 | 137 | function withdraw(uint amount) public{ 138 | if (credit[msg.sender]>= amount) { 139 | require(msg.sender.call.value(amount)()); 140 | credit[msg.sender]-=amount; 141 | } 142 | } 143 | 144 | function queryCredit(address to) view public returns(uint){ 145 | return credit[to]; 146 | } 147 | } 148 | 149 | ``` 150 | 151 | ### simple_dao_fixed.sol 152 | 153 | ```solidity 154 | /* 155 | * @source: http://blockchain.unica.it/projects/ethereum-survey/attacks.html#simpledao 156 | * @author: Atzei N., Bartoletti M., Cimoli T 157 | * Modified by Bernhard Mueller, Josselin Feist 158 | */ 159 | pragma solidity 0.4.24; 160 | 161 | contract SimpleDAO { 162 | mapping (address => uint) public credit; 163 | 164 | function donate(address to) payable public{ 165 | credit[to] += msg.value; 166 | } 167 | 168 | function withdraw(uint amount) public { 169 | if (credit[msg.sender]>= amount) { 170 | credit[msg.sender]-=amount; 171 | require(msg.sender.call.value(amount)()); 172 | } 173 | } 174 | 175 | function queryCredit(address to) view public returns (uint){ 176 | return credit[to]; 177 | } 178 | } 179 | 180 | ``` 181 | -------------------------------------------------------------------------------- /entries/docs/SWC-108.md: -------------------------------------------------------------------------------- 1 | # Please note, this content is no longer actively maintained. 2 | 3 | The content of the SWC registry has not been thoroughly updated since 2020. It is known to be incomplete and may contain errors as well as crucial omissions. 4 | 5 | For currently maintained guidance on known Smart Contract vulnerabilities written primarily as guidance for security reviewers, please see the 6 | [EEA EthTrust Security Levels specification](https://entethalliance.org/specs/ethtrust-sl). As well as the latest release version, an 7 | [Editor's draft](https://entethalliance.github.io/eta-registry/security-levels-spec.html) is available, 8 | that represents the latest work of the group developing the specification. 9 | 10 | General guidance for developers on what to consider to ensure security, that is currently maintained, is also available through the 11 | [Smart Contract Security Verification Standard (SCSVS)](https://github.com/ComposableSecurity/SCSVS). 12 | 13 | # Title 14 | 15 | State Variable Default Visibility 16 | 17 | ## Relationships 18 | 19 | [CWE-710: Improper Adherence to Coding Standards](https://cwe.mitre.org/data/definitions/710.html) 20 | 21 | ## Description 22 | 23 | Labeling the visibility explicitly makes it easier to catch incorrect assumptions about who can access the variable. 24 | 25 | ## Remediation 26 | 27 | Variables can be specified as being `public`, `internal` or `private`. Explicitly define visibility for all state variables. 28 | 29 | ## References 30 | 31 | - [Ethereum Smart Contract Best Practices - Visibility](https://consensys.github.io/smart-contract-best-practices/development-recommendations/solidity-specific/visibility/) 32 | 33 | ## Samples 34 | 35 | ### storage.sol 36 | 37 | ```solidity 38 | pragma solidity 0.4.24; 39 | 40 | contract TestStorage { 41 | 42 | uint storeduint1 = 15; 43 | uint constant constuint = 16; 44 | uint32 investmentsDeadlineTimeStamp = uint32(now); 45 | 46 | bytes16 string1 = "test1"; 47 | bytes32 private string2 = "test1236"; 48 | string public string3 = "lets string something"; 49 | 50 | mapping (address => uint) public uints1; 51 | mapping (address => DeviceData) structs1; 52 | 53 | uint[] uintarray; 54 | DeviceData[] deviceDataArray; 55 | 56 | struct DeviceData { 57 | string deviceBrand; 58 | string deviceYear; 59 | string batteryWearLevel; 60 | } 61 | 62 | function testStorage() public { 63 | address address1 = 0xbccc714d56bc0da0fd33d96d2a87b680dd6d0df6; 64 | address address2 = 0xaee905fdd3ed851e48d22059575b9f4245a82b04; 65 | 66 | uints1[address1] = 88; 67 | uints1[address2] = 99; 68 | 69 | DeviceData memory dev1 = DeviceData("deviceBrand", "deviceYear", "wearLevel"); 70 | 71 | structs1[address1] = dev1; 72 | 73 | uintarray.push(8000); 74 | uintarray.push(9000); 75 | 76 | deviceDataArray.push(dev1); 77 | } 78 | } 79 | ``` 80 | -------------------------------------------------------------------------------- /entries/docs/SWC-109.md: -------------------------------------------------------------------------------- 1 | # Please note, this content is no longer actively maintained. 2 | 3 | The content of the SWC registry has not been thoroughly updated since 2020. It is known to be incomplete and may contain errors as well as crucial omissions. 4 | 5 | For currently maintained guidance on known Smart Contract vulnerabilities written primarily as guidance for security reviewers, please see the 6 | [EEA EthTrust Security Levels specification](https://entethalliance.org/specs/ethtrust-sl). As well as the latest release version, an 7 | [Editor's draft](https://entethalliance.github.io/eta-registry/security-levels-spec.html) is available, 8 | that represents the latest work of the group developing the specification. 9 | 10 | General guidance for developers on what to consider to ensure security, that is currently maintained, is also available through the 11 | [Smart Contract Security Verification Standard (SCSVS)](https://github.com/ComposableSecurity/SCSVS). 12 | 13 | # Title 14 | 15 | Uninitialized Storage Pointer 16 | 17 | ## Relationships 18 | 19 | [CWE-824: Access of Uninitialized Pointer](https://cwe.mitre.org/data/definitions/824.html) 20 | 21 | ## Description 22 | 23 | Uninitialized local storage variables can point to unexpected storage locations in the contract, which can lead to intentional or unintentional vulnerabilities. 24 | 25 | ## Remediation 26 | 27 | Check if the contract requires a storage object as in many situations this is actually not the case. If a local variable is sufficient, mark the storage location of the variable explicitly with the `memory` attribute. If a storage variable is needed then initialise it upon declaration and additionally specify the storage location `storage`. 28 | 29 | **Note**: As of compiler version 0.5.0 and higher this issue has been systematically resolved as contracts with uninitialised storage pointers do no longer compile. 30 | 31 | ## References 32 | 33 | - [SigmaPrime - Uninitialised Storage Pointers](https://github.com/sigp/solidity-security-blog#unintialised-storage-pointers-1) 34 | 35 | ## Samples 36 | 37 | ### crypto_roulette.sol 38 | 39 | ```solidity 40 | /* 41 | * @source: https://github.com/thec00n/smart-contract-honeypots/blob/master/CryptoRoulette.sol 42 | */ 43 | pragma solidity ^0.4.19; 44 | 45 | // CryptoRoulette 46 | // 47 | // Guess the number secretly stored in the blockchain and win the whole contract balance! 48 | // A new number is randomly chosen after each try. 49 | // 50 | // To play, call the play() method with the guessed number (1-20). Bet price: 0.1 ether 51 | 52 | contract CryptoRoulette { 53 | 54 | uint256 private secretNumber; 55 | uint256 public lastPlayed; 56 | uint256 public betPrice = 0.1 ether; 57 | address public ownerAddr; 58 | 59 | struct Game { 60 | address player; 61 | uint256 number; 62 | } 63 | Game[] public gamesPlayed; 64 | 65 | function CryptoRoulette() public { 66 | ownerAddr = msg.sender; 67 | shuffle(); 68 | } 69 | 70 | function shuffle() internal { 71 | // randomly set secretNumber with a value between 1 and 20 72 | secretNumber = uint8(sha3(now, block.blockhash(block.number-1))) % 20 + 1; 73 | } 74 | 75 | function play(uint256 number) payable public { 76 | require(msg.value >= betPrice && number <= 10); 77 | 78 | Game game; 79 | game.player = msg.sender; 80 | game.number = number; 81 | gamesPlayed.push(game); 82 | 83 | if (number == secretNumber) { 84 | // win! 85 | msg.sender.transfer(this.balance); 86 | } 87 | 88 | shuffle(); 89 | lastPlayed = now; 90 | } 91 | 92 | function kill() public { 93 | if (msg.sender == ownerAddr && now > lastPlayed + 1 days) { 94 | suicide(msg.sender); 95 | } 96 | } 97 | 98 | function() public payable { } 99 | } 100 | ``` 101 | 102 | ### crypto_roulette_fixed.sol 103 | 104 | ```solidity 105 | /* 106 | * @source: https://github.com/thec00n/smart-contract-honeypots/blob/master/CryptoRoulette.sol 107 | */ 108 | pragma solidity ^0.4.19; 109 | 110 | // CryptoRoulette 111 | // 112 | // Guess the number secretly stored in the blockchain and win the whole contract balance! 113 | // A new number is randomly chosen after each try. 114 | // 115 | // To play, call the play() method with the guessed number (1-20). Bet price: 0.1 ether 116 | 117 | contract CryptoRoulette { 118 | 119 | uint256 private secretNumber; 120 | uint256 public lastPlayed; 121 | uint256 public betPrice = 0.1 ether; 122 | address public ownerAddr; 123 | 124 | struct Game { 125 | address player; 126 | uint256 number; 127 | } 128 | Game[] public gamesPlayed; 129 | 130 | function CryptoRoulette() public { 131 | ownerAddr = msg.sender; 132 | shuffle(); 133 | } 134 | 135 | function shuffle() internal { 136 | // randomly set secretNumber with a value between 1 and 20 137 | secretNumber = uint8(sha3(now, block.blockhash(block.number-1))) % 20 + 1; 138 | } 139 | 140 | function play(uint256 number) payable public { 141 | require(msg.value >= betPrice && number <= 10); 142 | 143 | Game memory game; 144 | game.player = msg.sender; 145 | game.number = number; 146 | gamesPlayed.push(game); 147 | 148 | if (number == secretNumber) { 149 | // win! 150 | msg.sender.transfer(this.balance); 151 | } 152 | 153 | shuffle(); 154 | lastPlayed = now; 155 | } 156 | 157 | function kill() public { 158 | if (msg.sender == ownerAddr && now > lastPlayed + 1 days) { 159 | suicide(msg.sender); 160 | } 161 | } 162 | 163 | function() public payable { } 164 | } 165 | 166 | ``` 167 | -------------------------------------------------------------------------------- /entries/docs/SWC-110.md: -------------------------------------------------------------------------------- 1 | # Please note, this content is no longer actively maintained. 2 | 3 | The content of the SWC registry has not been thoroughly updated since 2020. It is known to be incomplete and may contain errors as well as crucial omissions. 4 | 5 | For currently maintained guidance on known Smart Contract vulnerabilities written primarily as guidance for security reviewers, please see the 6 | [EEA EthTrust Security Levels specification](https://entethalliance.org/specs/ethtrust-sl). As well as the latest release version, an 7 | [Editor's draft](https://entethalliance.github.io/eta-registry/security-levels-spec.html) is available, 8 | that represents the latest work of the group developing the specification. 9 | 10 | General guidance for developers on what to consider to ensure security, that is currently maintained, is also available through the 11 | [Smart Contract Security Verification Standard (SCSVS)](https://github.com/ComposableSecurity/SCSVS). 12 | 13 | # Title 14 | 15 | Assert Violation 16 | 17 | ## Relationships 18 | 19 | [CWE-670: Always-Incorrect Control Flow Implementation](https://cwe.mitre.org/data/definitions/670.html) 20 | 21 | ## Description 22 | 23 | The Solidity `assert()` function is meant to assert invariants. Properly functioning code should *never* reach a failing assert statement. A reachable assertion can mean one of two things: 24 | 25 | 1. A bug exists in the contract that allows it to enter an invalid state; 26 | 1. The `assert` statement is used incorrectly, e.g. to validate inputs. 27 | 28 | ## Remediation 29 | 30 | Consider whether the condition checked in the `assert()` is actually an invariant. If not, replace the `assert()` statement with a `require()` statement. 31 | 32 | If the exception is indeed caused by unexpected behaviour of the code, fix the underlying bug(s) that allow the assertion to be violated. 33 | 34 | ## References 35 | 36 | - [The use of revert(), assert(), and require() in Solidity, and the new REVERT opcode in the EVM](https://media.consensys.net/when-to-use-revert-assert-and-require-in-solidity-61fb2c0e5a57) 37 | 38 | ## Samples 39 | 40 | ### assert_constructor.sol 41 | 42 | ```solidity 43 | /* 44 | * @source: https://github.com/ConsenSys/evm-analyzer-benchmark-suite 45 | * @author: Suhabe Bugrara 46 | */ 47 | 48 | pragma solidity ^0.4.19; 49 | 50 | contract AssertConstructor { 51 | function AssertConstructor() public { 52 | assert(false); 53 | } 54 | } 55 | 56 | ``` 57 | 58 | ### assert_minimal.sol 59 | 60 | ```solidity 61 | /* 62 | * @source: https://github.com/ConsenSys/evm-analyzer-benchmark-suite 63 | * @author: Suhabe Bugrara 64 | */ 65 | 66 | pragma solidity ^0.4.19; 67 | 68 | contract AssertMinimal { 69 | function run() public { 70 | assert(false); 71 | } 72 | } 73 | 74 | ``` 75 | 76 | ### assert_multitx_1.sol 77 | 78 | ```solidity 79 | /* 80 | * @source: https://github.com/ConsenSys/evm-analyzer-benchmark-suite 81 | * @author: Suhabe Bugrara 82 | */ 83 | 84 | pragma solidity ^0.4.19; 85 | 86 | contract AssertMultiTx1 { 87 | uint256 private param; 88 | 89 | function AssertMultiTx1(uint256 _param) public { 90 | require(_param > 0); 91 | param = _param; 92 | } 93 | 94 | function run() { 95 | assert(param > 0); 96 | } 97 | 98 | } 99 | 100 | ``` 101 | 102 | ### assert_multitx_2.sol 103 | 104 | ```solidity 105 | /* 106 | * @source: https://github.com/ConsenSys/evm-analyzer-benchmark-suite 107 | * @author: Suhabe Bugrara 108 | */ 109 | 110 | pragma solidity ^0.4.19; 111 | 112 | contract AssertMultiTx2 { 113 | uint256 private param; 114 | 115 | function AssertMultiTx2(uint256 _param) public { 116 | param = 0; 117 | } 118 | 119 | function run() { 120 | assert(param > 0); 121 | } 122 | 123 | function set(uint256 _param) { 124 | param = _param; 125 | } 126 | 127 | 128 | } 129 | 130 | ``` 131 | 132 | ### constructor_create.sol 133 | 134 | ```solidity 135 | /* 136 | * @source: ChainSecurity 137 | * @author: Anton Permenev 138 | */ 139 | 140 | pragma solidity ^0.4.25; 141 | 142 | contract ConstructorCreate{ 143 | B b = new B(); 144 | 145 | function check(){ 146 | assert(b.foo() == 10); 147 | } 148 | 149 | } 150 | 151 | contract B{ 152 | 153 | function foo() returns(uint){ 154 | return 11; 155 | } 156 | } 157 | 158 | ``` 159 | 160 | ### constructor_create_argument.sol 161 | 162 | ```solidity 163 | /* 164 | * @source: ChainSecurity 165 | * @author: Anton Permenev 166 | */ 167 | pragma solidity ^0.4.22; 168 | 169 | contract ConstructorCreateArgument{ 170 | B b = new B(11); 171 | 172 | function check(){ 173 | assert(b.foo() == 10); 174 | } 175 | 176 | } 177 | 178 | contract B{ 179 | 180 | uint x_; 181 | constructor(uint x){ 182 | x_ = x; 183 | } 184 | 185 | function foo() returns(uint){ 186 | return x_; 187 | } 188 | } 189 | 190 | 191 | ``` 192 | 193 | ### constructor_create_modifiable.sol 194 | 195 | ```solidity 196 | /* 197 | * @source: ChainSecurity 198 | * @author: Anton Permenev 199 | * Assert violation with 2 message calls: 200 | * - B.set_x(X): X != 10 201 | * - ContructorCreateModifiable.check() 202 | */ 203 | 204 | pragma solidity ^0.4.22; 205 | 206 | contract ContructorCreateModifiable{ 207 | B b = new B(10); 208 | 209 | function check(){ 210 | assert(b.foo() == 10); 211 | } 212 | 213 | } 214 | 215 | contract B{ 216 | 217 | uint x_; 218 | constructor(uint x){ 219 | x_ = x; 220 | } 221 | 222 | function foo() returns(uint){ 223 | return x_; 224 | } 225 | 226 | function set_x(uint x){ 227 | x_ = x; 228 | } 229 | } 230 | 231 | 232 | ``` 233 | 234 | ### gas_model.sol 235 | 236 | ```solidity 237 | /* 238 | * @source: ChainSecurity 239 | * @author: Anton Permenev 240 | */ 241 | pragma solidity ^0.4.21; 242 | 243 | contract GasModel{ 244 | uint x = 100; 245 | function check(){ 246 | uint a = gasleft(); 247 | x = x + 1; 248 | uint b = gasleft(); 249 | assert(b > a); 250 | } 251 | } 252 | 253 | ``` 254 | 255 | ### gas_model_fixed.sol 256 | 257 | ```solidity 258 | /* 259 | * @source: ChainSecurity 260 | * @author: Anton Permenev 261 | */ 262 | pragma solidity ^0.4.21; 263 | 264 | contract GasModelFixed{ 265 | uint x = 100; 266 | function check(){ 267 | uint a = gasleft(); 268 | x = x + 1; 269 | uint b = gasleft(); 270 | assert(b < a); 271 | } 272 | } 273 | 274 | 275 | ``` 276 | 277 | ### mapping_perfomance_2.sol 278 | 279 | ```solidity 280 | /* 281 | * @source: ChainSecurity 282 | * @author: Anton Permenev 283 | */ 284 | pragma solidity ^0.4.22; 285 | 286 | contract MappingPerformance2sets{ 287 | 288 | mapping(bytes32=>uint) m0; 289 | mapping(bytes32=>uint) m1; 290 | mapping(bytes32=>uint) m2; 291 | mapping(bytes32=>uint) m3; 292 | mapping(bytes32=>uint) m4; 293 | mapping(bytes32=>uint) m5; 294 | uint b; 295 | 296 | constructor(){ 297 | b = 10; 298 | } 299 | 300 | function set(bytes32 a, uint cond){ 301 | if(cond == 0){ 302 | m0[a] = 5; 303 | }else if(cond == 1){ 304 | m1[a] = 5; 305 | }else if(cond == 2){ 306 | m2[a] = 5; 307 | }else if(cond == 3){ 308 | m3[a] = 5; 309 | }else if(cond == 4){ 310 | m4[a] = 5; 311 | } 312 | } 313 | function check(bytes32 a0, uint cond0, 314 | bytes32 a1, uint cond1, bytes32 a){ 315 | set(a0, cond0); 316 | set(a1, cond1); 317 | assert(m5[a] == 0); 318 | } 319 | } 320 | 321 | ``` 322 | 323 | ### mapping_performance_1.sol 324 | 325 | ```solidity 326 | /* 327 | * @source: ChainSecurity 328 | * @author: Anton Permenev 329 | */ 330 | pragma solidity ^0.4.22; 331 | 332 | contract MappingPerformance1set{ 333 | 334 | mapping(bytes32=>uint) m0; 335 | mapping(bytes32=>uint) m1; 336 | mapping(bytes32=>uint) m2; 337 | mapping(bytes32=>uint) m3; 338 | mapping(bytes32=>uint) m4; 339 | mapping(bytes32=>uint) m5; 340 | uint b; 341 | 342 | constructor(){ 343 | b = 10; 344 | } 345 | 346 | function set(bytes32 a, uint cond){ 347 | if(cond == 0){ 348 | m0[a] = 5; 349 | }else if(cond == 1){ 350 | m1[a] = 5; 351 | }else if(cond == 2){ 352 | m2[a] = 5; 353 | }else if(cond == 3){ 354 | m3[a] = 5; 355 | }else if(cond == 4){ 356 | m4[a] = 5; 357 | } 358 | } 359 | function check(bytes32 a0, uint cond0, bytes32 a){ 360 | set(a0, cond0); 361 | assert(m5[a] == 0); 362 | } 363 | } 364 | 365 | ``` 366 | 367 | ### out-of-bounds-exception.sol 368 | 369 | ```solidity 370 | pragma solidity ^0.5.0; 371 | 372 | contract OutOfBoundsException { 373 | 374 | uint256[] private array; 375 | 376 | function getArrayElement(uint256 idx) public returns (uint256) { 377 | return array[idx]; 378 | } 379 | 380 | } 381 | 382 | ``` 383 | 384 | ### return_memory.sol 385 | 386 | ```solidity 387 | /* 388 | * @source: https://forum.zeppelin.solutions/t/using-automatic-analysis-tools-with-makerdao-contracts/1021/3 389 | * Author: Dan Guido / Trail of Bits 390 | * Slightly modified by Bernhard Mueller 391 | 392 | * An assertion violation is possible in 3 transactions: 393 | * 394 | * etch(addr) 395 | * lookup(slate, addr) 396 | * checkAnInvariant() 397 | 398 | * Whereby slate == Keccak(addr) 399 | * 400 | * Ideally tools should output the correct transaction trace. 401 | */ 402 | 403 | pragma solidity ^0.5.0; 404 | 405 | contract ReturnMemory { 406 | mapping(bytes32=>address) public slates; 407 | bool everMatched = false; 408 | 409 | function etch(address yay) public returns (bytes32 slate) { 410 | bytes32 hash = keccak256(abi.encodePacked(yay)); 411 | slates[hash] = yay; 412 | return hash; 413 | } 414 | 415 | function lookup(bytes32 slate, address nay) public { 416 | if (nay != address(0x0)) { 417 | everMatched = slates[slate] == nay; 418 | } 419 | } 420 | 421 | function checkAnInvariant() public returns (bool) { 422 | assert(!everMatched); 423 | } 424 | } 425 | ``` 426 | 427 | ### runtime_create_user_input.sol 428 | 429 | ```solidity 430 | /* 431 | * @source: ChainSecurity 432 | * @author: Anton Permenev 433 | */ 434 | pragma solidity ^0.4.22; 435 | 436 | contract RuntimeCreateUserInput{ 437 | 438 | function check(uint x){ 439 | B b = new B(x); 440 | assert(b.foo() == 10); 441 | } 442 | 443 | } 444 | 445 | contract B{ 446 | 447 | uint x_; 448 | constructor(uint x){ 449 | x_ = x; 450 | } 451 | 452 | function foo() returns(uint){ 453 | return x_; 454 | } 455 | 456 | } 457 | 458 | 459 | ``` 460 | 461 | ### runtime_user_input_call.sol 462 | 463 | ```solidity 464 | /* 465 | * @source: ChainSecurity 466 | * @author: Anton Permenev 467 | */ 468 | pragma solidity ^0.4.19; 469 | 470 | contract RuntimeUserInputCall{ 471 | 472 | function check(address b){ 473 | assert(B(b).foo() == 10); 474 | } 475 | 476 | } 477 | 478 | contract B{ 479 | function foo() returns(uint); 480 | } 481 | 482 | ``` 483 | 484 | ### sha_of_sha_2_mappings.sol 485 | 486 | ```solidity 487 | /* 488 | * @source: ChainSecurity 489 | * @author: Anton Permenev 490 | */ 491 | pragma solidity ^0.4.22; 492 | 493 | contract ShaOfSha2Mappings{ 494 | 495 | mapping(bytes32=>uint) m; 496 | mapping(bytes32=>uint) n; 497 | 498 | constructor(){ 499 | m[keccak256(abi.encode("AAA", msg.sender))] = 100; 500 | } 501 | 502 | function check(address a){ 503 | assert(n[keccak256(abi.encode("BBB", a))] == 0); 504 | } 505 | 506 | } 507 | 508 | 509 | ``` 510 | 511 | ### sha_of_sha_collision.sol 512 | 513 | ```solidity 514 | /* 515 | * @source: ChainSecurity 516 | * @author: Anton Permenev 517 | * Assert violation with 2 message calls: 518 | * - set(66) 519 | * - check(0x4100000000000000000000000000000000000000000000000000000000000000) 520 | */ 521 | pragma solidity ^0.4.22; 522 | 523 | contract ShaOfShaCollission{ 524 | 525 | mapping(bytes32=>uint) m; 526 | 527 | function set(uint x){ 528 | m[keccak256(abi.encodePacked("A", x))] = 1; 529 | } 530 | function check(uint x){ 531 | assert(m[keccak256(abi.encodePacked(x, "B"))] == 0); 532 | } 533 | 534 | } 535 | 536 | 537 | ``` 538 | 539 | ### sha_of_sha_concrete.sol 540 | 541 | ```solidity 542 | /* 543 | * @source: ChainSecurity 544 | * @author: Anton Permenev 545 | */ 546 | pragma solidity ^0.4.22; 547 | 548 | contract ShaOfShaConcrete{ 549 | 550 | mapping(bytes32=>uint) m; 551 | uint b; 552 | 553 | constructor(){ 554 | b = 1; 555 | } 556 | 557 | function check(uint x){ 558 | assert(m[keccak256(abi.encodePacked(x, "B"))] == 0); 559 | } 560 | 561 | } 562 | 563 | 564 | ``` 565 | 566 | ### token-with-backdoor.sol 567 | 568 | ```solidity 569 | /* 570 | * @source: TrailofBits workshop at TruffleCon 2018 571 | * @author: Josselin Feist (adapted for SWC by Bernhard Mueller) 572 | * Assert violation with 3 message calls: 573 | * - airdrop() 574 | * - backdoor() 575 | * - test_invariants() 576 | */ 577 | pragma solidity ^0.4.22; 578 | 579 | contract Token{ 580 | 581 | mapping(address => uint) public balances; 582 | function airdrop() public{ 583 | balances[msg.sender] = 1000; 584 | } 585 | 586 | function consume() public{ 587 | require(balances[msg.sender]>0); 588 | balances[msg.sender] -= 1; 589 | } 590 | 591 | function backdoor() public{ 592 | balances[msg.sender] += 1; 593 | } 594 | 595 | function test_invariants() { 596 | assert(balances[msg.sender] <= 1000); 597 | } 598 | } 599 | 600 | ``` 601 | 602 | ### two_mapppings.sol 603 | 604 | ```solidity 605 | pragma solidity ^0.4.22; 606 | 607 | contract TwoMappings{ 608 | 609 | mapping(uint=>uint) m; 610 | mapping(uint=>uint) n; 611 | 612 | constructor(){ 613 | m[10] = 100; 614 | } 615 | 616 | function check(uint a){ 617 | assert(n[a] == 0); 618 | } 619 | 620 | } 621 | 622 | 623 | ``` 624 | 625 | ### simpledschief.sol 626 | 627 | ```solidity 628 | /* 629 | * @source: https://forum.zeppelin.solutions/t/using-automatic-analysis-tools-with-makerdao-contracts/1021/3 630 | * Author: Vera Bogdanich Espina / Zeppelin Solutions 631 | * 632 | * A simplified version of the MakerDAO DSChief contract. 633 | * Tools should output the correct transaction trace (see source link). 634 | */ 635 | 636 | contract SimpleDSChief { 637 | mapping(bytes32=>address) public slates; 638 | mapping(address=>bytes32) public votes; 639 | mapping(address=>uint256) public approvals; 640 | mapping(address=>uint256) public deposits; 641 | 642 | function lock(uint wad) public { 643 | deposits[msg.sender] = add(deposits[msg.sender], wad); 644 | addWeight(wad, votes[msg.sender]); 645 | } 646 | 647 | function free(uint wad) public { 648 | deposits[msg.sender] = sub(deposits[msg.sender], wad); 649 | subWeight(wad, votes[msg.sender]); 650 | } 651 | 652 | function voteYays(address yay) public returns (bytes32){ 653 | bytes32 slate = etch(yay); 654 | voteSlate(slate); 655 | 656 | return slate; 657 | } 658 | 659 | function etch(address yay) public returns (bytes32 slate) { 660 | bytes32 hash = keccak256(abi.encodePacked(yay)); 661 | 662 | slates[hash] = yay; 663 | 664 | return hash; 665 | } 666 | 667 | function voteSlate(bytes32 slate) public { 668 | uint weight = deposits[msg.sender]; 669 | subWeight(weight, votes[msg.sender]); 670 | votes[msg.sender] = slate; 671 | addWeight(weight, votes[msg.sender]); 672 | } 673 | 674 | function addWeight(uint weight, bytes32 slate) internal { 675 | address yay = slates[slate]; 676 | approvals[yay] = add(approvals[yay], weight); 677 | } 678 | 679 | function subWeight(uint weight, bytes32 slate) internal { 680 | address yay = slates[slate]; 681 | approvals[yay] = sub(approvals[yay], weight); 682 | } 683 | 684 | function add(uint x, uint y) internal pure returns (uint z) { 685 | require((z = x + y) >= x); 686 | } 687 | 688 | function sub(uint x, uint y) internal pure returns (uint z) { 689 | require((z = x - y) <= x); 690 | } 691 | 692 | function checkAnInvariant() public { 693 | bytes32 senderSlate = votes[msg.sender]; 694 | address option = slates[senderSlate]; 695 | uint256 senderDeposit = deposits[msg.sender]; 696 | 697 | assert(approvals[option] >= senderDeposit); 698 | } 699 | } 700 | ``` 701 | -------------------------------------------------------------------------------- /entries/docs/SWC-111.md: -------------------------------------------------------------------------------- 1 | # Please note, this content is no longer actively maintained. 2 | 3 | The content of the SWC registry has not been thoroughly updated since 2020. It is known to be incomplete and may contain errors as well as crucial omissions. 4 | 5 | For currently maintained guidance on known Smart Contract vulnerabilities written primarily as guidance for security reviewers, please see the 6 | [EEA EthTrust Security Levels specification](https://entethalliance.org/specs/ethtrust-sl). As well as the latest release version, an 7 | [Editor's draft](https://entethalliance.github.io/eta-registry/security-levels-spec.html) is available, 8 | that represents the latest work of the group developing the specification. 9 | 10 | General guidance for developers on what to consider to ensure security, that is currently maintained, is also available through the 11 | [Smart Contract Security Verification Standard (SCSVS)](https://github.com/ComposableSecurity/SCSVS). 12 | 13 | # Title 14 | 15 | Use of Deprecated Solidity Functions 16 | 17 | ## Relationships 18 | 19 | [CWE-477: Use of Obsolete Function](https://cwe.mitre.org/data/definitions/477.html) 20 | 21 | ## Description 22 | 23 | Several functions and operators in Solidity are deprecated. Using them leads to reduced code quality. With new major versions of the Solidity compiler, deprecated functions and operators may result in side effects and compile errors. 24 | 25 | ## Remediation 26 | 27 | Solidity provides alternatives to the deprecated constructions. Most of them are aliases, thus replacing old constructions will not break current behavior. For example, `sha3` can be replaced with `keccak256`. 28 | 29 | | Deprecated | Alternative | 30 | | ----------------------- | ----------------------- | 31 | | `suicide(address)` | `selfdestruct(address)` | 32 | | `block.blockhash(uint)` | `blockhash(uint)` | 33 | | `sha3(...)` | `keccak256(...)` | 34 | | `callcode(...)` | `delegatecall(...)` | 35 | | `throw` | `revert()` | 36 | | `msg.gas` | `gasleft` | 37 | | `constant` | `view` | 38 | | `var` | corresponding type name | 39 | 40 | ## References 41 | 42 | - [List of global variables and functions, as of Solidity 0.4.25](https://solidity.readthedocs.io/en/v0.4.25/miscellaneous.html#global-variables) 43 | - [Error handling: Assert, Require, Revert and Exceptions](https://solidity.readthedocs.io/en/v0.4.25/control-structures.html#error-handling-assert-require-revert-and-exceptions) 44 | - [View functions](https://solidity.readthedocs.io/en/v0.4.25/contracts.html#view-functions) 45 | - [Untyped declaration is deprecated as of Solidity 0.4.20](https://github.com/ethereum/solidity/releases/tag/v0.4.20) 46 | - [Solidity compiler changelog](https://github.com/ethereum/solidity/releases) 47 | 48 | ## Samples 49 | 50 | ### deprecated_simple.sol 51 | 52 | ```solidity 53 | pragma solidity ^0.4.24; 54 | 55 | contract DeprecatedSimple { 56 | 57 | // Do everything that's deprecated, then commit suicide. 58 | 59 | function useDeprecated() public constant { 60 | 61 | bytes32 blockhash = block.blockhash(0); 62 | bytes32 hashofhash = sha3(blockhash); 63 | 64 | uint gas = msg.gas; 65 | 66 | if (gas == 0) { 67 | throw; 68 | } 69 | 70 | address(this).callcode(); 71 | 72 | var a = [1,2,3]; 73 | 74 | var (x, y, z) = (false, "test", 0); 75 | 76 | suicide(address(0)); 77 | } 78 | 79 | function () public {} 80 | 81 | } 82 | 83 | ``` 84 | 85 | ### deprecated_simple_fixed.sol 86 | 87 | ```solidity 88 | pragma solidity ^0.4.24; 89 | 90 | contract DeprecatedSimpleFixed { 91 | 92 | function useDeprecatedFixed() public view { 93 | 94 | bytes32 bhash = blockhash(0); 95 | bytes32 hashofhash = keccak256(bhash); 96 | 97 | uint gas = gasleft(); 98 | 99 | if (gas == 0) { 100 | revert(); 101 | } 102 | 103 | address(this).delegatecall(); 104 | 105 | uint8[3] memory a = [1,2,3]; 106 | 107 | (bool x, string memory y, uint8 z) = (false, "test", 0); 108 | 109 | selfdestruct(address(0)); 110 | } 111 | 112 | function () external {} 113 | 114 | } 115 | 116 | ``` 117 | -------------------------------------------------------------------------------- /entries/docs/SWC-112.md: -------------------------------------------------------------------------------- 1 | # Please note, this content is no longer actively maintained. 2 | 3 | The content of the SWC registry has not been thoroughly updated since 2020. It is known to be incomplete and may contain errors as well as crucial omissions. 4 | 5 | For currently maintained guidance on known Smart Contract vulnerabilities written primarily as guidance for security reviewers, please see the 6 | [EEA EthTrust Security Levels specification](https://entethalliance.org/specs/ethtrust-sl). As well as the latest release version, an 7 | [Editor's draft](https://entethalliance.github.io/eta-registry/security-levels-spec.html) is available, 8 | that represents the latest work of the group developing the specification. 9 | 10 | General guidance for developers on what to consider to ensure security, that is currently maintained, is also available through the 11 | [Smart Contract Security Verification Standard (SCSVS)](https://github.com/ComposableSecurity/SCSVS). 12 | 13 | # Title 14 | 15 | Delegatecall to Untrusted Callee 16 | 17 | ## Relationships 18 | 19 | [CWE-829: Inclusion of Functionality from Untrusted Control Sphere](https://cwe.mitre.org/data/definitions/829.html) 20 | 21 | ## Description 22 | 23 | There exists a special variant of a message call, named `delegatecall` which is identical to a message call apart from the fact that the code at the target address is executed in the context of the calling contract and `msg.sender` and `msg.value` do not change their values. This allows a smart contract to dynamically load code from a different address at runtime. Storage, current address and balance still refer to the calling contract. 24 | 25 | Calling into untrusted contracts is very dangerous, as the code at the target address can change any storage values of the caller and has full control over the caller's balance. 26 | 27 | ## Remediation 28 | 29 | Use `delegatecall` with caution and make sure to never call into untrusted contracts. If the target address is derived from user input ensure to check it against a whitelist of trusted contracts. 30 | 31 | ## References 32 | 33 | - [Solidity Documentation - Delegatecall / Callcode and Libraries](https://solidity.readthedocs.io/en/latest/introduction-to-smart-contracts.html#delegatecall-callcode-and-libraries) 34 | - [How to Secure Your Smart Contracts: 6 Solidity Vulnerabilities and how to avoid them (Part 1) - Delegate Call](https://medium.com/loom-network/how-to-secure-your-smart-contracts-6-solidity-vulnerabilities-and-how-to-avoid-them-part-1-c33048d4d17d) 35 | - [Solidity Security: Comprehensive list of known attack vectors and common anti-patterns - Delegatecall](https://blog.sigmaprime.io/solidity-security.html#delegatecall) 36 | 37 | ## Samples 38 | 39 | ### proxy.sol 40 | 41 | ```solidity 42 | pragma solidity ^0.4.24; 43 | 44 | contract Proxy { 45 | 46 | address owner; 47 | 48 | constructor() public { 49 | owner = msg.sender; 50 | } 51 | 52 | function forward(address callee, bytes _data) public { 53 | require(callee.delegatecall(_data)); 54 | } 55 | 56 | } 57 | 58 | ``` 59 | 60 | ### proxy_fixed.sol 61 | 62 | ```solidity 63 | pragma solidity ^0.4.24; 64 | 65 | contract Proxy { 66 | 67 | address callee; 68 | address owner; 69 | 70 | modifier onlyOwner { 71 | require(msg.sender == owner); 72 | _; 73 | } 74 | 75 | constructor() public { 76 | callee = address(0x0); 77 | owner = msg.sender; 78 | } 79 | 80 | function setCallee(address newCallee) public onlyOwner { 81 | callee = newCallee; 82 | } 83 | 84 | function forward(bytes _data) public { 85 | require(callee.delegatecall(_data)); 86 | } 87 | 88 | } 89 | 90 | ``` 91 | 92 | ### proxy_pattern_false_positive.sol 93 | 94 | ```solidity 95 | pragma solidity ^0.4.24; 96 | 97 | contract proxy{ 98 | address owner; 99 | 100 | function proxyCall(address _to, bytes _data) external { 101 | require( !_to.delegatecall(_data)); 102 | } 103 | function withdraw() external{ 104 | require(msg.sender == owner); 105 | msg.sender.transfer(address(this).balance); 106 | } 107 | } 108 | 109 | /* 110 | You can't use proxyCall to change the owner address as either: 111 | 112 | 1) the delegatecall reverts and thus does not change owner 113 | 2) the delegatecall does not revert and therefore will cause the proxyCall to revert and preventing owner from changing 114 | 115 | This false positive may seem like a really edge case, however since you can revert data back to proxy this patern is useful for proxy architectures 116 | */ 117 | ``` 118 | -------------------------------------------------------------------------------- /entries/docs/SWC-113.md: -------------------------------------------------------------------------------- 1 | # Please note, this content is no longer actively maintained. 2 | 3 | The content of the SWC registry has not been thoroughly updated since 2020. It is known to be incomplete and may contain errors as well as crucial omissions. 4 | 5 | For currently maintained guidance on known Smart Contract vulnerabilities written primarily as guidance for security reviewers, please see the 6 | [EEA EthTrust Security Levels specification](https://entethalliance.org/specs/ethtrust-sl). As well as the latest release version, an 7 | [Editor's draft](https://entethalliance.github.io/eta-registry/security-levels-spec.html) is available, 8 | that represents the latest work of the group developing the specification. 9 | 10 | General guidance for developers on what to consider to ensure security, that is currently maintained, is also available through the 11 | [Smart Contract Security Verification Standard (SCSVS)](https://github.com/ComposableSecurity/SCSVS). 12 | 13 | # Title 14 | 15 | DoS with Failed Call 16 | 17 | ## Relationships 18 | 19 | [CWE-703: Improper Check or Handling of Exceptional Conditions](https://cwe.mitre.org/data/definitions/703.html) 20 | 21 | ## Description 22 | 23 | External calls can fail accidentally or deliberately, which can cause a DoS condition in the contract. To minimize the damage caused by such failures, it is better to isolate each external call into its own transaction that can be initiated by the recipient of the call. This is especially relevant for payments, where it is better to let users withdraw funds rather than push funds to them automatically (this also reduces the chance of problems with the gas limit). 24 | 25 | ## Remediation 26 | 27 | It is recommended to follow call best practices: 28 | 29 | - Avoid combining multiple calls in a single transaction, especially when calls are executed as part of a loop 30 | - Always assume that external calls can fail 31 | - Implement the contract logic to handle failed calls 32 | 33 | ## References 34 | 35 | - [Ethereum Smart Contract Best Practices - Favor pull over push for external calls](https://consensys.github.io/smart-contract-best-practices/development-recommendations/general/external-calls/#favor-pull-over-push-for-external-calls) 36 | 37 | ## Samples 38 | 39 | ### send_loop.sol 40 | 41 | ```solidity 42 | /* 43 | * @source: https://consensys.github.io/smart-contract-best-practices/known_attacks/#dos-with-unexpected-revert 44 | * @author: ConsenSys Diligence 45 | * Modified by Bernhard Mueller 46 | */ 47 | 48 | pragma solidity 0.4.24; 49 | 50 | contract Refunder { 51 | 52 | address[] private refundAddresses; 53 | mapping (address => uint) public refunds; 54 | 55 | constructor() { 56 | refundAddresses.push(0x79B483371E87d664cd39491b5F06250165e4b184); 57 | refundAddresses.push(0x79B483371E87d664cd39491b5F06250165e4b185); 58 | } 59 | 60 | // bad 61 | function refundAll() public { 62 | for(uint x; x < refundAddresses.length; x++) { // arbitrary length iteration based on how many addresses participated 63 | require(refundAddresses[x].send(refunds[refundAddresses[x]])); // doubly bad, now a single failure on send will hold up all funds 64 | } 65 | } 66 | 67 | } 68 | 69 | ``` 70 | -------------------------------------------------------------------------------- /entries/docs/SWC-114.md: -------------------------------------------------------------------------------- 1 | # Please note, this content is no longer actively maintained. 2 | 3 | The content of the SWC registry has not been thoroughly updated since 2020. It is known to be incomplete and may contain errors as well as crucial omissions. 4 | 5 | For currently maintained guidance on known Smart Contract vulnerabilities written primarily as guidance for security reviewers, please see the 6 | [EEA EthTrust Security Levels specification](https://entethalliance.org/specs/ethtrust-sl). As well as the latest release version, an 7 | [Editor's draft](https://entethalliance.github.io/eta-registry/security-levels-spec.html) is available, 8 | that represents the latest work of the group developing the specification. 9 | 10 | General guidance for developers on what to consider to ensure security, that is currently maintained, is also available through the 11 | [Smart Contract Security Verification Standard (SCSVS)](https://github.com/ComposableSecurity/SCSVS). 12 | 13 | # Title 14 | 15 | Transaction Order Dependence 16 | 17 | ## Relationships 18 | 19 | [CWE-362: Concurrent Execution using Shared Resource with Improper Synchronization ('Race Condition')](https://cwe.mitre.org/data/definitions/362.html) 20 | 21 | ## Description 22 | 23 | The Ethereum network processes transactions in blocks, with new blocks getting confirmed approximately every 17 seconds. Miners review the transactions they have received and select which ones to include in a block, based on who has paid a high enough gas price to be included. Additionally, when transactions are sent to the Ethereum network, they are forwarded to each node for processing. Thus, a person who is running an Ethereum node can tell which transactions are going to occur before they are finalized. A race condition vulnerability occurs when code depends on the order of the transactions submitted to it. 24 | 25 | The simplest example of a race condition is when a smart contract gives a reward for submitting information. Suppose a contract will give out 1 token to the first person who solves a math problem. Alice solves the problem and submits the answer to the network with a standard gas price. Eve runs an Ethereum node and can see the answer to the math problem in the transaction that Alice submitted to the network. So, Eve submits the answer to the network with a much higher gas price, and thus it gets processed and committed before Alice's transaction. Eve receives one token, and Alice gets nothing, even though it was Alice who worked to solve the problem. A common way this occurs in practice is when a contract rewards people for calling out bad behavior in a protocol by giving a bad actor's deposit to the person who proved they were misbehaving. 26 | 27 | The race condition that happens most frequently on the network today is the race condition in the ERC20 token standard. The ERC20 token standard includes a function called 'approve', which allows an address to approve another address to spend tokens on their behalf. Assume that Alice has approved Eve to spend n of her tokens, then Alice decides to change Eve's approval to m tokens. Alice submits a function call to approve with the value n for Eve. Eve runs an Ethereum node, so she knows that Alice is going to change her approval to m. Eve then submits a transferFrom request, sending n of Alice's tokens to herself, but gives it a much higher gas price than Alice's transaction. The transferFrom executes first so gives Eve n tokens and sets Eve's approval to zero. Then Alice's transaction executes and sets Eve's approval to m. Eve then sends those m tokens to herself as well. Thus, Eve gets n + m tokens, even though she should have gotten at most max(n,m). 28 | 29 | ## Remediation 30 | 31 | A possible way to remedy race conditions in the submission of information in exchange for a reward is called a commit reveal hash scheme. Instead of submitting the answer, the party who has the answer submits hash(salt, address, answer) \[salt being some number of their choosing\]; the contract stores this hash and the sender's address. To claim the reward, the sender then submits a transaction with the salt, and answer. The contract hashes (salt, msg.sender, answer) and checks the hash produced against the stored hash. If the hash matches, the contract releases the reward. 32 | 33 | The best fix for the ERC20 race condition is to add a field to the inputs of approve, which is the expected current value, and to have approve revert if Eve's current allowance is not what Alice indicated she was expecting. However, this means that your contract no longer conforms to the ERC20 standard. If it is important to your project to have the contract conform to ERC20, you can add a safe approve function. From the user's perspective, it is possible to mitigate the ERC20 race condition by setting approvals to zero before changing them. 34 | 35 | ## References 36 | 37 | [General Article on Race Conditions](https://medium.com/coinmonks/solidity-transaction-ordering-attacks-1193a014884e) 38 | [ERC20 Race Condition](https://docs.google.com/document/d/1YLPtQxZu1UAvO9cZ1O2RPXBbT0mooh4DYKjA_jp-RLM/edit#) 39 | 40 | ## Samples 41 | 42 | ### ERC20.sol 43 | 44 | ```solidity 45 | pragma solidity ^0.4.24; 46 | 47 | /** Taken from the OpenZeppelin github 48 | * @title SafeMath 49 | * @dev Math operations with safety checks that revert on error 50 | */ 51 | library SafeMath { 52 | 53 | /** 54 | * @dev Multiplies two numbers, reverts on overflow. 55 | */ 56 | function mul(uint256 a, uint256 b) internal pure returns (uint256) { 57 | // Gas optimization: this is cheaper than requiring 'a' not being zero, but the 58 | // benefit is lost if 'b' is also tested. 59 | // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522 60 | if (a == 0) { 61 | return 0; 62 | } 63 | 64 | uint256 c = a * b; 65 | require(c / a == b); 66 | 67 | return c; 68 | } 69 | 70 | /** 71 | * @dev Integer division of two numbers truncating the quotient, reverts on division by zero. 72 | */ 73 | function div(uint256 a, uint256 b) internal pure returns (uint256) { 74 | require(b > 0); // Solidity only automatically asserts when dividing by 0 75 | uint256 c = a / b; 76 | // assert(a == b * c + a % b); // There is no case in which this doesn't hold 77 | 78 | return c; 79 | } 80 | 81 | /** 82 | * @dev Subtracts two numbers, reverts on overflow (i.e. if subtrahend is greater than minuend). 83 | */ 84 | function sub(uint256 a, uint256 b) internal pure returns (uint256) { 85 | require(b <= a); 86 | uint256 c = a - b; 87 | 88 | return c; 89 | } 90 | 91 | /** 92 | * @dev Adds two numbers, reverts on overflow. 93 | */ 94 | function add(uint256 a, uint256 b) internal pure returns (uint256) { 95 | uint256 c = a + b; 96 | require(c >= a); 97 | 98 | return c; 99 | } 100 | 101 | /** 102 | * @dev Divides two numbers and returns the remainder (unsigned integer modulo), 103 | * reverts when dividing by zero. 104 | */ 105 | function mod(uint256 a, uint256 b) internal pure returns (uint256) { 106 | require(b != 0); 107 | return a % b; 108 | } 109 | } 110 | 111 | 112 | contract ERC20 { 113 | 114 | event Transfer( address indexed from, address indexed to, uint256 value ); 115 | event Approval( address indexed owner, address indexed spender, uint256 value); 116 | using SafeMath for *; 117 | 118 | mapping (address => uint256) private _balances; 119 | 120 | mapping (address => mapping (address => uint256)) private _allowed; 121 | 122 | uint256 private _totalSupply; 123 | 124 | constructor(uint totalSupply){ 125 | _balances[msg.sender] = totalSupply; 126 | } 127 | 128 | function balanceOf(address owner) public view returns (uint256) { 129 | return _balances[owner]; 130 | } 131 | 132 | 133 | function allowance(address owner, address spender) public view returns (uint256) 134 | { 135 | return _allowed[owner][spender]; 136 | } 137 | 138 | function transfer(address to, uint256 value) public returns (bool) { 139 | require(value <= _balances[msg.sender]); 140 | require(to != address(0)); 141 | 142 | _balances[msg.sender] = _balances[msg.sender].sub(value); 143 | _balances[to] = _balances[to].add(value); 144 | emit Transfer(msg.sender, to, value); 145 | return true; 146 | } 147 | 148 | function approve(address spender, uint256 value) public returns (bool) { 149 | require(spender != address(0)); 150 | 151 | _allowed[msg.sender][spender] = value; 152 | emit Approval(msg.sender, spender, value); 153 | return true; 154 | } 155 | 156 | function transferFrom(address from, address to, uint256 value) public returns (bool) { 157 | require(value <= _balances[from]); 158 | require(value <= _allowed[from][msg.sender]); 159 | require(to != address(0)); 160 | 161 | _balances[from] = _balances[from].sub(value); 162 | _balances[to] = _balances[to].add(value); 163 | _allowed[from][msg.sender] = _allowed[from][msg.sender].sub(value); 164 | emit Transfer(from, to, value); 165 | return true; 166 | } 167 | } 168 | 169 | ``` 170 | 171 | ### eth_tx_order_dependence_minimal.sol 172 | 173 | ```solidity 174 | /* 175 | * @source: https://github.com/ConsenSys/evm-analyzer-benchmark-suite 176 | * @author: Suhabe Bugrara 177 | */ 178 | 179 | pragma solidity ^0.4.16; 180 | 181 | contract EthTxOrderDependenceMinimal { 182 | address public owner; 183 | bool public claimed; 184 | uint public reward; 185 | 186 | function EthTxOrderDependenceMinimal() public { 187 | owner = msg.sender; 188 | } 189 | 190 | function setReward() public payable { 191 | require (!claimed); 192 | 193 | require(msg.sender == owner); 194 | owner.transfer(reward); 195 | reward = msg.value; 196 | } 197 | 198 | function claimReward(uint256 submission) { 199 | require (!claimed); 200 | require(submission < 10); 201 | 202 | msg.sender.transfer(reward); 203 | claimed = true; 204 | } 205 | } 206 | 207 | 208 | ``` 209 | -------------------------------------------------------------------------------- /entries/docs/SWC-115.md: -------------------------------------------------------------------------------- 1 | # Please note, this content is no longer actively maintained. 2 | 3 | The content of the SWC registry has not been thoroughly updated since 2020. It is known to be incomplete and may contain errors as well as crucial omissions. 4 | 5 | For currently maintained guidance on known Smart Contract vulnerabilities written primarily as guidance for security reviewers, please see the 6 | [EEA EthTrust Security Levels specification](https://entethalliance.org/specs/ethtrust-sl). As well as the latest release version, an 7 | [Editor's draft](https://entethalliance.github.io/eta-registry/security-levels-spec.html) is available, 8 | that represents the latest work of the group developing the specification. 9 | 10 | General guidance for developers on what to consider to ensure security, that is currently maintained, is also available through the 11 | [Smart Contract Security Verification Standard (SCSVS)](https://github.com/ComposableSecurity/SCSVS). 12 | 13 | # Title 14 | 15 | Authorization through tx.origin 16 | 17 | ## Relationships 18 | 19 | - [CWE-477: Use of Obsolete Function](https://cwe.mitre.org/data/definitions/477.html) 20 | - EEA EthTrust Security Levels: 21 | - [**[S] No `tx.origin`**](https://entethalliance.github.io/eta-registry/security-levels-spec.html#req-1-no-tx.origin) 22 | - [**[Q] Verify `tx.origin` Usage**](https://entethalliance.github.io/eta-registry/security-levels-spec.html#req-3-verify-tx.origin) 23 | 24 | ## Description 25 | 26 | `tx.origin` is a global variable in Solidity which returns the address of the account that sent the transaction. Using the variable for authorization could make a contract vulnerable if an authorized account calls into a malicious contract. A call could be made to the vulnerable contract that passes the authorization check since `tx.origin` returns the original sender of the transaction which in this case is the authorized account. 27 | 28 | ## Remediation 29 | 30 | `tx.origin` should not be used for authorization. Use `msg.sender` instead. 31 | 32 | ## References 33 | 34 | - [Solidity Documentation - tx.origin](https://solidity.readthedocs.io/en/develop/security-considerations.html#tx-origin) 35 | - [Ethereum Smart Contract Best Practices - Avoid using tx.origin](https://consensys.github.io/smart-contract-best-practices/development-recommendations/solidity-specific/tx-origin/) 36 | - [SigmaPrime - Visibility](https://github.com/sigp/solidity-security-blog#tx-origin) 37 | 38 | ## Samples 39 | 40 | ### mycontract.sol 41 | 42 | ```solidity 43 | /* 44 | * @source: https://consensys.github.io/smart-contract-best-practices/recommendations/#avoid-using-txorigin 45 | * @author: Consensys Diligence 46 | * Modified by Gerhard Wagner 47 | */ 48 | 49 | pragma solidity 0.4.24; 50 | 51 | contract MyContract { 52 | 53 | address owner; 54 | 55 | function MyContract() public { 56 | owner = msg.sender; 57 | } 58 | 59 | function sendTo(address receiver, uint amount) public { 60 | require(tx.origin == owner); 61 | receiver.transfer(amount); 62 | } 63 | 64 | } 65 | ``` 66 | 67 | ### mycontract_fixed.sol 68 | 69 | ```solidity 70 | /* 71 | * @source: https://consensys.github.io/smart-contract-best-practices/recommendations/#avoid-using-txorigin 72 | * @author: Consensys Diligence 73 | * Modified by Gerhard Wagner 74 | */ 75 | 76 | pragma solidity 0.4.25; 77 | 78 | contract MyContract { 79 | 80 | address owner; 81 | 82 | function MyContract() public { 83 | owner = msg.sender; 84 | } 85 | 86 | function sendTo(address receiver, uint amount) public { 87 | require(msg.sender == owner); 88 | receiver.transfer(amount); 89 | } 90 | 91 | } 92 | 93 | ``` 94 | -------------------------------------------------------------------------------- /entries/docs/SWC-116.md: -------------------------------------------------------------------------------- 1 | # Please note, this content is no longer actively maintained. 2 | 3 | The content of the SWC registry has not been thoroughly updated since 2020. It is known to be incomplete and may contain errors as well as crucial omissions. 4 | 5 | For currently maintained guidance on known Smart Contract vulnerabilities written primarily as guidance for security reviewers, please see the 6 | [EEA EthTrust Security Levels specification](https://entethalliance.org/specs/ethtrust-sl). As well as the latest release version, an 7 | [Editor's draft](https://entethalliance.github.io/eta-registry/security-levels-spec.html) is available, 8 | that represents the latest work of the group developing the specification. 9 | 10 | General guidance for developers on what to consider to ensure security, that is currently maintained, is also available through the 11 | [Smart Contract Security Verification Standard (SCSVS)](https://github.com/ComposableSecurity/SCSVS). 12 | 13 | # Title 14 | 15 | Block values as a proxy for time 16 | 17 | ## Relationships 18 | 19 | - [CWE-829: Inclusion of Functionality from Untrusted Control Sphere](https://cwe.mitre.org/data/definitions/829.html) 20 | - [**[M] Document Special Code Use**](https://entethalliance.org/specs/ethtrust-sl/#req-2-documented) 21 | - [**[M] Don't Misuse Block Data**](https://entethalliance.org/specs/ethtrust-sl/#req-2-block-data-misuse) 22 | 23 | ## Description 24 | 25 | Contracts often need access to time values to perform certain types of functionality. Values such as `block.timestamp`, and `block.number` can give you a sense of the current time or a time delta, however, they are not safe to use for most purposes. 26 | 27 | In the case of `block.timestamp`, developers often attempt to use it to trigger time-dependent events. As Ethereum is decentralized, nodes can synchronize time only to some degree. Moreover, malicious miners can alter the timestamp of their blocks, especially if they can gain advantages by doing so. However, miners can't set a timestamp smaller than the previous one (otherwise the block will be rejected), nor can they set the timestamp too far ahead in the future. Taking all of the above into consideration, developers can't rely on the preciseness of the provided timestamp. 28 | 29 | As for `block.number`, considering the block time on Ethereum is generally about 14 seconds, it's possible to predict the time delta between blocks. However, block times are not constant and are subject to change for a variety of reasons, e.g. fork reorganisations and the difficulty bomb. Due to variable block times, `block.number` should also not be relied on for precise calculations of time. 30 | 31 | ## Remediation 32 | 33 | Developers should write smart contracts with the notion that block values are not precise, and the use of them can lead to unexpected effects. Alternatively, they may make use of oracles. 34 | 35 | ## References 36 | 37 | - [Safety: Timestamp dependence](https://github.com/ethereum/wiki/wiki/Safety#timestamp-dependence) 38 | - [Ethereum Smart Contract Best Practices - Timestamp Dependence](https://consensys.github.io/smart-contract-best-practices/development-recommendations/solidity-specific/timestamp-dependence/) 39 | - [How do Ethereum mining nodes maintain a time consistent with the network?](https://ethereum.stackexchange.com/questions/5924/how-do-ethereum-mining-nodes-maintain-a-time-consistent-with-the-network/5926#5926) 40 | - [Solidity: Timestamp dependency, is it possible to do safely?](https://ethereum.stackexchange.com/questions/15047/solidity-timestamp-dependency-is-it-possible-to-do-safely) 41 | - [Avoid using block.number as a timestamp](https://consensys.github.io/smart-contract-best-practices/development-recommendations/solidity-specific/timestamp-dependence/#avoid-using-blocknumber-as-a-timestamp) 42 | 43 | ## Samples 44 | 45 | ### time_lock.sol 46 | 47 | ```solidity 48 | /* 49 | * @author: Kaden Zipfel 50 | */ 51 | 52 | pragma solidity ^0.5.0; 53 | 54 | contract TimeLock { 55 | struct User { 56 | uint amount; // amount locked (in eth) 57 | uint unlockBlock; // minimum block to unlock eth 58 | } 59 | 60 | mapping(address => User) private users; 61 | 62 | // Tokens should be locked for exact time specified 63 | function lockEth(uint _time, uint _amount) public payable { 64 | require(msg.value == _amount, 'must send exact amount'); 65 | users[msg.sender].unlockBlock = block.number + (_time / 14); 66 | users[msg.sender].amount = _amount; 67 | } 68 | 69 | // Withdraw tokens if lock period is over 70 | function withdraw() public { 71 | require(users[msg.sender].amount > 0, 'no amount locked'); 72 | require(block.number >= users[msg.sender].unlockBlock, 'lock period not over'); 73 | 74 | uint amount = users[msg.sender].amount; 75 | users[msg.sender].amount = 0; 76 | (bool success, ) = msg.sender.call.value(amount)(""); 77 | require(success, 'transfer failed'); 78 | } 79 | } 80 | 81 | ``` 82 | 83 | ### timed_crowdsale.sol 84 | 85 | ```solidity 86 | pragma solidity ^0.5.0; 87 | 88 | contract TimedCrowdsale { 89 | 90 | event Finished(); 91 | event notFinished(); 92 | 93 | // Sale should finish exactly at January 1, 2019 94 | function isSaleFinished() private returns (bool) { 95 | return block.timestamp >= 1546300800; 96 | } 97 | 98 | function run() public { 99 | if (isSaleFinished()) { 100 | emit Finished(); 101 | } else { 102 | emit notFinished(); 103 | } 104 | } 105 | 106 | } 107 | ``` 108 | -------------------------------------------------------------------------------- /entries/docs/SWC-117.md: -------------------------------------------------------------------------------- 1 | # Please note, this content is no longer actively maintained. 2 | 3 | The content of the SWC registry has not been thoroughly updated since 2020. It is known to be incomplete and may contain errors as well as crucial omissions. 4 | 5 | For currently maintained guidance on known Smart Contract vulnerabilities written primarily as guidance for security reviewers, please see the 6 | [EEA EthTrust Security Levels specification](https://entethalliance.org/specs/ethtrust-sl). As well as the latest release version, an 7 | [Editor's draft](https://entethalliance.github.io/eta-registry/security-levels-spec.html) is available, 8 | that represents the latest work of the group developing the specification. 9 | 10 | General guidance for developers on what to consider to ensure security, that is currently maintained, is also available through the 11 | [Smart Contract Security Verification Standard (SCSVS)](https://github.com/ComposableSecurity/SCSVS). 12 | 13 | # Title 14 | 15 | Signature Malleability 16 | 17 | ## Relationships 18 | 19 | [CWE-347: Improper Verification of Cryptographic Signature](https://cwe.mitre.org/data/definitions/347.html) 20 | 21 | ## Description 22 | 23 | The implementation of a cryptographic signature system in Ethereum contracts often assumes that the signature is unique, but signatures can be altered without the possession of the private key and still be valid. The EVM specification defines several so-called ‘precompiled’ contracts one of them being `ecrecover` which executes the elliptic curve public key recovery. A malicious user can slightly modify the three values _v_, _r_ and _s_ to create other valid signatures. A system that performs signature verification on contract level might be susceptible to attacks if the signature is part of the signed message hash. Valid signatures could be created by a malicious user to replay previously signed messages. 24 | 25 | ## Remediation 26 | 27 | A signature should never be included into a signed message hash to check if previously messages have been processed by the contract. 28 | 29 | ## References 30 | 31 | [Bitcoin Transaction Malleability](https://eklitzke.org/bitcoin-transaction-malleability) 32 | [CTF - Challenge](https://ropsten.etherscan.io/address/0x0daabce0a1261b582e0d949ebca9dff4c22c88ef#code) 33 | 34 | ## Samples 35 | 36 | ### transaction_malleablity.sol 37 | 38 | ```solidity 39 | pragma solidity ^0.4.24; 40 | 41 | contract transaction_malleablity{ 42 | mapping(address => uint256) balances; 43 | mapping(bytes32 => bool) signatureUsed; 44 | 45 | constructor(address[] owners, uint[] init){ 46 | require(owners.length == init.length); 47 | for(uint i=0; i < owners.length; i ++){ 48 | balances[owners[i]] = init[i]; 49 | } 50 | } 51 | 52 | function transfer( 53 | bytes _signature, 54 | address _to, 55 | uint256 _value, 56 | uint256 _gasPrice, 57 | uint256 _nonce) 58 | public 59 | returns (bool) 60 | { 61 | bytes32 txid = keccak256(abi.encodePacked(getTransferHash(_to, _value, _gasPrice, _nonce), _signature)); 62 | require(!signatureUsed[txid]); 63 | 64 | address from = recoverTransferPreSigned(_signature, _to, _value, _gasPrice, _nonce); 65 | 66 | require(balances[from] > _value); 67 | balances[from] -= _value; 68 | balances[_to] += _value; 69 | 70 | signatureUsed[txid] = true; 71 | } 72 | 73 | function recoverTransferPreSigned( 74 | bytes _sig, 75 | address _to, 76 | uint256 _value, 77 | uint256 _gasPrice, 78 | uint256 _nonce) 79 | public 80 | view 81 | returns (address recovered) 82 | { 83 | return ecrecoverFromSig(getSignHash(getTransferHash(_to, _value, _gasPrice, _nonce)), _sig); 84 | } 85 | 86 | function getTransferHash( 87 | address _to, 88 | uint256 _value, 89 | uint256 _gasPrice, 90 | uint256 _nonce) 91 | public 92 | view 93 | returns (bytes32 txHash) { 94 | return keccak256(address(this), bytes4(0x1296830d), _to, _value, _gasPrice, _nonce); 95 | } 96 | 97 | function getSignHash(bytes32 _hash) 98 | public 99 | pure 100 | returns (bytes32 signHash) 101 | { 102 | return keccak256("\x19Ethereum Signed Message:\n32", _hash); 103 | } 104 | 105 | function ecrecoverFromSig(bytes32 hash, bytes sig) 106 | public 107 | pure 108 | returns (address recoveredAddress) 109 | { 110 | bytes32 r; 111 | bytes32 s; 112 | uint8 v; 113 | if (sig.length != 65) return address(0); 114 | assembly { 115 | r := mload(add(sig, 32)) 116 | s := mload(add(sig, 64)) 117 | v := byte(0, mload(add(sig, 96))) 118 | } 119 | if (v < 27) { 120 | v += 27; 121 | } 122 | if (v != 27 && v != 28) return address(0); 123 | return ecrecover(hash, v, r, s); 124 | } 125 | } 126 | 127 | ``` 128 | 129 | ### transaction_malleablity_fixed.sol 130 | 131 | ```solidity 132 | pragma solidity ^0.4.24; 133 | 134 | contract transaction_malleablity{ 135 | mapping(address => uint256) balances; 136 | mapping(bytes32 => bool) signatureUsed; 137 | 138 | constructor(address[] owners, uint[] init){ 139 | require(owners.length == init.length); 140 | for(uint i=0; i < owners.length; i ++){ 141 | balances[owners[i]] = init[i]; 142 | } 143 | } 144 | 145 | function transfer( 146 | bytes _signature, 147 | address _to, 148 | uint256 _value, 149 | uint256 _gasPrice, 150 | uint256 _nonce) 151 | public 152 | returns (bool) 153 | { 154 | bytes32 txid = getTransferHash(_to, _value, _gasPrice, _nonce); 155 | require(!signatureUsed[txid]); 156 | 157 | address from = recoverTransferPreSigned(_signature, _to, _value, _gasPrice, _nonce); 158 | 159 | require(balances[from] > _value); 160 | balances[from] -= _value; 161 | balances[_to] += _value; 162 | 163 | signatureUsed[txid] = true; 164 | } 165 | 166 | function recoverTransferPreSigned( 167 | bytes _sig, 168 | address _to, 169 | uint256 _value, 170 | uint256 _gasPrice, 171 | uint256 _nonce) 172 | public 173 | view 174 | returns (address recovered) 175 | { 176 | return ecrecoverFromSig(getSignHash(getTransferHash(_to, _value, _gasPrice, _nonce)), _sig); 177 | } 178 | 179 | function getTransferHash( 180 | address _to, 181 | uint256 _value, 182 | uint256 _gasPrice, 183 | uint256 _nonce) 184 | public 185 | view 186 | returns (bytes32 txHash) { 187 | return keccak256(address(this), bytes4(0x1296830d), _to, _value, _gasPrice, _nonce); 188 | } 189 | 190 | function getSignHash(bytes32 _hash) 191 | public 192 | pure 193 | returns (bytes32 signHash) 194 | { 195 | return keccak256("\x19Ethereum Signed Message:\n32", _hash); 196 | } 197 | 198 | function ecrecoverFromSig(bytes32 hash, bytes sig) 199 | public 200 | pure 201 | returns (address recoveredAddress) 202 | { 203 | bytes32 r; 204 | bytes32 s; 205 | uint8 v; 206 | if (sig.length != 65) return address(0); 207 | assembly { 208 | r := mload(add(sig, 32)) 209 | s := mload(add(sig, 64)) 210 | v := byte(0, mload(add(sig, 96))) 211 | } 212 | if (v < 27) { 213 | v += 27; 214 | } 215 | if (v != 27 && v != 28) return address(0); 216 | return ecrecover(hash, v, r, s); 217 | } 218 | } 219 | 220 | ``` 221 | -------------------------------------------------------------------------------- /entries/docs/SWC-118.md: -------------------------------------------------------------------------------- 1 | # Please note, this content is no longer actively maintained. 2 | 3 | The content of the SWC registry has not been thoroughly updated since 2020. It is known to be incomplete and may contain errors as well as crucial omissions. 4 | 5 | For currently maintained guidance on known Smart Contract vulnerabilities written primarily as guidance for security reviewers, please see the 6 | [EEA EthTrust Security Levels specification](https://entethalliance.org/specs/ethtrust-sl). As well as the latest release version, an 7 | [Editor's draft](https://entethalliance.github.io/eta-registry/security-levels-spec.html) is available, that represents the latest work of the group developing the specification. 8 | 9 | General guidance for developers on what to consider to ensure security, that is currently maintained, is also available through the 10 | [Smart Contract Security Verification Standard (SCSVS)](https://github.com/ComposableSecurity/SCSVS). 11 | 12 | # Title 13 | 14 | Incorrect Constructor Name 15 | 16 | ## Relationships 17 | 18 | - [CWE-665: Improper Initialization](http://cwe.mitre.org/data/definitions/665.html) 19 | - EthTrust Security Levels 20 | - [**[S] Use a Modern Compiler**](https://entethalliance.org/specs/ethtrust-sl/#req-1-compiler-060) 21 | - [**[Q] Code Linting**](https://entethalliance.org/specs/ethtrust-sl/#req-3-linted) 22 | 23 | ## Description 24 | 25 | Constructors are special functions that are called only once during the contract creation. They often perform critical, privileged actions such as setting the owner of the contract. Before Solidity version 0.4.22, the only way of defining a constructor was to create a function with the same name as the contract class containing it. A function meant to become a constructor becomes a normal, callable function if its name doesn't exactly match the contract name. 26 | This behavior sometimes leads to security issues, in particular when smart contract code is re-used with a different name but the name of the constructor function is not changed accordingly. 27 | 28 | ## Remediation 29 | 30 | Solidity version 0.4.22 introduces a new `constructor` keyword that make a constructor definitions clearer. It is therefore recommended to upgrade the contract to a recent version of the Solidity compiler and change to the new constructor declaration. 31 | 32 | ## References 33 | 34 | - [SigmaPrime - Constructors with Care](https://blog.sigmaprime.io/solidity-security.html#constructors) 35 | 36 | ## Samples 37 | 38 | ### incorrect_constructor_name1.sol 39 | 40 | ```solidity 41 | /* 42 | * @source: https://github.com/trailofbits/not-so-smart-contracts/blob/master/wrong_constructor_name/incorrect_constructor.sol 43 | * @author: Ben Perez 44 | * Modified by Gerhard Wagner 45 | */ 46 | 47 | 48 | pragma solidity 0.4.24; 49 | 50 | contract Missing{ 51 | address private owner; 52 | 53 | modifier onlyowner { 54 | require(msg.sender==owner); 55 | _; 56 | } 57 | 58 | function missing() 59 | public 60 | { 61 | owner = msg.sender; 62 | } 63 | 64 | function () payable {} 65 | 66 | function withdraw() 67 | public 68 | onlyowner 69 | { 70 | owner.transfer(this.balance); 71 | } 72 | } 73 | 74 | ``` 75 | 76 | ### incorrect_constructor_name1_fixed.sol 77 | 78 | ```solidity 79 | /* 80 | * @source: https://github.com/trailofbits/not-so-smart-contracts/blob/master/wrong_constructor_name/incorrect_constructor.sol 81 | * @author: Ben Perez 82 | * Modified by Gerhard Wagner 83 | */ 84 | 85 | 86 | pragma solidity ^0.4.24; 87 | 88 | contract Missing{ 89 | address private owner; 90 | 91 | modifier onlyowner { 92 | require(msg.sender==owner); 93 | _; 94 | } 95 | 96 | constructor() 97 | public 98 | { 99 | owner = msg.sender; 100 | } 101 | 102 | function () payable {} 103 | 104 | function withdraw() 105 | public 106 | onlyowner 107 | { 108 | owner.transfer(this.balance); 109 | } 110 | } 111 | 112 | ``` 113 | 114 | ### incorrect_constructor_name2.sol 115 | 116 | ```solidity 117 | /* 118 | * @source: https://github.com/trailofbits/not-so-smart-contracts/blob/master/wrong_constructor_name/incorrect_constructor.sol 119 | * @author: Ben Perez 120 | * Modified by Gerhard Wagner 121 | */ 122 | 123 | pragma solidity 0.4.24; 124 | 125 | contract Missing{ 126 | address private owner; 127 | 128 | modifier onlyowner { 129 | require(msg.sender==owner); 130 | _; 131 | } 132 | 133 | function Constructor() 134 | public 135 | { 136 | owner = msg.sender; 137 | } 138 | 139 | function () payable {} 140 | 141 | function withdraw() 142 | public 143 | onlyowner 144 | { 145 | owner.transfer(this.balance); 146 | } 147 | 148 | } 149 | 150 | ``` 151 | 152 | ### incorrect_constructor_name2_fixed.sol 153 | 154 | ```solidity 155 | /* 156 | * @source: https://github.com/trailofbits/not-so-smart-contracts/blob/master/wrong_constructor_name/incorrect_constructor.sol 157 | * @author: Ben Perez 158 | * Modified by Gerhard Wagner 159 | */ 160 | 161 | pragma solidity ^0.4.24; 162 | 163 | contract Missing{ 164 | address private owner; 165 | 166 | modifier onlyowner { 167 | require(msg.sender==owner); 168 | _; 169 | } 170 | 171 | constructor() 172 | public 173 | { 174 | owner = msg.sender; 175 | } 176 | 177 | function () payable {} 178 | 179 | function withdraw() 180 | public 181 | onlyowner 182 | { 183 | owner.transfer(this.balance); 184 | } 185 | 186 | } 187 | 188 | ``` 189 | -------------------------------------------------------------------------------- /entries/docs/SWC-119.md: -------------------------------------------------------------------------------- 1 | # Please note, this content is no longer actively maintained. 2 | 3 | The content of the SWC registry has not been thoroughly updated since 2020. It is known to be incomplete and may contain errors as well as crucial omissions. 4 | 5 | For currently maintained guidance on known Smart Contract vulnerabilities written primarily as guidance for security reviewers, please see the 6 | [EEA EthTrust Security Levels specification](https://entethalliance.org/specs/ethtrust-sl). As well as the latest release version, an 7 | [Editor's draft](https://entethalliance.github.io/eta-registry/security-levels-spec.html) is available, 8 | that represents the latest work of the group developing the specification. 9 | 10 | General guidance for developers on what to consider to ensure security, that is currently maintained, is also available through the 11 | [Smart Contract Security Verification Standard (SCSVS)](https://github.com/ComposableSecurity/SCSVS). 12 | 13 | # Title 14 | 15 | Shadowing State Variables 16 | 17 | ## Relationships 18 | 19 | - [CWE-710: Improper Adherence to Coding Standards](http://cwe.mitre.org/data/definitions/710.html) 20 | - EthTrust Security Levels: 21 | - [**[Q] Implement as Documented**](https://entethalliance.org/specs/ethtrust-sl/#req-3-implement-as-documented) 22 | 23 | ## Description 24 | 25 | Solidity allows for ambiguous naming of state variables when inheritance is used. Contract `A` with a variable `x` could inherit contract `B` that also has a state variable `x` defined. This would result in two separate versions of `x`, one of them being accessed from contract `A` and the other one from contract `B`. In more complex contract systems this condition could go unnoticed and subsequently lead to security issues. 26 | 27 | Shadowing state variables can also occur within a single contract when there are multiple definitions on the contract and function level. 28 | 29 | ## Remediation 30 | 31 | Review storage variable layouts for your contract systems carefully and remove any ambiguities. Always check for compiler warnings as they can flag the issue within a single contract. 32 | 33 | ## References 34 | 35 | - [Issue on Solidity's Github - Shadowing of inherited state variables should be an error (override keyword)](https://github.com/ethereum/solidity/issues/2563) 36 | - [Issue on Solidity's Github - Warn about shadowing state variables](https://github.com/ethereum/solidity/issues/973) 37 | 38 | EthTrust Security Levels: 39 | - [**[Q] Implement as Documented**](https://entethalliance.org/specs/ethtrust-sl/#req-3-implement-as-documented) 40 | 41 | ## Samples 42 | 43 | ### ShadowingInFunctions.sol 44 | 45 | ```solidity 46 | pragma solidity 0.4.24; 47 | 48 | contract ShadowingInFunctions { 49 | uint n = 2; 50 | uint x = 3; 51 | 52 | function test1() constant returns (uint n) { 53 | return n; // Will return 0 54 | } 55 | 56 | function test2() constant returns (uint n) { 57 | n = 1; 58 | return n; // Will return 1 59 | } 60 | 61 | function test3() constant returns (uint x) { 62 | uint n = 4; 63 | return n+x; // Will return 4 64 | } 65 | } 66 | 67 | ``` 68 | 69 | ### TokenSale.sol 70 | 71 | ```solidity 72 | pragma solidity 0.4.24; 73 | 74 | contract Tokensale { 75 | uint hardcap = 10000 ether; 76 | 77 | function Tokensale() {} 78 | 79 | function fetchCap() public constant returns(uint) { 80 | return hardcap; 81 | } 82 | } 83 | 84 | contract Presale is Tokensale { 85 | uint hardcap = 1000 ether; 86 | 87 | function Presale() Tokensale() {} 88 | } 89 | 90 | ``` 91 | 92 | ### TokenSale_fixed.sol 93 | 94 | ```solidity 95 | pragma solidity 0.4.25; 96 | 97 | //We fix the problem by eliminating the declaration which overrides the prefered hardcap. 98 | 99 | contract Tokensale { 100 | uint public hardcap = 10000 ether; 101 | 102 | function Tokensale() {} 103 | 104 | function fetchCap() public constant returns(uint) { 105 | return hardcap; 106 | } 107 | } 108 | 109 | contract Presale is Tokensale { 110 | //uint hardcap = 1000 ether; 111 | //If the hardcap variables were both needed we would have to rename one to fix this. 112 | function Presale() Tokensale() { 113 | hardcap = 1000 ether; //We set the hardcap from the constructor for the Tokensale to be 1000 instead of 10000 114 | } 115 | } 116 | 117 | ``` 118 | -------------------------------------------------------------------------------- /entries/docs/SWC-120.md: -------------------------------------------------------------------------------- 1 | # Please note, this content is no longer actively maintained. 2 | 3 | The content of the SWC registry has not been thoroughly updated since 2020. It is known to be incomplete and may contain errors as well as crucial omissions. 4 | 5 | For currently maintained guidance on known Smart Contract vulnerabilities written primarily as guidance for security reviewers, please see the 6 | [EEA EthTrust Security Levels specification](https://entethalliance.org/specs/ethtrust-sl). As well as the latest release version, an 7 | [Editor's draft](https://entethalliance.github.io/eta-registry/security-levels-spec.html) is available, 8 | that represents the latest work of the group developing the specification. 9 | 10 | General guidance for developers on what to consider to ensure security, that is currently maintained, is also available through the 11 | [Smart Contract Security Verification Standard (SCSVS)](https://github.com/ComposableSecurity/SCSVS). 12 | 13 | # Title 14 | 15 | Weak Sources of Randomness from Chain Attributes 16 | 17 | ## Relationships 18 | 19 | - [CWE-330: Use of Insufficiently Random Values](https://cwe.mitre.org/data/definitions/330.html) 20 | - EthTrust Security Levels: 21 | - [**[M] Sources of Randomness**](https://entethalliance.org/specs/ethtrust-sl/#req-2-random-enough) 22 | - [**[M] Document Special Code Use**](https://entethalliance.org/specs/ethtrust-sl/#req-2-documented) 23 | 24 | 25 | ## Description 26 | 27 | Ability to generate random numbers is very helpful in all kinds of applications. One obvious example is gambling DApps, where pseudo-random number generator is used to pick the winner. However, creating a strong enough source of randomness in Ethereum is very challenging. For example, use of `block.timestamp` is insecure, as a miner can choose to provide any timestamp within a few seconds and still get his block accepted by others. Use of `blockhash`, `block.difficulty` and other fields is also insecure, as they're controlled by the miner. If the stakes are high, the miner can mine lots of blocks in a short time by renting hardware, pick the block that has required block hash for him to win, and drop all others. 28 | 29 | ## Remediation 30 | 31 | - Using external sources of randomness via oracles, and cryptographically checking the outcome of the oracle on-chain. e.g. [Chainlink VRF](https://docs.chain.link/docs/chainlink-vrf). This approach does not rely on trusting the oracle, as a falsly generated random number will be rejected by the on-chain portion of the system. 32 | - Using [commitment scheme](https://en.wikipedia.org/wiki/Commitment_scheme), e.g. [RANDAO](https://github.com/randao/randao). 33 | - Using external sources of randomness via oracles, e.g. [Oraclize](http://www.oraclize.it/). Note that this approach requires trusting in oracle, thus it may be reasonable to use multiple oracles. 34 | - Using Bitcoin block hashes, as they are more expensive to mine. 35 | 36 | ## References 37 | 38 | - [How can I securely generate a random number in my smart contract?](https://ethereum.stackexchange.com/questions/191/how-can-i-securely-generate-a-random-number-in-my-smart-contract) 39 | - [When can BLOCKHASH be safely used for a random number? When would it be unsafe?](https://ethereum.stackexchange.com/questions/419/when-can-blockhash-be-safely-used-for-a-random-number-when-would-it-be-unsafe) 40 | - [The Run smart contract](https://etherscan.io/address/0xcac337492149bdb66b088bf5914bedfbf78ccc18) 41 | 42 | ## Samples 43 | 44 | ### guess_the_random_number.sol 45 | 46 | ```solidity 47 | 48 | /* 49 | * @source: https://capturetheether.com/challenges/lotteries/guess-the-random-number/ 50 | * @author: Steve Marx 51 | */ 52 | 53 | pragma solidity ^0.4.21; 54 | 55 | contract GuessTheRandomNumberChallenge { 56 | uint8 answer; 57 | 58 | function GuessTheRandomNumberChallenge() public payable { 59 | require(msg.value == 1 ether); 60 | answer = uint8(keccak256(block.blockhash(block.number - 1), now)); 61 | } 62 | 63 | function isComplete() public view returns (bool) { 64 | return address(this).balance == 0; 65 | } 66 | 67 | function guess(uint8 n) public payable { 68 | require(msg.value == 1 ether); 69 | 70 | if (n == answer) { 71 | msg.sender.transfer(2 ether); 72 | } 73 | } 74 | } 75 | 76 | ``` 77 | 78 | ### guess_the_random_number_fixed.sol 79 | 80 | ```solidity 81 | /* 82 | * @source: https://capturetheether.com/challenges/lotteries/guess-the-random-number/ 83 | * @author: Steve Marx 84 | */ 85 | 86 | pragma solidity ^0.4.25; 87 | 88 | contract GuessTheRandomNumberChallenge { 89 | uint8 answer; 90 | uint8 commitedGuess; 91 | uint commitBlock; 92 | address guesser; 93 | 94 | function GuessTheRandomNumberChallenge() public payable { 95 | require(msg.value == 1 ether); 96 | } 97 | 98 | function isComplete() public view returns (bool) { 99 | return address(this).balance == 0; 100 | } 101 | 102 | //Guess the modulo of the blockhash 20 blocks from your guess 103 | function guess(uint8 _guess) public payable { 104 | require(msg.value == 1 ether); 105 | commitedGuess = _guess; 106 | commitBlock = block.number; 107 | guesser = msg.sender; 108 | } 109 | function recover() public { 110 | //This must be called after the guessed block and before commitBlock+20's blockhash is unrecoverable 111 | require(block.number > commitBlock + 20 && commitBlock+20 > block.number - 256); 112 | require(guesser == msg.sender); 113 | 114 | if(uint(blockhash(commitBlock+20)) == commitedGuess){ 115 | msg.sender.transfer(2 ether); 116 | } 117 | } 118 | } 119 | ``` 120 | 121 | ### old_blockhash.sol 122 | 123 | ```solidity 124 | pragma solidity ^0.4.24; 125 | 126 | //Based on the the Capture the Ether challange at https://capturetheether.com/challenges/lotteries/predict-the-block-hash/ 127 | //Note that while it seems to have a 1/2^256 chance you guess the right hash, actually blockhash returns zero for blocks numbers that are more than 256 blocks ago so you can guess zero and wait. 128 | contract PredictTheBlockHashChallenge { 129 | 130 | struct guess{ 131 | uint block; 132 | bytes32 guess; 133 | } 134 | 135 | mapping(address => guess) guesses; 136 | 137 | constructor() public payable { 138 | require(msg.value == 1 ether); 139 | } 140 | 141 | function lockInGuess(bytes32 hash) public payable { 142 | require(guesses[msg.sender].block == 0); 143 | require(msg.value == 1 ether); 144 | 145 | guesses[msg.sender].guess = hash; 146 | guesses[msg.sender].block = block.number + 1; 147 | } 148 | 149 | function settle() public { 150 | require(block.number > guesses[msg.sender].block); 151 | 152 | bytes32 answer = blockhash(guesses[msg.sender].block); 153 | 154 | guesses[msg.sender].block = 0; 155 | if (guesses[msg.sender].guess == answer) { 156 | msg.sender.transfer(2 ether); 157 | } 158 | } 159 | } 160 | 161 | ``` 162 | 163 | ### old_blockhash_fixed.sol 164 | 165 | ```solidity 166 | pragma solidity ^0.4.24; 167 | 168 | //Based on the the Capture the Ether challange at https://capturetheether.com/challenges/lotteries/predict-the-block-hash/ 169 | //Note that while it seems to have a 1/2^256 chance you guess the right hash, actually blockhash returns zero for blocks numbers that are more than 256 blocks ago so you can guess zero and wait. 170 | contract PredictTheBlockHashChallenge { 171 | 172 | struct guess{ 173 | uint block; 174 | bytes32 guess; 175 | } 176 | 177 | mapping(address => guess) guesses; 178 | 179 | constructor() public payable { 180 | require(msg.value == 1 ether); 181 | } 182 | 183 | function lockInGuess(bytes32 hash) public payable { 184 | require(guesses[msg.sender].block == 0); 185 | require(msg.value == 1 ether); 186 | 187 | guesses[msg.sender].guess = hash; 188 | guesses[msg.sender].block = block.number + 1; 189 | } 190 | 191 | function settle() public { 192 | require(block.number > guesses[msg.sender].block +10); 193 | //Note that this solution prevents the attack where blockhash(guesses[msg.sender].block) is zero 194 | //Also we add ten block cooldown period so that a minner cannot use foreknowlege of next blockhashes 195 | if(guesses[msg.sender].block - block.number < 256){ 196 | bytes32 answer = blockhash(guesses[msg.sender].block); 197 | 198 | guesses[msg.sender].block = 0; 199 | if (guesses[msg.sender].guess == answer) { 200 | msg.sender.transfer(2 ether); 201 | } 202 | } 203 | else{ 204 | revert("Sorry your lottery ticket has expired"); 205 | } 206 | } 207 | } 208 | 209 | ``` 210 | 211 | ### random_number_generator.sol 212 | 213 | ```solidity 214 | pragma solidity ^0.4.25; 215 | 216 | // Based on TheRun contract deployed at 0xcac337492149bDB66b088bf5914beDfBf78cCC18. 217 | contract RandomNumberGenerator { 218 | uint256 private salt = block.timestamp; 219 | 220 | function random(uint max) view private returns (uint256 result) { 221 | // Get the best seed for randomness 222 | uint256 x = salt * 100 / max; 223 | uint256 y = salt * block.number / (salt % 5); 224 | uint256 seed = block.number / 3 + (salt % 300) + y; 225 | uint256 h = uint256(blockhash(seed)); 226 | // Random number between 1 and max 227 | return uint256((h / x)) % max + 1; 228 | } 229 | } 230 | 231 | ``` 232 | -------------------------------------------------------------------------------- /entries/docs/SWC-121.md: -------------------------------------------------------------------------------- 1 | # Please note, this content is no longer actively maintained. 2 | 3 | The content of the SWC registry has not been thoroughly updated since 2020. It is known to be incomplete and may contain errors as well as crucial omissions. 4 | 5 | For currently maintained guidance on known Smart Contract vulnerabilities written primarily as guidance for security reviewers, please see the 6 | [EEA EthTrust Security Levels specification](https://entethalliance.org/specs/ethtrust-sl). As well as the latest release version, an 7 | [Editor's draft](https://entethalliance.github.io/eta-registry/security-levels-spec.html) is available, 8 | that represents the latest work of the group developing the specification. 9 | 10 | General guidance for developers on what to consider to ensure security, that is currently maintained, is also available through the 11 | [Smart Contract Security Verification Standard (SCSVS)](https://github.com/ComposableSecurity/SCSVS). 12 | 13 | # Title 14 | 15 | Missing Protection against Signature Replay Attacks 16 | 17 | ## Relationships 18 | 19 | [CWE-347: Improper Verification of Cryptographic Signature](https://cwe.mitre.org/data/definitions/347.html) 20 | 21 | ## Description 22 | 23 | It is sometimes necessary to perform signature verification in smart contracts to achieve better usability or to save gas cost. A secure implementation needs to protect against Signature Replay Attacks by for example keeping track of all processed message hashes and only allowing new message hashes to be processed. A malicious user could attack a contract without such a control and get message hash that was sent by another user processed multiple times. 24 | 25 | ## Remediation 26 | 27 | In order to protect against signature replay attacks consider the following recommendations: 28 | 29 | - Store every message hash that has been processed by the smart contract. When new messages are received check against the already existing ones and only proceed with the business logic if it's a new message hash. 30 | - Include the address of the contract that processes the message. This ensures that the message can only be used in a single contract. 31 | - Under no circumstances generate the message hash including the signature. The `ecrecover` function is susceptible to signature malleability (see also SWC-117). 32 | 33 | ## References 34 | 35 | - [Medium - Replay Attack Vulnerability in Ethereum Smart Contracts Introduced by transferProxy()](https://medium.com/cypher-core/replay-attack-vulnerability-in-ethereum-smart-contracts-introduced-by-transferproxy-124bf3694e25) 36 | -------------------------------------------------------------------------------- /entries/docs/SWC-122.md: -------------------------------------------------------------------------------- 1 | # Please note, this content is no longer actively maintained. 2 | 3 | The content of the SWC registry has not been thoroughly updated since 2020. It is known to be incomplete and may contain errors as well as crucial omissions. 4 | 5 | For currently maintained guidance on known Smart Contract vulnerabilities written primarily as guidance for security reviewers, please see the 6 | [EEA EthTrust Security Levels specification](https://entethalliance.org/specs/ethtrust-sl). As well as the latest release version, an 7 | [Editor's draft](https://entethalliance.github.io/eta-registry/security-levels-spec.html) is available, 8 | that represents the latest work of the group developing the specification. 9 | 10 | General guidance for developers on what to consider to ensure security, that is currently maintained, is also available through the 11 | [Smart Contract Security Verification Standard (SCSVS)](https://github.com/ComposableSecurity/SCSVS). 12 | 13 | # Title 14 | 15 | Lack of Proper Signature Verification 16 | 17 | ## Relationships 18 | 19 | [CWE-345: Insufficient Verification of Data Authenticity](https://cwe.mitre.org/data/definitions/345.html) 20 | 21 | ## Description 22 | 23 | It is a common pattern for smart contract systems to allow users to sign messages off-chain instead of directly requesting users to do an on-chain transaction because of the flexibility and increased transferability that this provides. Smart contract systems that process signed messages have to implement their own logic to recover the authenticity from the signed messages before they process them further. A limitation for such systems is that smart contracts can not directly interact with them because they can not sign messages. Some signature verification implementations attempt to solve this problem by assuming the validity of a signed message based on other methods that do not have this limitation. An example of such a method is to rely on `msg.sender` and assume that if a signed message originated from the sender address then it has also been created by the sender address. This can lead to vulnerabilities especially in scenarios where proxies can be used to relay transactions. 24 | 25 | ## Remediation 26 | 27 | It is not recommended to use alternate verification schemes that do not require proper signature verification through `ecrecover()`. 28 | 29 | ## References 30 | 31 | - [Consensys Diligence 0x Audit Report - Insecure signature validator](https://github.com/ConsenSys/0x_audit_report_2018-07-23#32-mixinsignaturevalidator-insecure-signature-validator-signaturetypecaller) 32 | -------------------------------------------------------------------------------- /entries/docs/SWC-123.md: -------------------------------------------------------------------------------- 1 | # Please note, this content is no longer actively maintained. 2 | 3 | The content of the SWC registry has not been thoroughly updated since 2020. It is known to be incomplete and may contain errors as well as crucial omissions. 4 | 5 | For currently maintained guidance on known Smart Contract vulnerabilities written primarily as guidance for security reviewers, please see the 6 | [EEA EthTrust Security Levels specification](https://entethalliance.org/specs/ethtrust-sl). As well as the latest release version, an 7 | [Editor's draft](https://entethalliance.github.io/eta-registry/security-levels-spec.html) is available, 8 | that represents the latest work of the group developing the specification. 9 | 10 | General guidance for developers on what to consider to ensure security, that is currently maintained, is also available through the 11 | [Smart Contract Security Verification Standard (SCSVS)](https://github.com/ComposableSecurity/SCSVS). 12 | 13 | # Title 14 | 15 | Requirement Violation 16 | 17 | ## Relationships 18 | 19 | [CWE-573: Improper Following of Specification by Caller](https://cwe.mitre.org/data/definitions/573.html) 20 | 21 | ## Description 22 | 23 | The Solidity `require()` construct is meant to validate external inputs of a function. In most cases, such external inputs are provided by callers, but they may also be returned by callees. In the former case, we refer to them as precondition violations. Violations of a requirement can indicate one of two possible issues: 24 | 25 | 1. A bug exists in the contract that provided the external input. 26 | 1. The condition used to express the requirement is too strong. 27 | 28 | ## Remediation 29 | 30 | If the required logical condition is too strong, it should be weakened to allow all valid external inputs. 31 | 32 | Otherwise, the bug must be in the contract that provided the external input and one should consider fixing its code by making sure no invalid inputs are provided. 33 | 34 | ## References 35 | 36 | - [The use of revert(), assert(), and require() in Solidity, and the new REVERT opcode in the EVM](https://media.consensys.net/when-to-use-revert-assert-and-require-in-solidity-61fb2c0e5a57) 37 | 38 | ## Samples 39 | 40 | ### requirement_simple.sol 41 | 42 | ```solidity 43 | pragma solidity ^0.4.25; 44 | 45 | contract Bar { 46 | Foo private f = new Foo(); 47 | function doubleBaz() public view returns (int256) { 48 | return 2 * f.baz(0); 49 | } 50 | } 51 | 52 | contract Foo { 53 | function baz(int256 x) public pure returns (int256) { 54 | require(0 < x); 55 | return 42; 56 | } 57 | } 58 | 59 | ``` 60 | 61 | ### requirement_simple_fixed.sol 62 | 63 | ```solidity 64 | pragma solidity ^0.4.25; 65 | 66 | contract Bar { 67 | Foo private f = new Foo(); 68 | function doubleBaz() public view returns (int256) { 69 | return 2 * f.baz(1); //Changes the external contract to not hit the overly strong requirement. 70 | } 71 | } 72 | 73 | contract Foo { 74 | function baz(int256 x) public pure returns (int256) { 75 | require(0 < x); //You can also fix the contract by changing the input to the uint type and removing the require 76 | return 42; 77 | } 78 | } 79 | 80 | ``` 81 | -------------------------------------------------------------------------------- /entries/docs/SWC-124.md: -------------------------------------------------------------------------------- 1 | # Please note, this content is no longer actively maintained. 2 | 3 | The content of the SWC registry has not been thoroughly updated since 2020. It is known to be incomplete and may contain errors as well as crucial omissions. 4 | 5 | For currently maintained guidance on known Smart Contract vulnerabilities written primarily as guidance for security reviewers, please see the 6 | [EEA EthTrust Security Levels specification](https://entethalliance.org/specs/ethtrust-sl). As well as the latest release version, an 7 | [Editor's draft](https://entethalliance.github.io/eta-registry/security-levels-spec.html) is available, 8 | that represents the latest work of the group developing the specification. 9 | 10 | General guidance for developers on what to consider to ensure security, that is currently maintained, is also available through the 11 | [Smart Contract Security Verification Standard (SCSVS)](https://github.com/ComposableSecurity/SCSVS). 12 | 13 | # Title 14 | 15 | Write to Arbitrary Storage Location 16 | 17 | ## Relationships 18 | 19 | [CWE-123: Write-what-where Condition](https://cwe.mitre.org/data/definitions/123.html) 20 | 21 | ## Description 22 | 23 | A smart contract's data (e.g., storing the owner of the contract) is persistently stored 24 | at some storage location (i.e., a key or address) on the EVM level. The contract is 25 | responsible for ensuring that only authorized user or contract accounts may write to 26 | sensitive storage locations. If an attacker is able to write to arbitrary storage 27 | locations of a contract, the authorization checks may easily be circumvented. This can 28 | allow an attacker to corrupt the storage; for instance, by overwriting a field that stores 29 | the address of the contract owner. 30 | 31 | ## Remediation 32 | 33 | As a general advice, given that all data structures share the same storage (address) 34 | space, one should make sure that writes to one data structure cannot inadvertently 35 | overwrite entries of another data structure. 36 | 37 | ## References 38 | 39 | - [Entry to Underhanded Solidity Coding Contest 2017 (honorable mention)](https://github.com/Arachnid/uscc/tree/master/submissions-2017/doughoyte) 40 | 41 | ## Samples 42 | 43 | ### arbitrary_location_write_simple.sol 44 | 45 | ```solidity 46 | pragma solidity ^0.4.25; 47 | 48 | contract Wallet { 49 | uint[] private bonusCodes; 50 | address private owner; 51 | 52 | constructor() public { 53 | bonusCodes = new uint[](0); 54 | owner = msg.sender; 55 | } 56 | 57 | function () public payable { 58 | } 59 | 60 | function PushBonusCode(uint c) public { 61 | bonusCodes.push(c); 62 | } 63 | 64 | function PopBonusCode() public { 65 | require(0 <= bonusCodes.length); 66 | bonusCodes.length--; 67 | } 68 | 69 | function UpdateBonusCodeAt(uint idx, uint c) public { 70 | require(idx < bonusCodes.length); 71 | bonusCodes[idx] = c; 72 | } 73 | 74 | function Destroy() public { 75 | require(msg.sender == owner); 76 | selfdestruct(msg.sender); 77 | } 78 | } 79 | 80 | ``` 81 | 82 | ### arbitrary_location_write_simple_fixed.sol 83 | 84 | ```solidity 85 | pragma solidity ^0.4.25; 86 | 87 | contract Wallet { 88 | uint[] private bonusCodes; 89 | address private owner; 90 | 91 | constructor() public { 92 | bonusCodes = new uint[](0); 93 | owner = msg.sender; 94 | } 95 | 96 | function () public payable { 97 | } 98 | 99 | function PushBonusCode(uint c) public { 100 | bonusCodes.push(c); 101 | } 102 | 103 | function PopBonusCode() public { 104 | require(0 < bonusCodes.length); 105 | bonusCodes.length--; 106 | } 107 | 108 | function UpdateBonusCodeAt(uint idx, uint c) public { 109 | require(idx < bonusCodes.length); //Since you now have to push very codes this is no longer an arbitray write. 110 | bonusCodes[idx] = c; 111 | } 112 | 113 | function Destroy() public { 114 | require(msg.sender == owner); 115 | selfdestruct(msg.sender); 116 | } 117 | } 118 | 119 | ``` 120 | 121 | ### mapping_write.sol 122 | 123 | ```solidity 124 | pragma solidity ^0.4.24; 125 | 126 | //This code is derived from the Capture the Ether https://capturetheether.com/challenges/math/mapping/ 127 | 128 | contract Map { 129 | address public owner; 130 | uint256[] map; 131 | 132 | function set(uint256 key, uint256 value) public { 133 | if (map.length <= key) { 134 | map.length = key + 1; 135 | } 136 | 137 | map[key] = value; 138 | } 139 | 140 | function get(uint256 key) public view returns (uint256) { 141 | return map[key]; 142 | } 143 | function withdraw() public{ 144 | require(msg.sender == owner); 145 | msg.sender.transfer(address(this).balance); 146 | } 147 | } 148 | 149 | ``` 150 | -------------------------------------------------------------------------------- /entries/docs/SWC-126.md: -------------------------------------------------------------------------------- 1 | # Please note, this content is no longer actively maintained. 2 | 3 | The content of the SWC registry has not been thoroughly updated since 2020. It is known to be incomplete and may contain errors as well as crucial omissions. 4 | 5 | For currently maintained guidance on known Smart Contract vulnerabilities written primarily as guidance for security reviewers, please see the 6 | [EEA EthTrust Security Levels specification](https://entethalliance.org/specs/ethtrust-sl). As well as the latest release version, an 7 | [Editor's draft](https://entethalliance.github.io/eta-registry/security-levels-spec.html) is available, 8 | that represents the latest work of the group developing the specification. 9 | 10 | General guidance for developers on what to consider to ensure security, that is currently maintained, is also available through the 11 | [Smart Contract Security Verification Standard (SCSVS)](https://github.com/ComposableSecurity/SCSVS). 12 | 13 | # Title 14 | 15 | Insufficient Gas Griefing 16 | 17 | ## Relationships 18 | 19 | - [CWE-691: Insufficient Control Flow Management](https://cwe.mitre.org/data/definitions/691.html) 20 | - EEA EthTrust Security Levels: 21 | - [**[Q] Manage Gas Usage Increases**](https://entethalliance.github.io/eta-registry/security-levels-spec.html#req-3-enough-gas) 22 | - [**[Q] Protect Gas Usage**](https://entethalliance.github.io/eta-registry/security-levels-spec.html#req-3-protect-gas) 23 | 24 | ## Description 25 | 26 | Insufficient gas griefing attacks can be performed on contracts which accept data and use it in a sub-call on another contract. If the sub-call fails, either the whole transaction is reverted, or execution is continued. In the case of a relayer contract, the user who executes the transaction, the 'forwarder', can effectively censor transactions by using just enough gas to execute the transaction, but not enough for the sub-call to succeed. 27 | 28 | ## Remediation 29 | 30 | There are two options to prevent insufficient gas griefing: 31 | 32 | - Only allow trusted users to relay transactions. 33 | - Require that the forwarder provides enough gas. 34 | 35 | ## References 36 | 37 | - [Consensys Smart Contract Best Practices](https://consensys.github.io/smart-contract-best-practices/attacks/griefing/) 38 | - [What does griefing mean?](https://ethereum.stackexchange.com/questions/62829/what-does-griefing-mean) 39 | - [Griefing Attacks: Are they profitable for the attacker?](https://ethereum.stackexchange.com/questions/73261/griefing-attacks-are-they-profitable-for-the-attacker) 40 | 41 | ## Samples 42 | 43 | ### relayer.sol 44 | 45 | ```solidity 46 | /* 47 | * @source: https://consensys.github.io/smart-contract-best-practices/known_attacks/#insufficient-gas-griefing 48 | * @author: ConsenSys Diligence 49 | * Modified by Kaden Zipfel 50 | */ 51 | 52 | pragma solidity ^0.5.0; 53 | 54 | contract Relayer { 55 | uint transactionId; 56 | 57 | struct Tx { 58 | bytes data; 59 | bool executed; 60 | } 61 | 62 | mapping (uint => Tx) transactions; 63 | 64 | function relay(Target target, bytes memory _data) public returns(bool) { 65 | // replay protection; do not call the same transaction twice 66 | require(transactions[transactionId].executed == false, 'same transaction twice'); 67 | transactions[transactionId].data = _data; 68 | transactions[transactionId].executed = true; 69 | transactionId += 1; 70 | 71 | (bool success, ) = address(target).call(abi.encodeWithSignature("execute(bytes)", _data)); 72 | return success; 73 | } 74 | } 75 | 76 | // Contract called by Relayer 77 | contract Target { 78 | function execute(bytes memory _data) public { 79 | // Execute contract code 80 | } 81 | } 82 | 83 | ``` 84 | 85 | ### relayer_fixed.sol 86 | 87 | ```solidity 88 | /* 89 | * @source: https://consensys.github.io/smart-contract-best-practices/known_attacks/#insufficient-gas-griefing 90 | * @author: ConsenSys Diligence 91 | * Modified by Kaden Zipfel 92 | */ 93 | 94 | pragma solidity ^0.5.0; 95 | 96 | contract Relayer { 97 | uint transactionId; 98 | 99 | struct Tx { 100 | bytes data; 101 | bool executed; 102 | } 103 | 104 | mapping (uint => Tx) transactions; 105 | 106 | function relay(Target target, bytes memory _data, uint _gasLimit) public { 107 | // replay protection; do not call the same transaction twice 108 | require(transactions[transactionId].executed == false, 'same transaction twice'); 109 | transactions[transactionId].data = _data; 110 | transactions[transactionId].executed = true; 111 | transactionId += 1; 112 | 113 | address(target).call(abi.encodeWithSignature("execute(bytes)", _data, _gasLimit)); 114 | } 115 | } 116 | 117 | // Contract called by Relayer 118 | contract Target { 119 | function execute(bytes memory _data, uint _gasLimit) public { 120 | require(gasleft() >= _gasLimit, 'not enough gas'); 121 | // Execute contract code 122 | } 123 | } 124 | 125 | ``` 126 | -------------------------------------------------------------------------------- /entries/docs/SWC-127.md: -------------------------------------------------------------------------------- 1 | # Please note, this content is no longer actively maintained. 2 | 3 | The content of the SWC registry has not been thoroughly updated since 2020. It is known to be incomplete and may contain errors as well as crucial omissions. 4 | 5 | For currently maintained guidance on known Smart Contract vulnerabilities written primarily as guidance for security reviewers, please see the 6 | [EEA EthTrust Security Levels specification](https://entethalliance.org/specs/ethtrust-sl). As well as the latest release version, an 7 | [Editor's draft](https://entethalliance.github.io/eta-registry/security-levels-spec.html) is available, 8 | that represents the latest work of the group developing the specification. 9 | 10 | General guidance for developers on what to consider to ensure security, that is currently maintained, is also available through the 11 | [Smart Contract Security Verification Standard (SCSVS)](https://github.com/ComposableSecurity/SCSVS). 12 | 13 | # Title 14 | 15 | Arbitrary Jump with Function Type Variable 16 | 17 | ## Relationships 18 | 19 | - [CWE-695: Use of Low-Level Functionality](https://cwe.mitre.org/data/definitions/695.html) 20 | - EEA EthTrust Security Levels: 21 | - [**[S] No `assembly {}`**](https://entethalliance.github.io/eta-registry/security-levels-spec.html#req-1-no-assembly) 22 | - [**[M] Avoid Common `assembly {}` Attack Vectors**](https://entethalliance.github.io/eta-registry/security-levels-spec.html#req-2-safe-assembly) 23 | 24 | ## Description 25 | 26 | Solidity supports function types. That is, a variable of function type can be assigned with a reference to a function with a matching signature. The function saved to such variable can be called just like a regular function. 27 | 28 | The problem arises when a user has the ability to arbitrarily change the function type variable and thus execute random code instructions. As Solidity doesn't support pointer arithmetics, it's impossible to change such variable to an arbitrary value. However, if the developer uses assembly instructions, such as `mstore` or assign operator, in the worst case scenario an attacker is able to point a function type variable to any code instruction, violating required validations and required state changes. 29 | 30 | ## Remediation 31 | 32 | The use of assembly should be minimal. A developer should not allow a user to assign arbitrary values to function type variables. 33 | 34 | ## References 35 | 36 | - [Solidity CTF](https://medium.com/authio/solidity-ctf-part-2-safe-execution-ad6ded20e042) 37 | - [Solidity docs - Solidity Assembly](https://solidity.readthedocs.io/en/v0.4.25/assembly.html) 38 | - [Solidity docs - Function Types](https://solidity.readthedocs.io/en/v0.4.25/types.html#function-types) 39 | 40 | ## Samples 41 | 42 | ### FunctionTypes.sol 43 | 44 | ```solidity 45 | /* 46 | * @source: https://gist.github.com/wadeAlexC/7a18de852693b3f890560ab6a211a2b8 47 | * @author: Alexander Wade 48 | */ 49 | 50 | pragma solidity ^0.4.25; 51 | 52 | contract FunctionTypes { 53 | 54 | constructor() public payable { require(msg.value != 0); } 55 | 56 | function withdraw() private { 57 | require(msg.value == 0, 'dont send funds!'); 58 | address(msg.sender).transfer(address(this).balance); 59 | } 60 | 61 | function frwd() internal 62 | { withdraw(); } 63 | 64 | struct Func { function () internal f; } 65 | 66 | function breakIt() public payable { 67 | require(msg.value != 0, 'send funds!'); 68 | Func memory func; 69 | func.f = frwd; 70 | assembly { mstore(func, add(mload(func), callvalue)) } 71 | func.f(); 72 | } 73 | } 74 | 75 | ``` 76 | -------------------------------------------------------------------------------- /entries/docs/SWC-128.md: -------------------------------------------------------------------------------- 1 | # Please note, this content is no longer actively maintained. 2 | 3 | The content of the SWC registry has not been thoroughly updated since 2020. It is known to be incomplete and may contain errors as well as crucial omissions. 4 | 5 | For currently maintained guidance on known Smart Contract vulnerabilities written primarily as guidance for security reviewers, please see the 6 | [EEA EthTrust Security Levels specification](https://entethalliance.org/specs/ethtrust-sl). As well as the latest release version, an 7 | [Editor's draft](https://entethalliance.github.io/eta-registry/security-levels-spec.html) is available, 8 | that represents the latest work of the group developing the specification. 9 | 10 | General guidance for developers on what to consider to ensure security, that is currently maintained, is also available through the 11 | [Smart Contract Security Verification Standard (SCSVS)](https://github.com/ComposableSecurity/SCSVS). 12 | 13 | # Title 14 | 15 | DoS With Block Gas Limit 16 | 17 | ## Relationships 18 | 19 | - [CWE-400: Uncontrolled Resource Consumption](https://cwe.mitre.org/data/definitions/400.html) 20 | - EEA EthTrust Security Levels: 21 | - [**[Q] Manage Gas Usage Increases**](https://entethalliance.github.io/eta-registry/security-levels-spec.html#req-3-enough-gas) 22 | 23 | ## Description 24 | 25 | When smart contracts are deployed or functions inside them are called, the execution of these actions always requires a certain amount of gas, based of how much computation is needed to complete them. The Ethereum network specifies a block gas limit and the sum of all transactions included in a block can not exceed the threshold. 26 | 27 | Programming patterns that are harmless in centralized applications can lead to Denial of Service conditions in smart contracts when the cost of executing a function exceeds the block gas limit. Modifying an array of unknown size, that increases in size over time, can lead to such a Denial of Service condition. 28 | 29 | ## Remediation 30 | 31 | Caution is advised when you expect to have large arrays that grow over time. Actions that require looping across the entire data structure should be avoided. 32 | 33 | If you absolutely must loop over an array of unknown size, then you should plan for it to potentially take multiple blocks, and therefore require multiple transactions. 34 | 35 | ## References 36 | 37 | - [Ethereum Design Rationale](https://github.com/ethereum/wiki/wiki/Design-Rationale#gas-and-fees) 38 | - [Ethereum Yellow Paper](https://ethereum.github.io/yellowpaper/paper.pdf) 39 | - [Clear Large Array Without Blowing Gas Limit](https://ethereum.stackexchange.com/questions/3373/how-to-clear-large-arrays-without-blowing-the-gas-limit) 40 | - [GovernMental jackpot payout DoS Gas](https://www.reddit.com/r/ethereum/comments/4ghzhv/governmentals_1100_eth_jackpot_payout_is_stuck/) 41 | 42 | ## Samples 43 | 44 | ### dos_address.sol 45 | 46 | ```solidity 47 | pragma solidity ^0.4.25; 48 | 49 | contract DosGas { 50 | 51 | address[] creditorAddresses; 52 | bool win = false; 53 | 54 | function emptyCreditors() public { 55 | if(creditorAddresses.length>1500) { 56 | creditorAddresses = new address[](0); 57 | win = true; 58 | } 59 | } 60 | 61 | function addCreditors() public returns (bool) { 62 | for(uint i=0;i<350;i++) { 63 | creditorAddresses.push(msg.sender); 64 | } 65 | return true; 66 | } 67 | 68 | function iWin() public view returns (bool) { 69 | return win; 70 | } 71 | 72 | function numberCreditors() public view returns (uint) { 73 | return creditorAddresses.length; 74 | } 75 | } 76 | 77 | ``` 78 | 79 | ### dos_number.sol 80 | 81 | ```solidity 82 | pragma solidity ^0.4.25; 83 | 84 | contract DosNumber { 85 | 86 | uint numElements = 0; 87 | uint[] array; 88 | 89 | function insertNnumbers(uint value,uint numbers) public { 90 | 91 | // Gas DOS if number > 382 more or less, it depends on actual gas limit 92 | for(uint i=0;i1500); 102 | numElements = 0; 103 | } 104 | 105 | // Gas DOS clear 106 | function clearDOS() public { 107 | 108 | // number depends on actual gas limit 109 | require(numElements>1500); 110 | array = new uint[](0); 111 | numElements = 0; 112 | } 113 | 114 | function getLengthArray() public view returns(uint) { 115 | return numElements; 116 | } 117 | 118 | function getRealLengthArray() public view returns(uint) { 119 | return array.length; 120 | } 121 | } 122 | 123 | ``` 124 | 125 | ### dos_simple.sol 126 | 127 | ```solidity 128 | pragma solidity ^0.4.25; 129 | 130 | contract DosOneFunc { 131 | 132 | address[] listAddresses; 133 | 134 | function ifillArray() public returns (bool){ 135 | if(listAddresses.length<1500) { 136 | 137 | for(uint i=0;i<350;i++) { 138 | listAddresses.push(msg.sender); 139 | } 140 | return true; 141 | 142 | } else { 143 | listAddresses = new address[](0); 144 | return false; 145 | } 146 | } 147 | } 148 | 149 | ``` 150 | -------------------------------------------------------------------------------- /entries/docs/SWC-129.md: -------------------------------------------------------------------------------- 1 | # Please note, this content is no longer actively maintained. 2 | 3 | The content of the SWC registry has not been thoroughly updated since 2020. It is known to be incomplete and may contain errors as well as crucial omissions. 4 | 5 | For currently maintained guidance on known Smart Contract vulnerabilities written primarily as guidance for security reviewers, please see the 6 | [EEA EthTrust Security Levels specification](https://entethalliance.org/specs/ethtrust-sl). As well as the latest release version, an 7 | [Editor's draft](https://entethalliance.github.io/eta-registry/security-levels-spec.html) is available, 8 | that represents the latest work of the group developing the specification. 9 | 10 | General guidance for developers on what to consider to ensure security, that is currently maintained, is also available through the 11 | [Smart Contract Security Verification Standard (SCSVS)](https://github.com/ComposableSecurity/SCSVS). 12 | 13 | # Title 14 | 15 | Typographical Error 16 | 17 | ## Relationships 18 | 19 | - [CWE-480: Use of Incorrect Operator](https://cwe.mitre.org/data/definitions/480.html) 20 | - EEA EthTrust Security Levels: 21 | - [**[Q] Implement as Documented**](https://entethalliance.github.io/eta-registry/security-levels-spec.html#req-3-implement-as-documented) 22 | 23 | ## Description 24 | 25 | A typographical error can occur for example when the intent of a defined operation is to sum a number to a variable (+=) but it has accidentally been defined in a wrong way (=+), introducing a typo which happens to be a valid operator. Instead of calculating the sum it initializes the variable again. 26 | 27 | The unary + operator is deprecated in new solidity compiler versions. 28 | 29 | ## Remediation 30 | 31 | The weakness can be avoided by performing pre-condition checks on any math operation or using a vetted library for arithmetic calculations such as SafeMath developed by OpenZeppelin. 32 | 33 | ## References 34 | 35 | - [HackerGold Bug Analysis](https://blog.zeppelin.solutions/hackergold-bug-analysis-68d893cad738) 36 | - [SafeMath by OpenZeppelin](https://github.com/OpenZeppelin/openzeppelin-solidity/blob/master/contracts/math/SafeMath.sol) 37 | - [Disallow Unary plus](https://github.com/ethereum/solidity/issues/1760) 38 | 39 | ## Samples 40 | 41 | ### typo_one_command.sol 42 | 43 | ```solidity 44 | pragma solidity ^0.4.25; 45 | 46 | contract TypoOneCommand { 47 | uint numberOne = 1; 48 | 49 | function alwaysOne() public { 50 | numberOne =+ 1; 51 | } 52 | } 53 | 54 | ``` 55 | 56 | ### typo_safe_math.sol 57 | 58 | ```solidity 59 | pragma solidity ^0.4.25; 60 | 61 | /** Taken from the OpenZeppelin github 62 | * @title SafeMath 63 | * @dev Math operations with safety checks that revert on error 64 | */ 65 | library SafeMath { 66 | 67 | /** 68 | * @dev Multiplies two numbers, reverts on overflow. 69 | */ 70 | function mul(uint256 a, uint256 b) internal pure returns (uint256) { 71 | // Gas optimization: this is cheaper than requiring 'a' not being zero, but the 72 | // benefit is lost if 'b' is also tested. 73 | // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522 74 | if (a == 0) { 75 | return 0; 76 | } 77 | 78 | uint256 c = a * b; 79 | require(c / a == b); 80 | 81 | return c; 82 | } 83 | 84 | /** 85 | * @dev Integer division of two numbers truncating the quotient, reverts on division by zero. 86 | */ 87 | function div(uint256 a, uint256 b) internal pure returns (uint256) { 88 | require(b > 0); // Solidity only automatically asserts when dividing by 0 89 | uint256 c = a / b; 90 | // assert(a == b * c + a % b); // There is no case in which this doesn't hold 91 | 92 | return c; 93 | } 94 | 95 | /** 96 | * @dev Subtracts two numbers, reverts on overflow (i.e. if subtrahend is greater than minuend). 97 | */ 98 | function sub(uint256 a, uint256 b) internal pure returns (uint256) { 99 | require(b <= a); 100 | uint256 c = a - b; 101 | 102 | return c; 103 | } 104 | 105 | /** 106 | * @dev Adds two numbers, reverts on overflow. 107 | */ 108 | function add(uint256 a, uint256 b) internal pure returns (uint256) { 109 | uint256 c = a + b; 110 | require(c >= a); 111 | 112 | return c; 113 | } 114 | 115 | /** 116 | * @dev Divides two numbers and returns the remainder (unsigned integer modulo), 117 | * reverts when dividing by zero. 118 | */ 119 | function mod(uint256 a, uint256 b) internal pure returns (uint256) { 120 | require(b != 0); 121 | return a % b; 122 | } 123 | } 124 | 125 | 126 | contract TypoSafeMath { 127 | 128 | using SafeMath for uint256; 129 | uint256 public numberOne = 1; 130 | bool public win = false; 131 | 132 | function addOne() public { 133 | numberOne =+ 1; 134 | } 135 | 136 | function addOneCorrect() public { 137 | numberOne += 1; 138 | } 139 | 140 | function addOneSafeMath() public { 141 | numberOne = numberOne.add(1); 142 | } 143 | 144 | function iWin() public { 145 | if(!win && numberOne>3) { 146 | win = true; 147 | } 148 | } 149 | } 150 | 151 | ``` 152 | 153 | ### typo_simple.sol 154 | 155 | ```solidity 156 | pragma solidity ^0.4.25; 157 | 158 | contract TypoSimple { 159 | 160 | uint onlyOne = 1; 161 | bool win = false; 162 | 163 | function addOne() public { 164 | onlyOne =+ 1; 165 | if(onlyOne>1) { 166 | win = true; 167 | } 168 | } 169 | 170 | function iWin() view public returns (bool) { 171 | return win; 172 | } 173 | } 174 | 175 | ``` 176 | -------------------------------------------------------------------------------- /entries/docs/SWC-130.md: -------------------------------------------------------------------------------- 1 | # Please note, this content is no longer actively maintained. 2 | 3 | The content of the SWC registry has not been thoroughly updated since 2020. It is known to be incomplete and may contain errors as well as crucial omissions. 4 | 5 | For currently maintained guidance on known Smart Contract vulnerabilities written primarily as guidance for security reviewers, please see the 6 | [EEA EthTrust Security Levels specification](https://entethalliance.org/specs/ethtrust-sl). As well as the latest release version, an 7 | [Editor's draft](https://entethalliance.github.io/eta-registry/security-levels-spec.html) is available, that represents the latest work of the group developing the specification. 8 | 9 | General guidance for developers on what to consider to ensure security, that is currently maintained, is also available through the 10 | [Smart Contract Security Verification Standard (SCSVS)](https://github.com/ComposableSecurity/SCSVS). 11 | 12 | # Title 13 | 14 | Right-To-Left-Override control character (U+202E) 15 | 16 | ## Relationships 17 | 18 | - [CWE-451: User Interface (UI) Misrepresentation of Critical Information](http://cwe.mitre.org/data/definitions/451.html) 19 | - EEA EthTrust Security Levels specification: 20 | - [**[S] No Unicode Direction Control Characters**](https://entethalliance.org/specs/ethtrust-sl/#req-1-unicode-bdo) 21 | - [**[M] No Unnecessary Unicode Controls**](https://entethalliance.org/specs/ethtrust-sl/#req-2-unicode-bdo) 22 | - [**[M] No Homoglyph-style Attack**](https://entethalliance.org/specs/ethtrust-sl/#req-2-no-homoglyph-attack) 23 | 24 | ## Description 25 | 26 | Malicious actors can use the Right-To-Left-Override unicode character to force RTL text rendering and confuse users as to the real intent of a contract. 27 | 28 | ## Remediation 29 | 30 | There are very few legitimate uses of the U+202E character. It should not appear in the source code of a smart contract. 31 | 32 | ## References 33 | 34 | - [Outsmarting Smart Contracts](https://youtu.be/P_Mtd5Fc_3E?t=1813) 35 | 36 | 37 | ## Samples 38 | 39 | ### guess_the_number.sol 40 | 41 | ```solidity 42 | /* 43 | * @source: https://youtu.be/P_Mtd5Fc_3E 44 | * @author: Shahar Zini 45 | */ 46 | pragma solidity ^0.5.0; 47 | 48 | contract GuessTheNumber 49 | { 50 | uint _secretNumber; 51 | address payable _owner; 52 | event success(string); 53 | event wrongNumber(string); 54 | 55 | constructor(uint secretNumber) payable public 56 | { 57 | require(secretNumber <= 10); 58 | _secretNumber = secretNumber; 59 | _owner = msg.sender; 60 | } 61 | 62 | function getValue() view public returns (uint) 63 | { 64 | return address(this).balance; 65 | } 66 | 67 | function guess(uint n) payable public 68 | { 69 | require(msg.value == 1 ether); 70 | 71 | uint p = address(this).balance; 72 | checkAndTransferPrize(/*The prize‮/*rebmun desseug*/n , p/*‭ 73 | /*The user who should benefit */,msg.sender); 74 | } 75 | 76 | function checkAndTransferPrize(uint p, uint n, address payable guesser) internal returns(bool) 77 | { 78 | if(n == _secretNumber) 79 | { 80 | guesser.transfer(p); 81 | emit success("You guessed the correct number!"); 82 | } 83 | else 84 | { 85 | emit wrongNumber("You've made an incorrect guess!"); 86 | } 87 | } 88 | 89 | function kill() public 90 | { 91 | require(msg.sender == _owner); 92 | selfdestruct(_owner); 93 | } 94 | } 95 | ``` 96 | 97 | #### Comments 98 | 99 | The line 100 | 101 | ``` 102 | checkAndTransferPrize(/*The prize‮/*rebmun desseug*/n , p/* 103 | ``` 104 | 105 | inside the function `guess(uint n)` uses invisible direction control characters, so what is present on the screen misrepresents the order 106 | of the parameters - the function is called with parameters `n, p, address`, which is the **logical order** of characters, 107 | but some are displayed from right to left, so that the segment 'n, p' appears in reverse order to a reader, 108 | because invisible direction control characters are included in the code. 109 | 110 | Selecting the text character by character will usually show this - the selection suddenly jumps to the end of the right-to-left text, 111 | and starts to extend from the right hand side leftward. It is also possible to check for the unicode characters explicitly in the content. 112 | -------------------------------------------------------------------------------- /entries/docs/SWC-131.md: -------------------------------------------------------------------------------- 1 | # Please note, this content is no longer actively maintained. 2 | 3 | The content of the SWC registry has not been thoroughly updated since 2020. It is known to be incomplete and may contain errors as well as crucial omissions. 4 | 5 | For currently maintained guidance on known Smart Contract vulnerabilities written primarily as guidance for security reviewers, please see the 6 | [EEA EthTrust Security Levels specification](https://entethalliance.org/specs/ethtrust-sl). As well as the latest release version, an 7 | [Editor's draft](https://entethalliance.github.io/eta-registry/security-levels-spec.html) is available, that represents the latest work of the group developing the specification. 8 | 9 | General guidance for developers on what to consider to ensure security, that is currently maintained, is also available through the 10 | [Smart Contract Security Verification Standard (SCSVS)](https://github.com/ComposableSecurity/SCSVS). 11 | 12 | # Title 13 | 14 | Presence of unused variables 15 | 16 | ## Relationships 17 | 18 | - [CWE-1164: Irrelevant Code](https://cwe.mitre.org/data/definitions/1164.html) 19 | - EthTrust Security Levels: 20 | - [**[Q] Code Linting**](https://entethalliance.org/specs/ethtrust-sl/#req-3-linted) 21 | 22 | ## Description 23 | 24 | Unused variables are allowed in Solidity and they do not pose a direct security issue. It is best practice though to avoid them as they can: 25 | 26 | - cause an increase in computations (and unnecessary gas consumption) 27 | - indicate bugs or malformed data structures and they are generally a sign of poor code quality 28 | - cause code noise and decrease readability of the code 29 | 30 | ## Remediation 31 | 32 | Remove all unused variables from the code base. 33 | 34 | ## References 35 | 36 | - [Unused local variables warnings discussion](https://github.com/ethereum/solidity/issues/718) 37 | - [Shadowing of inherited state variables discussion](https://github.com/ethereum/solidity/issues/2563) 38 | 39 | ## Samples 40 | 41 | ### unused_state_variables.sol 42 | 43 | ```solidity 44 | pragma solidity >=0.5.0; 45 | pragma experimental ABIEncoderV2; 46 | 47 | import "./base.sol"; 48 | 49 | contract DerivedA is Base { 50 | // i is not used in the current contract 51 | A i = A(1); 52 | 53 | int internal j = 500; 54 | 55 | function call(int a) public { 56 | assign1(a); 57 | } 58 | 59 | function assign3(A memory x) public returns (uint) { 60 | return g[1] + x.a + uint(j); 61 | } 62 | 63 | function ret() public returns (int){ 64 | return this.e(); 65 | 66 | } 67 | 68 | } 69 | ``` 70 | 71 | ### unused_state_variables_fixed.sol 72 | 73 | ```solidity 74 | pragma solidity >=0.5.0; 75 | pragma experimental ABIEncoderV2; 76 | 77 | import "./base_fixed.sol"; 78 | 79 | contract DerivedA is Base { 80 | 81 | int internal j = 500; 82 | 83 | function call(int a) public { 84 | assign1(a); 85 | } 86 | 87 | function assign3(A memory x) public returns (uint) { 88 | return g[1] + x.a + uint(j); 89 | } 90 | 91 | function ret() public returns (int){ 92 | return this.e(); 93 | 94 | } 95 | 96 | } 97 | ``` 98 | 99 | ### unused_variables.sol 100 | 101 | ```solidity 102 | pragma solidity ^0.5.0; 103 | 104 | contract UnusedVariables { 105 | int a = 1; 106 | 107 | // y is not used 108 | function unusedArg(int x, int y) public view returns (int z) { 109 | z = x + a; 110 | } 111 | 112 | // n is not reported it is part of another SWC category 113 | function unusedReturn(int x, int y) public pure returns (int m, int n, int o) { 114 | m = y - x; 115 | o = m/2; 116 | } 117 | 118 | // x is not accessed 119 | function neverAccessed(int test) public pure returns (int) { 120 | int z = 10; 121 | 122 | if (test > z) { 123 | // x is not used 124 | int x = test - z; 125 | 126 | return test - z; 127 | } 128 | 129 | return z; 130 | } 131 | 132 | function tupleAssignment(int p) public returns (int q, int r){ 133 | (q, , r) = unusedReturn(p,2); 134 | 135 | } 136 | 137 | 138 | } 139 | 140 | ``` 141 | 142 | ### unused_variables_fixed.sol 143 | 144 | ```solidity 145 | pragma solidity ^0.5.0; 146 | 147 | contract UnusedVariables { 148 | int a = 1; 149 | 150 | function unusedArg(int x) public view returns (int z) { 151 | z = x + a; 152 | } 153 | 154 | // n is not reported it is part of another SWC category 155 | function unusedReturn(int x, int y) public pure returns (int m, int n,int o) { 156 | m = y - x; 157 | o = m/2; 158 | } 159 | 160 | // x is not accessed 161 | function neverAccessed(int test) public pure returns (int) { 162 | int z = 10; 163 | 164 | if (test > z) { 165 | return test - z; 166 | } 167 | 168 | return z; 169 | } 170 | 171 | function tupleAssignment(int p) public returns (int q, int r){ 172 | (q, , r) = unusedReturn(p,2); 173 | 174 | } 175 | 176 | } 177 | 178 | ``` 179 | -------------------------------------------------------------------------------- /entries/docs/SWC-132.md: -------------------------------------------------------------------------------- 1 | # Please note, this content is no longer actively maintained. 2 | 3 | The content of the SWC registry has not been thoroughly updated since 2020. It is known to be incomplete and may contain errors as well as crucial omissions. 4 | 5 | For currently maintained guidance on known Smart Contract vulnerabilities written primarily as guidance for security reviewers, please see the 6 | [EEA EthTrust Security Levels specification](https://entethalliance.org/specs/ethtrust-sl). As well as the latest release version, an 7 | [Editor's draft](https://entethalliance.github.io/eta-registry/security-levels-spec.html) is available, that represents the latest work of the group developing the specification. 8 | 9 | General guidance for developers on what to consider to ensure security, that is currently maintained, is also available through the 10 | [Smart Contract Security Verification Standard (SCSVS)](https://github.com/ComposableSecurity/SCSVS). 11 | 12 | # Title 13 | 14 | Unexpected Ether balance 15 | 16 | ## Relationships 17 | 18 | - [CWE-667: Improper Locking](https://cwe.mitre.org/data/definitions/667.html) 19 | - EEA EthTrust Security Levels: 20 | - [**[S] No Exact Balance Check**](https://entethalliance.org/specs/ethtrust-sl/#req-1-exact-balance-check) 21 | - [**[M] Verify Exact Balance Checks**](https://entethalliance.org/specs/ethtrust-sl/#req-1-verify-exact-balance-check) 22 | 23 | ## Description 24 | 25 | Contracts can behave erroneously when they strictly assume a specific Ether balance. It is always possible to forcibly send ether to a contract (without triggering its fallback function), using selfdestruct, or by mining to the account. In the worst case scenario this could lead to DOS conditions that might render the contract unusable. 26 | 27 | ## Remediation 28 | 29 | Avoid strict equality checks for the Ether balance in a contract. 30 | 31 | ## References 32 | 33 | - [Consensys Best Practices: Force Feeding](https://consensys.github.io/smart-contract-best-practices/attacks/force-feeding/) 34 | - [Sigmaprime: Unexpected Ether](https://blog.sigmaprime.io/solidity-security.html#ether) 35 | - [Gridlock (a smart contract bug)](https://medium.com/@nmcl/gridlock-a-smart-contract-bug-73b8310608a9) 36 | 37 | ## Samples 38 | 39 | ### Lockdrop.sol 40 | 41 | ```solidity 42 | /** 43 | * @source: https://github.com/hicommonwealth/edgeware-lockdrop/blob/93ecb524c9c88d25bab36278541f190fa9e910c2/contracts/Lockdrop.sol 44 | */ 45 | 46 | pragma solidity ^0.5.0; 47 | 48 | contract Lock { 49 | // address owner; slot #0 50 | // address unlockTime; slot #1 51 | constructor (address owner, uint256 unlockTime) public payable { 52 | assembly { 53 | sstore(0x00, owner) 54 | sstore(0x01, unlockTime) 55 | } 56 | } 57 | 58 | /** 59 | * @dev Withdraw function once timestamp has passed unlock time 60 | */ 61 | function () external payable { // payable so solidity doesn't add unnecessary logic 62 | assembly { 63 | switch gt(timestamp, sload(0x01)) 64 | case 0 { revert(0, 0) } 65 | case 1 { 66 | switch call(gas, sload(0x00), balance(address), 0, 0, 0, 0) 67 | case 0 { revert(0, 0) } 68 | } 69 | } 70 | } 71 | } 72 | 73 | contract Lockdrop { 74 | enum Term { 75 | ThreeMo, 76 | SixMo, 77 | TwelveMo 78 | } 79 | // Time constants 80 | uint256 constant public LOCK_DROP_PERIOD = 1 days * 92; // 3 months 81 | uint256 public LOCK_START_TIME; 82 | uint256 public LOCK_END_TIME; 83 | // ETH locking events 84 | event Locked(address indexed owner, uint256 eth, Lock lockAddr, Term term, bytes edgewareAddr, bool isValidator, uint time); 85 | event Signaled(address indexed contractAddr, bytes edgewareAddr, uint time); 86 | 87 | constructor(uint startTime) public { 88 | LOCK_START_TIME = startTime; 89 | LOCK_END_TIME = startTime + LOCK_DROP_PERIOD; 90 | } 91 | 92 | /** 93 | * @dev Locks up the value sent to contract in a new Lock 94 | * @param term The length of the lock up 95 | * @param edgewareAddr The bytes representation of the target edgeware key 96 | * @param isValidator Indicates if sender wishes to be a validator 97 | */ 98 | function lock(Term term, bytes calldata edgewareAddr, bool isValidator) 99 | external 100 | payable 101 | didStart 102 | didNotEnd 103 | { 104 | uint256 eth = msg.value; 105 | address owner = msg.sender; 106 | uint256 unlockTime = unlockTimeForTerm(term); 107 | // Create ETH lock contract 108 | Lock lockAddr = (new Lock).value(eth)(owner, unlockTime); 109 | // ensure lock contract has all ETH, or fail 110 | assert(address(lockAddr).balance == msg.value); 111 | emit Locked(owner, eth, lockAddr, term, edgewareAddr, isValidator, now); 112 | } 113 | 114 | /** 115 | * @dev Signals a contract's (or address's) balance decided after lock period 116 | * @param contractAddr The contract address from which to signal the balance of 117 | * @param nonce The transaction nonce of the creator of the contract 118 | * @param edgewareAddr The bytes representation of the target edgeware key 119 | */ 120 | function signal(address contractAddr, uint32 nonce, bytes calldata edgewareAddr) 121 | external 122 | didStart 123 | didNotEnd 124 | didCreate(contractAddr, msg.sender, nonce) 125 | { 126 | emit Signaled(contractAddr, edgewareAddr, now); 127 | } 128 | 129 | function unlockTimeForTerm(Term term) internal view returns (uint256) { 130 | if (term == Term.ThreeMo) return now + 92 days; 131 | if (term == Term.SixMo) return now + 183 days; 132 | if (term == Term.TwelveMo) return now + 365 days; 133 | 134 | revert(); 135 | } 136 | 137 | /** 138 | * @dev Ensures the lockdrop has started 139 | */ 140 | modifier didStart() { 141 | require(now >= LOCK_START_TIME); 142 | _; 143 | } 144 | 145 | /** 146 | * @dev Ensures the lockdrop has not ended 147 | */ 148 | modifier didNotEnd() { 149 | require(now <= LOCK_END_TIME); 150 | _; 151 | } 152 | 153 | /** 154 | * @dev Rebuilds the contract address from a normal address and transaction nonce 155 | * @param _origin The non-contract address derived from a user's public key 156 | * @param _nonce The transaction nonce from which to generate a contract address 157 | */ 158 | function addressFrom(address _origin, uint32 _nonce) public pure returns (address) { 159 | if(_nonce == 0x00) return address(uint160(uint256(keccak256(abi.encodePacked(byte(0xd6), byte(0x94), _origin, byte(0x80)))))); 160 | if(_nonce <= 0x7f) return address(uint160(uint256(keccak256(abi.encodePacked(byte(0xd6), byte(0x94), _origin, uint8(_nonce)))))); 161 | if(_nonce <= 0xff) return address(uint160(uint256(keccak256(abi.encodePacked(byte(0xd7), byte(0x94), _origin, byte(0x81), uint8(_nonce)))))); 162 | if(_nonce <= 0xffff) return address(uint160(uint256(keccak256(abi.encodePacked(byte(0xd8), byte(0x94), _origin, byte(0x82), uint16(_nonce)))))); 163 | if(_nonce <= 0xffffff) return address(uint160(uint256(keccak256(abi.encodePacked(byte(0xd9), byte(0x94), _origin, byte(0x83), uint24(_nonce)))))); 164 | return address(uint160(uint256(keccak256(abi.encodePacked(byte(0xda), byte(0x94), _origin, byte(0x84), uint32(_nonce)))))); // more than 2^32 nonces not realistic 165 | } 166 | 167 | /** 168 | * @dev Ensures the target address was created by a parent at some nonce 169 | * @param target The target contract address (or trivially the parent) 170 | * @param parent The creator of the alleged contract address 171 | * @param nonce The creator's tx nonce at the time of the contract creation 172 | */ 173 | modifier didCreate(address target, address parent, uint32 nonce) { 174 | // Trivially let senders "create" themselves 175 | if (target == parent) { 176 | _; 177 | } else { 178 | require(target == addressFrom(parent, nonce)); 179 | _; 180 | } 181 | } 182 | } 183 | ``` 184 | -------------------------------------------------------------------------------- /entries/docs/SWC-133.md: -------------------------------------------------------------------------------- 1 | # Please note, this content is no longer actively maintained. 2 | 3 | The content of the SWC registry has not been thoroughly updated since 2020. It is known to be incomplete and may contain errors as well as crucial omissions. 4 | 5 | For currently maintained guidance on known Smart Contract vulnerabilities written primarily as guidance for security reviewers, please see the 6 | [EEA EthTrust Security Levels specification](https://entethalliance.org/specs/ethtrust-sl). As well as the latest release version, an 7 | [Editor's draft](https://entethalliance.github.io/eta-registry/security-levels-spec.html) is available, that represents the latest work of the group developing the specification. 8 | 9 | General guidance for developers on what to consider to ensure security, that is currently maintained, is also available through the 10 | [Smart Contract Security Verification Standard (SCSVS)](https://github.com/ComposableSecurity/SCSVS). 11 | 12 | # Title 13 | 14 | Hash Collisions With Multiple Variable Length Arguments 15 | 16 | ## Relationships 17 | 18 | [CWE-294: Authentication Bypass by Capture-replay](https://cwe.mitre.org/data/definitions/294.html) 19 | 20 | ## Description 21 | 22 | Using `abi.encodePacked()` with multiple variable length arguments can, in certain situations, lead to a hash collision. Since `abi.encodePacked()` packs all elements in order regardless of whether they're part of an array, you can move elements between arrays and, so long as all elements are in the same order, it will return the same encoding. In a signature verification situation, an attacker could exploit this by modifying the position of elements in a previous function call to effectively bypass authorization. 23 | 24 | ## Remediation 25 | 26 | When using `abi.encodePacked()`, it's crucial to ensure that a matching signature cannot be achieved using different parameters. To do so, either do not allow users access to parameters used in `abi.encodePacked()`, or use fixed length arrays. Alternatively, you can simply use `abi.encode()` instead. 27 | 28 | It is also recommended that you use replay protection (see [SWC-121](./SWC-121.md)), although an attacker can still bypass this by [front-running](./SWC-114.md). 29 | 30 | ## References 31 | 32 | - [Solidity Non-standard Packed Mode](https://solidity.readthedocs.io/en/v0.5.3/abi-spec.html#non-standard-packed-mode) 33 | - [Hash Collision Attack](https://learncryptography.com/hash-functions/hash-collision-attack) 34 | 35 | ## Samples 36 | 37 | ### access_control.sol 38 | 39 | ```solidity 40 | /* 41 | * @author: Steve Marx 42 | */ 43 | 44 | pragma solidity ^0.5.0; 45 | 46 | import "./ECDSA.sol"; 47 | 48 | contract AccessControl { 49 | using ECDSA for bytes32; 50 | mapping(address => bool) isAdmin; 51 | mapping(address => bool) isRegularUser; 52 | // Add admins and regular users. 53 | function addUsers( 54 | address[] calldata admins, 55 | address[] calldata regularUsers, 56 | bytes calldata signature 57 | ) 58 | external 59 | { 60 | if (!isAdmin[msg.sender]) { 61 | // Allow calls to be relayed with an admin's signature. 62 | bytes32 hash = keccak256(abi.encodePacked(admins, regularUsers)); 63 | address signer = hash.toEthSignedMessageHash().recover(signature); 64 | require(isAdmin[signer], "Only admins can add users."); 65 | } 66 | for (uint256 i = 0; i < admins.length; i++) { 67 | isAdmin[admins[i]] = true; 68 | } 69 | for (uint256 i = 0; i < regularUsers.length; i++) { 70 | isRegularUser[regularUsers[i]] = true; 71 | } 72 | } 73 | } 74 | ``` 75 | 76 | ### access_control_fixed_1.sol 77 | 78 | ```solidity 79 | /* 80 | * @author: Steve Marx 81 | * Modified by Kaden Zipfel 82 | */ 83 | 84 | pragma solidity ^0.5.0; 85 | 86 | import "./ECDSA.sol"; 87 | 88 | contract AccessControl { 89 | using ECDSA for bytes32; 90 | mapping(address => bool) isAdmin; 91 | mapping(address => bool) isRegularUser; 92 | // Add a single user, either an admin or regular user. 93 | function addUser( 94 | address user, 95 | bool admin, 96 | bytes calldata signature 97 | ) 98 | external 99 | { 100 | if (!isAdmin[msg.sender]) { 101 | // Allow calls to be relayed with an admin's signature. 102 | bytes32 hash = keccak256(abi.encodePacked(user)); 103 | address signer = hash.toEthSignedMessageHash().recover(signature); 104 | require(isAdmin[signer], "Only admins can add users."); 105 | } 106 | if (admin) { 107 | isAdmin[user] = true; 108 | } else { 109 | isRegularUser[user] = true; 110 | } 111 | } 112 | } 113 | ``` 114 | 115 | ### access_control_fixed_2.sol 116 | 117 | ```solidity 118 | /* 119 | * @author: Steve Marx 120 | * Modified by Kaden Zipfel 121 | */ 122 | 123 | pragma solidity ^0.5.0; 124 | 125 | import "./ECDSA.sol"; 126 | 127 | contract AccessControl { 128 | using ECDSA for bytes32; 129 | mapping(address => bool) isAdmin; 130 | mapping(address => bool) isRegularUser; 131 | // Add admins and regular users. 132 | function addUsers( 133 | // Use fixed length arrays. 134 | address[3] calldata admins, 135 | address[3] calldata regularUsers, 136 | bytes calldata signature 137 | ) 138 | external 139 | { 140 | if (!isAdmin[msg.sender]) { 141 | // Allow calls to be relayed with an admin's signature. 142 | bytes32 hash = keccak256(abi.encodePacked(admins, regularUsers)); 143 | address signer = hash.toEthSignedMessageHash().recover(signature); 144 | require(isAdmin[signer], "Only admins can add users."); 145 | } 146 | for (uint256 i = 0; i < admins.length; i++) { 147 | isAdmin[admins[i]] = true; 148 | } 149 | for (uint256 i = 0; i < regularUsers.length; i++) { 150 | isRegularUser[regularUsers[i]] = true; 151 | } 152 | } 153 | } 154 | ``` 155 | -------------------------------------------------------------------------------- /entries/docs/SWC-134.md: -------------------------------------------------------------------------------- 1 | # Please note, this content is no longer actively maintained. 2 | 3 | The content of the SWC registry has not been thoroughly updated since 2020. It is known to be incomplete and may contain errors as well as crucial omissions. 4 | 5 | For currently maintained guidance on known Smart Contract vulnerabilities written primarily as guidance for security reviewers, please see the 6 | [EEA EthTrust Security Levels specification](https://entethalliance.org/specs/ethtrust-sl). As well as the latest release version, an 7 | [Editor's draft](https://entethalliance.github.io/eta-registry/security-levels-spec.html) is available, that represents the latest work of the group developing the specification. 8 | 9 | General guidance for developers on what to consider to ensure security, that is currently maintained, is also available through the 10 | [Smart Contract Security Verification Standard (SCSVS)](https://github.com/ComposableSecurity/SCSVS). 11 | 12 | # Title 13 | 14 | Message call with hardcoded gas amount 15 | 16 | ## Relationships 17 | 18 | [CWE-655: Improper Initialization](https://cwe.mitre.org/data/definitions/665.html) 19 | 20 | ## Description 21 | 22 | The `transfer()` and `send()` functions forward a fixed amount of 2300 gas. Historically, it has often been recommended to use these functions for value transfers to guard against reentrancy attacks. However, the gas cost of EVM instructions may change significantly during hard forks which may break already deployed contract systems that make fixed assumptions about gas costs. For example. [EIP 1884](https://eips.ethereum.org/EIPS/eip-1884) broke several existing smart contracts due to a cost increase of the SLOAD instruction. 23 | 24 | ## Remediation 25 | 26 | Avoid the use of `transfer()` and `send()` and do not otherwise specify a fixed amount of gas when performing calls. Use `.call.value(...)("")` instead. Use the checks-effects-interactions pattern and/or reentrancy locks to prevent reentrancy attacks. 27 | 28 | ## References 29 | 30 | - [ChainSecurity - Ethereum Istanbul Hardfork: The Security Perspective](https://docs.google.com/presentation/d/1IiRYSjwle02zQUmWId06Bss8GrxGyw6nQAiZdCRFEPk/) 31 | - [Steve Marx - Stop Using Solidity’s transfer() Now 32 | ](https://diligence.consensys.net/blog/2019/09/stop-using-soliditys-transfer-now/) 33 | - [EIP 1884](https://eips.ethereum.org/EIPS/eip-1884) 34 | 35 | ## Samples 36 | 37 | ### hardcoded_gas_limits.sol 38 | 39 | ```solidity 40 | /* 41 | * @author: Bernhard Mueller (ConsenSys / MythX) 42 | */ 43 | 44 | pragma solidity 0.6.4; 45 | 46 | interface ICallable { 47 | function callMe() external; 48 | } 49 | 50 | contract HardcodedNotGood { 51 | 52 | address payable _callable = 0xaAaAaAaaAaAaAaaAaAAAAAAAAaaaAaAaAaaAaaAa; 53 | ICallable callable = ICallable(_callable); 54 | 55 | constructor() public payable { 56 | } 57 | 58 | function doTransfer(uint256 amount) public { 59 | _callable.transfer(amount); 60 | } 61 | 62 | function doSend(uint256 amount) public { 63 | _callable.send(amount); 64 | } 65 | 66 | function callLowLevel() public { 67 | _callable.call.value(0).gas(10000)(""); 68 | } 69 | 70 | function callWithArgs() public { 71 | callable.callMe{gas: 10000}(); 72 | } 73 | } 74 | 75 | ``` 76 | -------------------------------------------------------------------------------- /entries/docs/SWC-135.md: -------------------------------------------------------------------------------- 1 | # Please note, this content is no longer actively maintained. 2 | 3 | The content of the SWC registry has not been thoroughly updated since 2020. It is known to be incomplete and may contain errors as well as crucial omissions. 4 | 5 | For currently maintained guidance on known Smart Contract vulnerabilities written primarily as guidance for security reviewers, please see the 6 | [EEA EthTrust Security Levels specification](https://entethalliance.org/specs/ethtrust-sl). As well as the latest release version, an 7 | [Editor's draft](https://entethalliance.github.io/eta-registry/security-levels-spec.html) is available, that represents the latest work of the group developing the specification. 8 | 9 | General guidance for developers on what to consider to ensure security, that is currently maintained, is also available through the 10 | [Smart Contract Security Verification Standard (SCSVS)](https://github.com/ComposableSecurity/SCSVS). 11 | 12 | # Title 13 | 14 | Code With No Effects 15 | 16 | ## Relationships 17 | 18 | - [CWE-710: Improper Adherence to Coding Standards](https://cwe.mitre.org/data/definitions/710.html) 19 | - EthTrust Security Levels: 20 | - [**[Q] Code Linting**](https://entethalliance.org/specs/ethtrust-sl/#req-3-linted) 21 | 22 | ## Description 23 | 24 | In Solidity, it's possible to write code that does not produce the intended effects. Currently, the solidity compiler will not return a warning for effect-free code. This can lead to the introduction of "dead" code that does not properly perform an intended action. 25 | 26 | For example, it's easy to miss the trailing parentheses in `msg.sender.call.value(address(this).balance)("");`, which could lead to a function proceeding without transferring funds to `msg.sender`. Although, this should be avoided by [checking the return value of the call](./SWC-104.md). 27 | 28 | ## Remediation 29 | 30 | It's important to carefully ensure that your contract works as intended. Write unit tests to verify correct behaviour of the code. 31 | 32 | ## References 33 | 34 | - [Issue on Solidity's Github - raise an error when a statement can never have side-effects](https://github.com/ethereum/solidity/issues/2707) 35 | - [Issue on Solidity's Github - msg.sender.call.value(address(this).balance); should produce a warning](https://github.com/ethereum/solidity/issues/7096) 36 | 37 | ## Samples 38 | 39 | ### deposit_box.sol 40 | 41 | ```solidity 42 | pragma solidity ^0.5.0; 43 | 44 | contract DepositBox { 45 | mapping(address => uint) balance; 46 | 47 | // Accept deposit 48 | function deposit(uint amount) public payable { 49 | require(msg.value == amount, 'incorrect amount'); 50 | // Should update user balance 51 | balance[msg.sender] == amount; 52 | } 53 | } 54 | ``` 55 | 56 | ### deposit_box_fixed.sol 57 | 58 | ```solidity 59 | pragma solidity ^0.5.0; 60 | 61 | contract DepositBox { 62 | mapping(address => uint) balance; 63 | 64 | // Accept deposit 65 | function deposit(uint amount) public payable { 66 | require(msg.value == amount, 'incorrect amount'); 67 | // Should update user balance 68 | balance[msg.sender] = amount; 69 | } 70 | } 71 | ``` 72 | 73 | ### wallet.sol 74 | 75 | ```solidity 76 | /* 77 | * @author: Kaden Zipfel 78 | */ 79 | 80 | pragma solidity ^0.5.0; 81 | 82 | contract Wallet { 83 | mapping(address => uint) balance; 84 | 85 | // Deposit funds in contract 86 | function deposit(uint amount) public payable { 87 | require(msg.value == amount, 'msg.value must be equal to amount'); 88 | balance[msg.sender] = amount; 89 | } 90 | 91 | // Withdraw funds from contract 92 | function withdraw(uint amount) public { 93 | require(amount <= balance[msg.sender], 'amount must be less than balance'); 94 | 95 | uint previousBalance = balance[msg.sender]; 96 | balance[msg.sender] = previousBalance - amount; 97 | 98 | // Attempt to send amount from the contract to msg.sender 99 | msg.sender.call.value(amount); 100 | } 101 | } 102 | ``` 103 | 104 | ### wallet_fixed.sol 105 | 106 | ```solidity 107 | /* 108 | * @author: Kaden Zipfel 109 | */ 110 | 111 | pragma solidity ^0.5.0; 112 | 113 | contract Wallet { 114 | mapping(address => uint) balance; 115 | 116 | // Deposit funds in contract 117 | function deposit(uint amount) public payable { 118 | require(msg.value == amount, 'msg.value must be equal to amount'); 119 | balance[msg.sender] = amount; 120 | } 121 | 122 | // Withdraw funds from contract 123 | function withdraw(uint amount) public { 124 | require(amount <= balance[msg.sender], 'amount must be less than balance'); 125 | 126 | uint previousBalance = balance[msg.sender]; 127 | balance[msg.sender] = previousBalance - amount; 128 | 129 | // Attempt to send amount from the contract to msg.sender 130 | (bool success, ) = msg.sender.call.value(amount)(""); 131 | require(success, 'transfer failed'); 132 | } 133 | } 134 | ``` 135 | -------------------------------------------------------------------------------- /entries/docs/SWC-136.md: -------------------------------------------------------------------------------- 1 | # Please note, this content is no longer actively maintained. 2 | 3 | The content of the SWC registry has not been thoroughly updated since 2020. It is known to be incomplete and may contain errors as well as crucial omissions. 4 | 5 | For currently maintained guidance on known Smart Contract vulnerabilities written primarily as guidance for security reviewers, please see the 6 | [EEA EthTrust Security Levels specification](https://entethalliance.org/specs/ethtrust-sl). As well as the latest release version, an 7 | [Editor's draft](https://entethalliance.github.io/eta-registry/security-levels-spec.html) is available, 8 | that represents the latest work of the group developing the specification. 9 | 10 | General guidance for developers on what to consider to ensure security, that is currently maintained, is also available through the 11 | [Smart Contract Security Verification Standard (SCSVS)](https://github.com/ComposableSecurity/SCSVS). 12 | 13 | # Title 14 | 15 | Unencrypted Private Data On-Chain 16 | 17 | ## Relationships 18 | 19 | - [CWE-767: Access to Critical Private Variable via Public Method](https://cwe.mitre.org/data/definitions/767.html) 20 | - EthTrust Security Levels: 21 | - [**[Q] No Private Data**](https://entethalliance.github.io/eta-registry/security-levels-spec.html#req-3-no-private-data) 22 | - [**[Q] Enforce Least Privilege**](https://entethalliance.github.io/eta-registry/security-levels-spec.html#req-3-access-control) 23 | 24 | ## Description 25 | 26 | It is a common misconception that `private` type variables cannot be read. Even if your contract is not published, attackers can look at contract transactions to determine values stored in the state of the contract. For this reason, it's important that unencrypted private data is not stored in the contract code or state. 27 | 28 | ## Remediation 29 | 30 | Any private data should either be stored off-chain, or carefully encrypted. 31 | 32 | ## References 33 | 34 | - [Keeping secrets on Ethereum](https://medium.com/solidified/keeping-secrets-on-ethereum-5b556c3bb1ee) 35 | - [A Survey of Attacks on Ethereum Smart Contracts (SoK)](https://www.semanticscholar.org/paper/A-Survey-of-Attacks-on-Ethereum-Smart-Contracts-Atzei-Bartoletti/aec843c0f38aff6c7901391a75ec10114a3d60f8) 36 | - [Unencrypted Secrets](https://github.com/KadenZipfel/smart-contract-attack-vectors/blob/master/vulnerabilities/unencrypted-secrets.md) 37 | - [Stack Overflow - Decrypt message on-chain](https://ethereum.stackexchange.com/questions/69825/decrypt-message-on-chain) 38 | 39 | ## Samples 40 | 41 | ### odd_even.sol 42 | 43 | ```solidity 44 | /* 45 | * @source: https://gist.github.com/manojpramesh/336882804402bee8d6b99bea453caadd#file-odd-even-sol 46 | * @author: https://github.com/manojpramesh 47 | * Modified by Kaden Zipfel 48 | */ 49 | 50 | pragma solidity ^0.5.0; 51 | 52 | contract OddEven { 53 | struct Player { 54 | address addr; 55 | uint number; 56 | } 57 | 58 | Player[2] private players; 59 | uint count = 0; 60 | 61 | function play(uint number) public payable { 62 | require(msg.value == 1 ether, 'msg.value must be 1 eth'); 63 | players[count] = Player(msg.sender, number); 64 | count++; 65 | if (count == 2) selectWinner(); 66 | } 67 | 68 | function selectWinner() private { 69 | uint n = players[0].number + players[1].number; 70 | (bool success, ) = players[n%2].addr.call.value(address(this).balance)(""); 71 | require(success, 'transfer failed'); 72 | delete players; 73 | count = 0; 74 | } 75 | } 76 | ``` 77 | 78 | #### Comments 79 | 80 | The vulnerable version above requires the players to send the number they are using 81 | as part of the transaction. 82 | This means the first player's number will be visible, allowing the second player to select a number 83 | that they know will make them a winner. 84 | (This assumption is simplistic to illustrate - there are also possibilities to front-run players, 85 | among other potential issues). 86 | 87 | In the fixed version below, the players instead submit a commitment that obfuscates their number, 88 | and only subsequently reveal that they know the secret to set in train the process of a payout. 89 | 90 | ### odd_even_fixed.sol 91 | 92 | ```solidity 93 | /* 94 | * @source: https://github.com/yahgwai/rps 95 | * @author: Chris Buckland 96 | * Modified by Kaden Zipfel 97 | * Modified by Kacper Żuk 98 | */ 99 | 100 | pragma solidity ^0.5.0; 101 | 102 | contract OddEven { 103 | enum Stage { 104 | FirstCommit, 105 | SecondCommit, 106 | FirstReveal, 107 | SecondReveal, 108 | Distribution 109 | } 110 | 111 | struct Player { 112 | address addr; 113 | bytes32 commitment; 114 | bool revealed; 115 | uint number; 116 | } 117 | 118 | Player[2] private players; 119 | Stage public stage = Stage.FirstCommit; 120 | 121 | function play(bytes32 commitment) public payable { 122 | // Only run during commit stages 123 | uint playerIndex; 124 | if(stage == Stage.FirstCommit) playerIndex = 0; 125 | else if(stage == Stage.SecondCommit) playerIndex = 1; 126 | else revert("only two players allowed"); 127 | 128 | // Require proper amount deposited 129 | // 1 ETH as a bet + 1 ETH as a bond 130 | require(msg.value == 2 ether, 'msg.value must be 2 eth'); 131 | 132 | // Store the commitment 133 | players[playerIndex] = Player(msg.sender, commitment, false, 0); 134 | 135 | // Move to next stage 136 | if(stage == Stage.FirstCommit) stage = Stage.SecondCommit; 137 | else stage = Stage.FirstReveal; 138 | } 139 | 140 | function reveal(uint number, bytes32 blindingFactor) public { 141 | // Only run during reveal stages 142 | require(stage == Stage.FirstReveal || stage == Stage.SecondReveal, "wrong stage"); 143 | 144 | // Find the player index 145 | uint playerIndex; 146 | if(players[0].addr == msg.sender) playerIndex = 0; 147 | else if(players[1].addr == msg.sender) playerIndex = 1; 148 | else revert("unknown player"); 149 | 150 | // Protect against double-reveal, which would trigger move to Stage.Distribution too early 151 | require(!players[playerIndex].revealed, "already revealed"); 152 | 153 | // Check the hash to prove the player's honesty 154 | require(keccak256(abi.encodePacked(msg.sender, number, blindingFactor)) == players[playerIndex].commitment, "invalid hash"); 155 | 156 | // Update player number if correct 157 | players[playerIndex].number = number; 158 | 159 | // Protect against double-reveal 160 | players[playerIndex].revealed = true; 161 | 162 | // Move to next stage 163 | if(stage == Stage.FirstReveal) stage = Stage.SecondReveal; 164 | else stage = Stage.Distribution; 165 | } 166 | 167 | function distribute() public { 168 | // Only run during distribution stage 169 | require(stage == Stage.Distribution, "wrong stage"); 170 | 171 | // Find winner 172 | uint n = players[0].number + players[1].number; 173 | 174 | // Payout winners winnings and bond 175 | players[n%2].addr.call.value(3 ether)(""); 176 | 177 | // Payback losers bond 178 | players[(n+1)%2].addr.call.value(1 ether)(""); 179 | 180 | // Reset the state 181 | delete players; 182 | stage = Stage.FirstCommit; 183 | } 184 | } 185 | 186 | ``` 187 | -------------------------------------------------------------------------------- /entries/index.md: -------------------------------------------------------------------------------- 1 | # Please note, this content is no longer actively maintained. 2 | 3 | The content of the SWC registry has not been thoroughly updated since 2020. It is known to be incomplete and may contain errors as well as crucial omissions. 4 | 5 | For currently maintained guidance on known Smart Contract vulnerabilities written primarily as guidance for security reviewers, please see the 6 | [EEA EthTrust Security Levels specification](https://entethalliance.org/specs/ethtrust-sl). As well as the latest release version, an 7 | [Editor's draft](https://entethalliance.github.io/eta-registry/security-levels-spec.html) is available, 8 | that represents the latest work of the group developing the specification. 9 | 10 | General guidance for developers on how to ensure security, that is currently maintained, is also available through the 11 | [Smart Contract Security Verification Standard (SCSVS)](https://github.com/ComposableSecurity/SCSVS), or 12 | the [Smart Contract Security Field Guide](https://scsfg.io). 13 | 14 | The following table contains an overview of the SWC registry. Each row consists of an SWC identifier (ID), weakness title, CWE parent and list of related code samples. The links in the ID and Test Cases columns link to the respective SWC definition. Links in the Relationships column link to the CWE Base or Class type. 15 | 16 | | ID | Title | Relationships | 17 | | ---------------------------- | ------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | 18 | | [SWC-136](./docs/SWC-136.md) | Unencrypted Private Data On-Chain | [CWE-767: Access to Critical Private Variable via Public Method](https://cwe.mitre.org/data/definitions/767.html) | 19 | | [SWC-135](./docs/SWC-135.md) | Code With No Effects | [CWE-1164: Irrelevant Code](https://cwe.mitre.org/data/definitions/1164.html) | 20 | | [SWC-134](./docs/SWC-134.md) | Message call with hardcoded gas amount | [CWE-655: Improper Initialization](https://cwe.mitre.org/data/definitions/665.html) | 21 | | [SWC-133](./docs/SWC-133.md) | Hash Collisions With Multiple Variable Length Arguments | [CWE-294: Authentication Bypass by Capture-replay](https://cwe.mitre.org/data/definitions/294.html) | 22 | | [SWC-132](./docs/SWC-132.md) | Unexpected Ether balance | [CWE-667: Improper Locking](https://cwe.mitre.org/data/definitions/667.html) | 23 | | [SWC-131](./docs/SWC-131.md) | Presence of unused variables | [CWE-1164: Irrelevant Code](https://cwe.mitre.org/data/definitions/1164.html) | 24 | | [SWC-130](./docs/SWC-130.md) | Right-To-Left-Override control character (U+202E) | [CWE-451: User Interface (UI) Misrepresentation of Critical Information](http://cwe.mitre.org/data/definitions/451.html) | 25 | | [SWC-129](./docs/SWC-129.md) | Typographical Error | [CWE-480: Use of Incorrect Operator](https://cwe.mitre.org/data/definitions/480.html) | 26 | | [SWC-128](./docs/SWC-128.md) | DoS With Block Gas Limit | [CWE-400: Uncontrolled Resource Consumption](https://cwe.mitre.org/data/definitions/400.html) | 27 | | [SWC-127](./docs/SWC-127.md) | Arbitrary Jump with Function Type Variable | [CWE-695: Use of Low-Level Functionality](https://cwe.mitre.org/data/definitions/695.html) | 28 | | [SWC-126](./docs/SWC-126.md) | Insufficient Gas Griefing | [CWE-691: Insufficient Control Flow Management](https://cwe.mitre.org/data/definitions/691.html) | 29 | | [SWC-125](./docs/SWC-125.md) | Incorrect Inheritance Order | [CWE-696: Incorrect Behavior Order](https://cwe.mitre.org/data/definitions/696.html) | 30 | | [SWC-124](./docs/SWC-124.md) | Write to Arbitrary Storage Location | [CWE-123: Write-what-where Condition](https://cwe.mitre.org/data/definitions/123.html) | 31 | | [SWC-123](./docs/SWC-123.md) | Requirement Violation | [CWE-573: Improper Following of Specification by Caller](https://cwe.mitre.org/data/definitions/573.html) | 32 | | [SWC-122](./docs/SWC-122.md) | Lack of Proper Signature Verification | [CWE-345: Insufficient Verification of Data Authenticity](https://cwe.mitre.org/data/definitions/345.html) | 33 | | [SWC-121](./docs/SWC-121.md) | Missing Protection against Signature Replay Attacks | [CWE-347: Improper Verification of Cryptographic Signature](https://cwe.mitre.org/data/definitions/347.html) | 34 | | [SWC-120](./docs/SWC-120.md) | Weak Sources of Randomness from Chain Attributes | [CWE-330: Use of Insufficiently Random Values](https://cwe.mitre.org/data/definitions/330.html) | 35 | | [SWC-119](./docs/SWC-119.md) | Shadowing State Variables | [CWE-710: Improper Adherence to Coding Standards](http://cwe.mitre.org/data/definitions/710.html) | 36 | | [SWC-118](./docs/SWC-118.md) | Incorrect Constructor Name | [CWE-665: Improper Initialization](http://cwe.mitre.org/data/definitions/665.html) | 37 | | [SWC-117](./docs/SWC-117.md) | Signature Malleability | [CWE-347: Improper Verification of Cryptographic Signature](https://cwe.mitre.org/data/definitions/347.html) | 38 | | [SWC-116](./docs/SWC-116.md) | Block values as a proxy for time | [CWE-829: Inclusion of Functionality from Untrusted Control Sphere](https://cwe.mitre.org/data/definitions/829.html) | 39 | | [SWC-115](./docs/SWC-115.md) | Authorization through tx.origin | [CWE-477: Use of Obsolete Function](https://cwe.mitre.org/data/definitions/477.html) | 40 | | [SWC-114](./docs/SWC-114.md) | Transaction Order Dependence | [CWE-362: Concurrent Execution using Shared Resource with Improper Synchronization ('Race Condition')](https://cwe.mitre.org/data/definitions/362.html) | 41 | | [SWC-113](./docs/SWC-113.md) | DoS with Failed Call | [CWE-703: Improper Check or Handling of Exceptional Conditions](https://cwe.mitre.org/data/definitions/703.html) | 42 | | [SWC-112](./docs/SWC-112.md) | Delegatecall to Untrusted Callee | [CWE-829: Inclusion of Functionality from Untrusted Control Sphere](https://cwe.mitre.org/data/definitions/829.html) | 43 | | [SWC-111](./docs/SWC-111.md) | Use of Deprecated Solidity Functions | [CWE-477: Use of Obsolete Function](https://cwe.mitre.org/data/definitions/477.html) | 44 | | [SWC-110](./docs/SWC-110.md) | Assert Violation | [CWE-670: Always-Incorrect Control Flow Implementation](https://cwe.mitre.org/data/definitions/670.html) | 45 | | [SWC-109](./docs/SWC-109.md) | Uninitialized Storage Pointer | [CWE-824: Access of Uninitialized Pointer](https://cwe.mitre.org/data/definitions/824.html) | 46 | | [SWC-108](./docs/SWC-108.md) | State Variable Default Visibility | [CWE-710: Improper Adherence to Coding Standards](https://cwe.mitre.org/data/definitions/710.html) | 47 | | [SWC-107](./docs/SWC-107.md) | Reentrancy | [CWE-841: Improper Enforcement of Behavioral Workflow](https://cwe.mitre.org/data/definitions/841.html) | 48 | | [SWC-106](./docs/SWC-106.md) | Unprotected SELFDESTRUCT Instruction | [CWE-284: Improper Access Control](https://cwe.mitre.org/data/definitions/284.html) | 49 | | [SWC-105](./docs/SWC-105.md) | Unprotected Ether Withdrawal | [CWE-284: Improper Access Control](https://cwe.mitre.org/data/definitions/284.html) | 50 | | [SWC-104](./docs/SWC-104.md) | Unchecked Call Return Value | [CWE-252: Unchecked Return Value](https://cwe.mitre.org/data/definitions/252.html) | 51 | | [SWC-103](./docs/SWC-103.md) | Floating Pragma | [CWE-664: Improper Control of a Resource Through its Lifetime](https://cwe.mitre.org/data/definitions/664.html) | 52 | | [SWC-102](./docs/SWC-102.md) | Outdated Compiler Version | [CWE-937: Using Components with Known Vulnerabilities](http://cwe.mitre.org/data/definitions/937.html) | 53 | | [SWC-101](./docs/SWC-101.md) | Integer Overflow and Underflow | [CWE-682: Incorrect Calculation](https://cwe.mitre.org/data/definitions/682.html) | 54 | | [SWC-100](./docs/SWC-100.md) | Function Default Visibility | [CWE-710: Improper Adherence to Coding Standards](https://cwe.mitre.org/data/definitions/710.html) | 55 | -------------------------------------------------------------------------------- /mkdocs.yml: -------------------------------------------------------------------------------- 1 | site_name: Smart Contract Weakness Classification (SWC) 2 | site_url: https://swcregistry.io/ 3 | site_description: Smart Contract Weakness Classification and Test Cases 4 | site_author: Dominik Muhs 5 | 6 | repo_url: https://github.com/SmartContractSecurity/SWC-registry 7 | repo_name: SWC Registry 8 | remote_branch: gh-pages 9 | remote_name: origin 10 | 11 | strict: true 12 | docs_dir: entries 13 | 14 | nav: 15 | - Overview: index.md 16 | - SWC-100: docs/SWC-100.md 17 | - SWC-101: docs/SWC-101.md 18 | - SWC-102: docs/SWC-102.md 19 | - SWC-103: docs/SWC-103.md 20 | - SWC-104: docs/SWC-104.md 21 | - SWC-105: docs/SWC-105.md 22 | - SWC-106: docs/SWC-106.md 23 | - SWC-107: docs/SWC-107.md 24 | - SWC-108: docs/SWC-108.md 25 | - SWC-109: docs/SWC-109.md 26 | - SWC-110: docs/SWC-110.md 27 | - SWC-111: docs/SWC-111.md 28 | - SWC-112: docs/SWC-112.md 29 | - SWC-113: docs/SWC-113.md 30 | - SWC-114: docs/SWC-114.md 31 | - SWC-115: docs/SWC-115.md 32 | - SWC-116: docs/SWC-116.md 33 | - SWC-117: docs/SWC-117.md 34 | - SWC-118: docs/SWC-118.md 35 | - SWC-119: docs/SWC-119.md 36 | - SWC-120: docs/SWC-120.md 37 | - SWC-121: docs/SWC-121.md 38 | - SWC-122: docs/SWC-122.md 39 | - SWC-123: docs/SWC-123.md 40 | - SWC-124: docs/SWC-124.md 41 | - SWC-125: docs/SWC-125.md 42 | - SWC-126: docs/SWC-126.md 43 | - SWC-127: docs/SWC-127.md 44 | - SWC-128: docs/SWC-128.md 45 | - SWC-129: docs/SWC-129.md 46 | - SWC-130: docs/SWC-130.md 47 | - SWC-131: docs/SWC-131.md 48 | - SWC-132: docs/SWC-132.md 49 | - SWC-133: docs/SWC-133.md 50 | - SWC-134: docs/SWC-134.md 51 | - SWC-135: docs/SWC-135.md 52 | - SWC-136: docs/SWC-136.md 53 | 54 | theme: 55 | name: "material" 56 | language: en 57 | 58 | markdown_extensions: 59 | - pymdownx.superfences 60 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | mkdocs 2 | mkdocs-material 3 | pygments 4 | pygments-lexer-solidity 5 | pymdown-extensions 6 | --------------------------------------------------------------------------------