Solidity Basics

1. Data Types and Variables

Solidity, like other programming languages, has a variety of data types and variables used to store and manipulate data. Understanding these basics is crucial for writing smart contracts.

  • Primitive Data Types:

    • uint: Unsigned integer (positive only).

    • int: Signed integer (can be positive or negative).

    • bool: Boolean value (true or false).

    • address: Represents a 20-byte Ethereum address.

    • bytes: Dynamically-sized byte array.

    • string: Dynamically-sized UTF-8 encoded string.

    uint256 myNumber = 42;
    bool isActive = true;
    address myAddress = 0x1234567890abcdef1234567890abcdef12345678;
    string myString = "Hello, Solidity!";

2. Functions

Functions in Solidity are similar to functions in other programming languages. They define a piece of code that can be called and executed.

  • Basic Function Syntax:

    function multiply(uint256 a, uint256 b) public pure returns (uint256) {
        return a * b;
    }
    • public: The function can be called both internally and externally.

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

3. Visibility Specifiers

Visibility specifiers control how and where functions and state variables can be accessed.

  • Types of Visibility:

    • public: Accessible externally and internally.

    • private: Accessible only within the contract that defines it.

    • internal: Accessible within the contract and contracts deriving from it.

    • external: Accessible only from outside the contract.

4. Modifiers

Modifiers are used to change the behavior of functions. They allow you to add preconditions to functions.

  • Example of a Modifier:

    modifier onlyOwner() {
        require(msg.sender == owner, "Not the contract owner");
        _;
    }
    
    function changeOwner(address newOwner) public onlyOwner {
        owner = newOwner;
    }
    • _: The placeholder for the function's body.

5. Custom Modifiers

You can create custom modifiers to enforce specific rules within your contract.

  • Example:

    modifier isAdult(uint256 age) {
        require(age >= 18, "Not an adult");
        _;
    }
    
    function enterBar(uint256 age) public isAdult(age) {
        // code for entering the bar
    }

6. Constructors

Constructors are special functions that are executed only once when a contract is deployed. They are typically used to initialize contract state.

  • Example:

    contract MyContract {
        address public owner;
    
        constructor() {
            owner = msg.sender;
        }
    }

7. Global Variables

Solidity provides several global variables that can be accessed within contracts.

  • Examples:

    • msg.sender: The address of the caller.

    • msg.value: The amount of Ether sent with the transaction.

    • block.timestamp: The current block's timestamp.

    • block.number: The current block number.

8. Operators

Solidity supports standard operators like arithmetic, comparison, and logical operators.

  • Examples:

    • Arithmetic: +, -, *, /, %

    • Comparison: ==, !=, >, <, >=, <=

    • Logical: &&, ||, !

9. Conditionals

Conditionals are used to perform different actions based on different conditions.

  • Example:

    function checkNumber(uint256 num) public pure returns (string memory) {
        if (num > 10) {
            return "Greater than 10";
        } else {
            return "10 or less";
        }
    }

10. Arrays

Arrays in Solidity can be of fixed or dynamic size.

  • Example:

    uint256[] public numbers;
    
    function addNumber(uint256 num) public {
        numbers.push(num);
    }

11. Mappings

Mappings are key-value pairs where each unique key is mapped to a single value.

  • Example:

    mapping(address => uint256) public balances;
    
    function updateBalance(address user, uint256 newBalance) public {
        balances[user] = newBalance;
    }

12. Structs

Structs allow you to create more complex data types by grouping multiple variables.

  • Example:

    struct User {
        string name;
        uint256 age;
    }
    
    User public user;
    
    function setUser(string memory name, uint256 age) public {
        user = User(name, age);
    }

13. Events

Events are used to log information on the blockchain, which can be listened to by off-chain applications.

  • Example:

    event UserCreated(address indexed userAddress, string name);
    
    function createUser(string memory name) public {
        emit UserCreated(msg.sender, name);
    }

14. Ether and Payments

Solidity allows contracts to handle Ether, the native currency of Ethereum.

  • Example:

    function sendEther(address payable recipient) public payable {
        recipient.transfer(msg.value);
    }

15. Errors

Solidity allows you to define custom errors to save gas and improve readability.

  • Example:

    error NotEnoughFunds(uint256 available, uint256 required);
    
    function withdraw(uint256 amount) public {
        if (amount > address(this).balance) {
            revert NotEnoughFunds(address(this).balance, amount);
        }
    }

16. Inheritance

Solidity supports inheritance, allowing you to create new contracts based on existing ones.

  • Example:

    contract Parent {
        function sayHello() public pure returns (string memory) {
            return "Hello from Parent";
        }
    }
    
    contract Child is Parent {
        function sayHelloFromChild() public pure returns (string memory) {
            return "Hello from Child";
        }
    }

17. Calling Other Contracts

You can call functions from other contracts using either call or interface-based method calls.

  • Example:

    contract ExternalContract {
        function externalFunction() public pure returns (string memory) {
            return "Called from another contract";
        }
    }
    
    contract MyContract {
        ExternalContract externalContract;
    
        constructor(address _externalContractAddress) {
            externalContract = ExternalContract(_externalContractAddress);
        }
    
        function callExternalFunction() public view returns (string memory) {
            return externalContract.externalFunction();
        }
    }

18. Interfaces

Interfaces define the functions that must be implemented by a contract but do not contain any implementation themselves.

  • Example:

    interface IERC20 {
        function totalSupply() external view returns (uint256);
        function balanceOf(address account) external view returns (uint256);
        function transfer(address recipient, uint256 amount) external returns (bool);
    }
    
    contract MyToken is IERC20 {
        // Implement the functions defined in the interface
    }

Last updated