- 함수와 상태 변수의 가시성을 명시적으로 작성하도록 합니다.
SWC-101 Integer Overflow and Underflow
- 오픈제플린의 SafeMath를 사용하도록 합니다.
- 컨트랙트 크기를 줄이기 위해 필요한 부분만 가져다가 SafeMath 라이브러리를 재구성해서 사용할 수 있습니다.
SWC-102 Outdated Compiler Version
SWC-103 Floating Pragma
- solidity 버전은 특별한 이유가 없는 한 정확한 버전을 명시하도록 합니다.
- pragma solidity 0.4.25; // or pragma solidity =0.4.25;
SWC-104 Unchecked Call Return Value
- 저수준 call 메소드를 사용할 때는 실패에 대한 가능성을 분명히 다루기 위해서 리턴 값을 체크해야 합니다.
- 저수준 call은 실패한 경우 false를 리턴합니다.
SWC-105 Unprotected Ether Withdrawal
- Implement controls so withdrawals can only be triggered by authorized parties or according to the specs of the smart contract system.
SWC-106 Unprotected SELFDESTRUCT Instruction
- Due to missing or insufficient access controls, malicious parties can self-destruct the contract.
- 꼭 필요한 경우가 아니라면 self-destruct 함수를 포함하지 않도록 합니다. 꼭 필요하다면 다중 서명이 가능하도록 구현합니다.
SWC-109 Uninitialized Storage Pointer
SWC-110 Assert Violation
SWC-111 Use of Deprecated Solidity Functions
- suicide(address) – selfdestruct(address)
- block.blockhash(uint) – blockhash(uint)
- sha3(…) – keccak256(…)
- callcode(…) – delegatecall(…)
- throw – revert()
- msg.gas – gasleft
- constant – view
- var – corresponding type name
SWC-112 Delegatecall to Untrusted Callee
SWC-113 DoS with Failed Call
- 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).
- It is recommended to follow call best practices:
- Avoid combining multiple calls in a single transaction, especially when calls are executed as part of a loop
- Always assume that external calls can fail
- Implement the contract logic to handle failed calls
SWC-114 Transaction Order Dependence
- A possible way to remedy for race conditions in 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.
- 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 important to your project to have the contract conform to ERC20, you can add a safe approve function. From the user perspective it is possible to mediate the ERC20 race condition by setting approvals to zero before changing them.
SWC-115 Authorization through tx.origin
SWC-116 Block values as a proxy for time – block.timestamp, and block.number
SWC-117 Signature Malleability
- 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.
- A signature should never be included into a signed message hash to check if previously messages have been processed by the contract.
SWC-118 Incorrect Constructor Name
SWC-119 Shadowing State Variables
- 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.
SWC-120 Weak Sources of Randomness from Chain Attributes
SWC-121 Missing Protection against Signature Replay Attacks
- 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.
- In order to protect against signature replay attacks consider the following recommendations:
- 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.
- Include the address of the contract that processes the message. This ensures that the message can only be used in a single contract.
- Under no circumstances generate the message hash including the signature. The ecrecover function is susceptible to signature malleability (see also SWC-117).
SWC-122 Lack of Proper Signature Verification
- 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.
- It is not recommended to use alternate verification schemes that do not require proper signature verification through ecrecover().
SWC-123 Requirement Violation
- 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:
- A bug exists in the contract that provided the external input.
- The condition used to express the requirement is too strong.
- If the required logical condition is too strong, it should be weakened to allow all valid external inputs. 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.
SWC-124 Write to Arbitrary Storage Location
- A smart contract’s data (e.g., storing the owner of the contract) is persistently stored at some storage location (i.e., a key or address) on the EVM level. The contract is responsible for ensuring that only authorized user or contract accounts may write to sensitive storage locations. If an attacker is able to write to arbitrary storage locations of a contract, the authorization checks may easily be circumvented. This can allow an attacker to corrupt the storage; for instance, by overwriting a field that stores the address of the contract owner.
- As a general advice, given that all data structures share the same storage (address) space, one should make sure that writes to one data structure cannot inadvertently overwrite entries of another data structure.
SWC-125 Incorrect Inheritance Order
- Solidity supports multiple inheritance, meaning that one contract can inherit several contracts. Multiple inheritance introduces ambiguity called Diamond Problem: if two or more base contracts define the same function, which one should be called in the child contract? Solidity deals with this ambiguity by using reverse C3 Linearization, which sets a priority between base contracts. That way, base contracts have different priorities, so the order of inheritance matters. Neglecting inheritance order can lead to unexpected behavior.
- When inheriting multiple contracts, especially if they have identical functions, a developer should carefully specify inheritance in the correct order. The rule of thumb is to inherit contracts from more /general/ to more /specific/.
SWC-126 Insufficient Gas Griefing
SWC-127 Arbitrary Jump with Function Type Variable
- 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. 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.
- The use of assembly should be minimal. A developer should not allow a user to assign arbitrary values to function type variables.
SWC-128 DoS With Block Gas Limit
SWC-129 Typographical Error
SWC-130 Right-To-Left-Override control character (U+202E)
- 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.
- There are very few legitimate uses of the U+202E character. It should not appear in the source code of a smart contract.
SWC-131 Presence of unused variables
SWC-132 Unexpected Ether balance
SWC-133 Hash Collisions With Multiple Variable Length Arguments
- 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.
- 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. It is also recommended that you use replay protection (see SWC-121), although an attacker can still bypass this by front-running.
SWC-134 Message call with hardcoded gas amount
- 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.
SWC-135 Code With No Effects
SWC-136 Unencrypted Private Data On-Chain