Convert Figma logo to code with AI

crytic logonot-so-smart-contracts

Examples of Solidity security issues

2,142
335
2,142
10

Top Related Projects

OpenZeppelin Contracts is a library for secure smart contract development.

A guide to smart contract security best practices

Comprehensive list of known attack vectors and common anti-patterns

node of the decentralized oracle network, bridging on and off-chain computation

Quick Overview

The "crytic/not-so-smart-contracts" repository is a collection of common Ethereum smart contract vulnerabilities. It serves as an educational resource for developers and security researchers, showcasing various security issues in Solidity contracts along with explanations and potential fixes.

Pros

  • Provides real-world examples of smart contract vulnerabilities
  • Includes detailed explanations and potential fixes for each vulnerability
  • Serves as a valuable learning resource for Ethereum developers
  • Regularly updated with new vulnerabilities and best practices

Cons

  • May not cover all possible vulnerabilities in smart contracts
  • Some examples might become outdated as Solidity and Ethereum evolve
  • Requires a basic understanding of Solidity and smart contract development
  • Not a comprehensive security solution on its own

Code Examples

  1. Reentrancy vulnerability:
contract Vulnerable {
    mapping(address => uint) public balances;

    function withdraw() public {
        uint bal = balances[msg.sender];
        require(bal > 0);
        (bool sent, ) = msg.sender.call{value: bal}("");
        require(sent, "Failed to send Ether");
        balances[msg.sender] = 0;
    }
}

This code demonstrates a reentrancy vulnerability where an attacker can repeatedly call the withdraw function before the balance is updated.

  1. Integer overflow:
contract Overflow {
    mapping(address => uint8) public balances;

    function transfer(address _to, uint8 _amount) public {
        balances[msg.sender] -= _amount;
        balances[_to] += _amount;
    }
}

This example shows an integer overflow vulnerability where the balance can wrap around due to the use of uint8.

  1. Unprotected self-destruct:
contract Destroyable {
    function destroy() public {
        selfdestruct(payable(msg.sender));
    }
}

This code demonstrates an unprotected selfdestruct function that allows anyone to destroy the contract and send its balance to themselves.

Getting Started

To explore the vulnerabilities:

  1. Clone the repository:
    git clone https://github.com/crytic/not-so-smart-contracts.git
    
  2. Navigate to the desired vulnerability folder.
  3. Read the README.md file for an explanation of the vulnerability.
  4. Review the vulnerable and fixed contract examples in the Solidity files.
  5. Use a development environment like Remix or Truffle to deploy and test the contracts.

Competitor Comparisons

OpenZeppelin Contracts is a library for secure smart contract development.

Pros of openzeppelin-contracts

  • Comprehensive library of secure, audited smart contract components
  • Actively maintained with regular updates and improvements
  • Extensive documentation and community support

Cons of openzeppelin-contracts

  • Larger codebase may increase gas costs for deployment
  • Learning curve for developers new to the library
  • May include unnecessary features for simpler projects

Code Comparison

openzeppelin-contracts:

contract ERC20 is Context, IERC20, IERC20Metadata {
    mapping(address => uint256) private _balances;
    mapping(address => mapping(address => uint256)) private _allowances;
    uint256 private _totalSupply;
    string private _name;
    string private _symbol;

not-so-smart-contracts:

contract VulnerableToken {
    mapping(address => uint) public balances;
    uint public totalSupply;
    function transfer(address to, uint amount) public {
        balances[msg.sender] -= amount;
        balances[to] += amount;
    }

The openzeppelin-contracts example showcases a more robust and secure implementation of an ERC20 token, while the not-so-smart-contracts example demonstrates a vulnerable token contract for educational purposes.

A guide to smart contract security best practices

Pros of smart-contract-best-practices

  • Comprehensive coverage of best practices and security considerations
  • Regular updates and contributions from the community
  • Includes practical examples and code snippets

Cons of smart-contract-best-practices

  • Can be overwhelming for beginners due to the extensive information
  • Lacks a structured learning path or progression
  • Some sections may require prior knowledge of smart contract development

Code Comparison

smart-contract-best-practices:

function transfer(address to, uint256 amount) public {
    require(balances[msg.sender] >= amount, "Insufficient balance");
    balances[msg.sender] -= amount;
    balances[to] += amount;
    emit Transfer(msg.sender, to, amount);
}

not-so-smart-contracts:

function transfer(address to, uint256 amount) public {
    balances[msg.sender] -= amount;
    balances[to] += amount;
    emit Transfer(msg.sender, to, amount);
}

The smart-contract-best-practices example includes a balance check, demonstrating better security practices, while the not-so-smart-contracts example lacks this check, potentially allowing underflow vulnerabilities.

Comprehensive list of known attack vectors and common anti-patterns

Pros of solidity-security-blog

  • More comprehensive coverage of security topics, including detailed explanations and examples
  • Regular updates and contributions from the community
  • Includes practical mitigation strategies for each vulnerability

Cons of solidity-security-blog

  • Less structured organization compared to not-so-smart-contracts
  • Fewer ready-to-use code snippets for testing and demonstration
  • May be overwhelming for beginners due to the depth of information

Code Comparison

not-so-smart-contracts:

function withdraw() public {
    uint256 amount = balances[msg.sender];
    (bool success, ) = msg.sender.call.value(amount)("");
    require(success);
    balances[msg.sender] = 0;
}

solidity-security-blog:

function withdraw() public {
    uint256 amount = balances[msg.sender];
    balances[msg.sender] = 0;
    (bool success, ) = msg.sender.call.value(amount)("");
    require(success, "Transfer failed.");
}

Both repositories provide valuable resources for Solidity developers interested in smart contract security. not-so-smart-contracts offers a more structured approach with specific vulnerability examples, while solidity-security-blog provides in-depth explanations and community-driven content. The code comparison shows a subtle difference in the order of operations, highlighting the importance of following best practices to prevent reentrancy attacks.

node of the decentralized oracle network, bridging on and off-chain computation

Pros of Chainlink

  • Actively maintained and widely adopted in the blockchain industry
  • Comprehensive documentation and extensive ecosystem support
  • Provides real-world data integration and off-chain computation capabilities

Cons of Chainlink

  • More complex codebase with a steeper learning curve
  • Requires understanding of oracle networks and decentralized data feeds
  • Higher resource requirements for deployment and maintenance

Code Comparison

Chainlink (price feed example):

import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol";

contract PriceConsumerV3 {
    AggregatorV3Interface internal priceFeed;

    constructor() {
        priceFeed = AggregatorV3Interface(0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419);
    }
}

Not-so-smart-contracts (vulnerable code example):

contract Vulnerable {
    mapping(address => uint) public balances;

    function withdraw() public {
        uint amount = balances[msg.sender];
        (bool success, ) = msg.sender.call{value: amount}("");
        require(success);
        balances[msg.sender] = 0;
    }
}

Not-so-smart-contracts focuses on showcasing vulnerable smart contract patterns, while Chainlink provides robust infrastructure for building secure and interconnected smart contracts.

Convert Figma logo designs to code with AI

Visual Copilot

Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.

Try Visual Copilot

README

No-so-smart-contracts is now in building-secure-contracts (see https://secure-contracts.com/)

(Not So) Smart Contracts

This repository contains examples of common Ethereum smart contract vulnerabilities, including code from real smart contracts. Use Not So Smart Contracts to learn about EVM and Solidity vulnerabilities, as a reference when performing security reviews, and as a benchmark for security and analysis tools.

Features

Each Not So Smart Contract includes a standard set of information:

  • Description of the unique vulnerability type
  • Attack scenarios to exploit the vulnerability
  • Recommendations to eliminate or mitigate the vulnerability
  • Real-world contracts that exhibit the flaw
  • References to third-party resources with more information

Bonus! We have also included a repository and analysis of several honeypots.

Vulnerabilities

Not So Smart ContractDescription
Bad randomnessContract attempts to get on-chain randomness, which can be manipulated by users
Denial of ServiceAttacker stalls contract execution by failing in strategic way
Forced Ether ReceptionContracts can be forced to receive Ether
Incorrect InterfaceImplementation uses different function signatures than interface
Integer OverflowArithmetic in Solidity (or EVM) is not safe by default
Race ConditionTransactions can be frontrun on the blockchain
ReentrancyCalling external contracts gives them control over execution
Unchecked External CallSome Solidity operations silently fail
Unprotected FunctionFailure to use function modifier allows attacker to manipulate contract
Variable ShadowingLocal variable name is identical to one in outer scope
Wrong Constructor NameAnyone can become owner of contract due to missing constructor

Credits

These examples are developed and maintained by Trail of Bits. Contributions are encouraged and are covered under our bounty program.

If you have questions, problems, or just want to learn more, then join the #ethereum channel on the Empire Hacking Slack or contact us directly.