DeveloperBreeze

Solidity Cheatsheet

Solidity Cheatsheet

Solidity is the primary programming language used to write smart contracts on the Ethereum blockchain. This cheatsheet provides a quick reference to the key syntax, functions, and concepts in Solidity, covering everything from basic syntax to advanced features.

---

1. Basic Structure

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract ContractName {
    // State variables
    uint public myUint;
    string public myString;

    // Constructor
    constructor() {
        // Initialization code
    }

    // Functions
    function setMyUint(uint _value) public {
        myUint = _value;
    }

    function getMyUint() public view returns (uint) {
        return myUint;
    }
}

---

2. Data Types

  • Value Types:

- bool: true or false

- int: Signed integers (e.g., int256, int128)

- uint: Unsigned integers (e.g., uint256, uint128)

- address: Holds a 20-byte Ethereum address

- bytes1, bytes32: Fixed-size byte arrays

  • Reference Types:

- string: Dynamically-sized UTF-8 encoded string

- bytes: Dynamically-sized byte array

- array: Fixed or dynamic array

- mapping: Key-value store (e.g., mapping(address => uint))

---

3. Visibility Specifiers

  • public: Accessible externally and internally

  • internal: Accessible only within the contract and derived contracts

  • private: Accessible only within the contract

  • external: Accessible only externally (cannot be called internally without this)

---

4. State Variables and Constants

uint public myVariable;
address private owner;
bool internal isActive;

uint constant MY_CONSTANT = 10;
address immutable MY_ADDRESS = msg.sender;

---

5. Functions

  • Function Modifiers:

- view: Indicates that the function does not modify the state.

- pure: Indicates that the function does not read or modify the state.

- payable: Indicates that the function can receive Ether.

function setMyUint(uint _value) public {
    myUint = _value;
}

function getMyUint() public view returns (uint) {
    return myUint;
}

function add(uint a, uint b) public pure returns (uint) {
    return a + b;
}

function deposit() public payable {
    // Function to receive Ether
}

---

6. Modifiers

Modifiers are used to change the behavior of functions.

modifier onlyOwner() {
    require(msg.sender == owner, "Not the owner");
    _;
}

function setMyUint(uint _value) public onlyOwner {
    myUint = _value;
}

---

7. Events

Events allow logging of data on the blockchain, which can be listened to by external applications.

event MyEvent(address indexed from, uint value);

function triggerEvent(uint _value) public {
    emit MyEvent(msg.sender, _value);
}

---

8. Structs and Enums

  • Structs: Define custom data types.

struct User {
    uint id;
    string name;
}

User public user;

function setUser(uint _id, string memory _name) public {
    user = User(_id, _name);
}

  • Enums: Define enumerated lists.

enum State { Created, Locked, Inactive }
State public state;

function setState(State _state) public {
    state = _state;
}

---

9. Mappings

Mappings are key-value stores, often used to associate addresses with balances.

mapping(address => uint) public balances;

function updateBalance(address _address, uint _amount) public {
    balances[_address] = _amount;
}

function getBalance(address _address) public view returns (uint) {
    return balances[_address];
}

---

10. Inheritance

Solidity supports single inheritance. Contracts can inherit from other contracts.

contract Base {
    uint public data;

    function setData(uint _data) public {
        data = _data;
    }
}

contract Derived is Base {
    function getData() public view returns (uint) {
        return data;
    }
}

---

11. Interfaces

Interfaces define a contract's functions without implementing them, allowing different contracts to interact.

interface MyInterface {
    function setData(uint _data) external;
    function getData() external view returns (uint);
}

contract MyContract is MyInterface {
    uint private data;

    function setData(uint _data) external override {
        data = _data;
    }

    function getData() external view override returns (uint) {
        return data;
    }
}

---

12. Libraries

Libraries are similar to contracts but are meant to hold reusable code. They cannot hold state.

library Math {
    function add(uint a, uint b) internal pure returns (uint) {
        return a + b;
    }
}

contract MyContract {
    using Math for uint;

    function calculate(uint a, uint b) public pure returns (uint) {
        return a.add(b);
    }
}

---

13. Fallback and Receive Functions

Fallback and receive functions handle direct payments to contracts.

  • Fallback: Called when no other function matches or if no data is provided.

  • Receive: Specifically handles Ether transfers.

// Fallback function
fallback() external payable {
    // Logic to execute when no other function matches
}

// Receive function
receive() external payable {
    // Logic to execute when contract receives Ether directly
}

---

14. Error Handling

Use require, assert, and revert for error handling.

  • require: Checks conditions and reverts if false. Used for input validation.

  • assert: Used to check for conditions that should never be false.

  • revert: Explicitly reverts the transaction, optionally providing an error message.

function withdraw(uint _amount) public {
    require(_amount <= balances[msg.sender], "Insufficient balance");
    balances[msg.sender] -= _amount;
}

function divide(uint a, uint b) public pure returns (uint) {
    assert(b != 0);
    return a / b;
}

function doSomething(uint _value) public {
    if (_value < 10) {
        revert("Value too low");
    }
}

---

15. Assembly

Inline assembly allows for low-level operations and optimizations.

function multiply(uint a, uint b) public pure returns (uint) {
    uint result;
    assembly {
        result := mul(a, b)
    }
    return result;
}

---

16. Gas Optimization Tips

  • Use memory over storage for temporary variables.

  • Group multiple storage updates in a single transaction.

  • Avoid complex computations within loops.

  • Use immutable and constant for variables that do not change.

  • Leverage view and pure functions to save gas on reads.

---

17. Common Design Patterns

  • Ownable Pattern: Restricts access to certain functions to the contract owner.

  • Pausable Pattern: Allows the contract to be paused or unpaused.

  • Upgradable Contracts: Use proxy patterns to upgrade contract logic while preserving state.

  • ERC20/721 Tokens: Standards for implementing tokens.

---

18. ERC Standards

  • ERC20: Standard interface for fungible tokens.

  • ERC721: Standard interface for non-fungible tokens (NFTs).

  • ERC1155: Standard for multi-token contracts.

---

19. Best Practices

  • Always validate inputs with require.

  • Use SafeMath or Solidity's built-in overflow checks for arithmetic.

  • Limit gas consumption by optimizing functions.

  • Write unit tests for every contract function.

  • Audit and review contracts before deploying to the mainnet.

---

20. Deployment and Testing Tools

  • Remix IDE: Web-based IDE for writing and testing smart contracts.

  • Truffle: Development framework for Ethereum smart contracts.

  • Hardhat: Flexible development environment for Ethereum.

  • Ganache: Personal blockchain for Ethereum development.

---

This Solidity cheatsheet covers the essential concepts and syntax needed to start writing and optimizing smart contracts. As you develop more complex contracts, always consider security, gas efficiency, and best practices to ensure your contracts are robust and cost-effective.

Related Posts

More content you might like

Tutorial
javascript

Non-Primitive Data Types (Objects, Arrays, and Functions)

  • Removing Elements:
  fruits.pop(); // Removes the last element
  fruits.shift(); // Removes the first element
  console.log(fruits);

Dec 11, 2024
Read More
Code
javascript

Dynamic and Responsive DataTable with Server-Side Processing and Custom Styling

$('#exampleTable').DataTable({
    "responsive": true,
    "processing": true,
    "serverSide": true,
    "ajax": {
        "url": "{{ route('fetchUserData') }}",
        "type": "GET",
        "error": function(xhr, status, errorThrown) {
            console.error("Error during AJAX request: ", errorThrown);
        },
        "dataSrc": function(response) {
            console.info("Data received from server: ", response);
            if (response.records && response.records.length) {
                console.info("Data entries loaded:");
                response.records.forEach(function(record) {
                    console.log(record);
                });
                return response.records;
            } else {
                console.warn("No records found.");
                return [];
            }
        }
    },
    "columns": [
        { "data": "username" },
        { "data": "points" },
        { "data": "followers" },
        { "data": "referrals" }
    ],
    "language": {
        "emptyTable": "No records to display" // Custom message for empty table
    },
    "initComplete": function() {
        $('div.dataTables_length select').addClass('form-select mt-1 w-full');
        $('div.dataTables_filter input').addClass('form-input block w-full mt-1');
    },
    "drawCallback": function() {
        $('table').addClass('min-w-full bg-gray-50');
        $('thead').addClass('bg-blue-100');
        $('thead th').addClass('py-3 px-5 text-left text-xs font-semibold text-gray-700 uppercase tracking-wide');
        $('tbody tr').addClass('border-t border-gray-300');
        $('tbody td').addClass('py-3 px-5 text-sm text-gray-800');
    }
});

This JavaScript code initializes a DataTables instance on an HTML table with the ID #exampleTable. It enhances the table with various features like responsiveness, server-side processing, AJAX data fetching, and custom styling.

Oct 24, 2024
Read More
Tutorial
php

Handling HTTP Requests and Raw Responses in Laravel

use Illuminate\Support\Facades\Http;

$response = Http::post('https://api.example.com/endpoint', [
    'key1' => 'value1',
    'key2' => 'value2',
]);

$rawResponse = $response->body(); // Get the raw response
$parsedResponse = [];

// Parse the query string into an associative array
parse_str($rawResponse, $parsedResponse);

dd($parsedResponse); // Now you can work with the associative array
  • parse_str(): Parses the query string into an associative array. This is useful when working with URL-encoded responses.

Oct 24, 2024
Read More
Tutorial

Understanding `crypto.randomBytes` and `ethers.randomBytes`: A Comparison

  • crypto.randomBytes is part of Node.js, so it requires no external dependencies. This makes it ideal for Node.js environments where minimal dependencies are desired.
  • ethers.randomBytes requires the installation of the ethers.js library, which is primarily designed for blockchain-related projects. This is useful if you're already working with Ethereum, but it adds an external dependency to the project.
  • crypto.randomBytes:
  • Takes a single argument specifying the number of bytes.
  • Always requires a size input; no default value is provided.
  • ethers.randomBytes:
  • Optionally takes the number of bytes to generate.
  • If no argument is provided, it defaults to generating 32 bytes.

Oct 24, 2024
Read More

Discussion 0

Please sign in to join the discussion.

No comments yet. Be the first to share your thoughts!