⚡ TECH BLOG
Home
Blog
Tags
About
⚡

Powered by Next.js 15 & Modern Web Tech ⚡

Back to Home

Solidity Smart Contract Basics: Your First Contract

December 15, 2022
solidityblockchainethereumsmart-contracts
Solidity Smart Contract Basics: Your First Contract

Solidity Smart Contract Basics: Your First Contract

Solidity is the primary language for writing smart contracts on Ethereum. Let's learn the fundamentals.

Basic Contract Structure

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

contract SimpleStorage {
    // State variable
    uint256 public value;
    
    // Events
    event ValueChanged(uint256 newValue);
    
    // Functions
    function setValue(uint256 _value) public {
        value = _value;
        emit ValueChanged(_value);
    }
    
    function getValue() public view returns (uint256) {
        return value;
    }
}

Data Types

contract DataTypes {
    // Value types
    bool public isActive = true;
    uint256 public count = 100;  // Unsigned integer
    int256 public temperature = -10;  // Signed integer
    address public owner;  // Ethereum address
    bytes32 public data;  // Fixed-size bytes
    
    // Reference types
    string public name = "Hello";
    bytes public dynamicData;
    uint256[] public numbers;  // Dynamic array
    uint256[10] public fixedNumbers;  // Fixed array
    
    // Mappings
    mapping(address => uint256) public balances;
    mapping(address => mapping(address => uint256)) public allowances;
    
    // Structs
    struct User {
        string name;
        uint256 balance;
        bool isActive;
    }
    
    mapping(address => User) public users;
    
    // Enums
    enum Status { Pending, Active, Completed }
    Status public currentStatus;
}

Functions

contract Functions {
    uint256 private value;
    
    // View function - doesn't modify state
    function getValue() public view returns (uint256) {
        return value;
    }
    
    // Pure function - doesn't read or modify state
    function add(uint256 a, uint256 b) public pure returns (uint256) {
        return a + b;
    }
    
    // Payable function - can receive ETH
    function deposit() public payable {
        // msg.value contains sent ETH
    }
    
    // Function modifiers
    address public owner;
    
    modifier onlyOwner() {
        require(msg.sender == owner, "Not owner");
        _;  // Continue execution
    }
    
    function withdraw() public onlyOwner {
        // Only owner can call this
    }
}

Error Handling

contract ErrorHandling {
    uint256 public value;
    
    function setValue(uint256 _value) public {
        require(_value > 0, "Value must be greater than 0");
        value = _value;
    }
    
    function setValueRevert(uint256 _value) public {
        if (_value == 0) {
            revert("Value cannot be zero");
        }
        value = _value;
    }
    
    function assertExample(uint256 _value) public {
        assert(_value != type(uint256).max);  // Internal error
        value = _value;
    }
    
    // Custom errors (Solidity 0.8.4+)
    error InsufficientBalance(uint256 available, uint256 required);
    
    function withdraw(uint256 amount) public {
        if (amount > value) {
            revert InsufficientBalance(value, amount);
        }
        value -= amount;
    }
}

Inheritance

contract Ownable {
    address public owner;
    
    constructor() {
        owner = msg.sender;
    }
    
    modifier onlyOwner() {
        require(msg.sender == owner, "Not owner");
        _;
    }
}

contract Token is Ownable {
    mapping(address => uint256) public balances;
    
    function mint(address to, uint256 amount) public onlyOwner {
        balances[to] += amount;
    }
}

Events and Logs

contract Events {
    event Transfer(address indexed from, address indexed to, uint256 amount);
    event Approval(address indexed owner, address indexed spender, uint256 amount);
    
    function transfer(address to, uint256 amount) public {
        emit Transfer(msg.sender, to, amount);
    }
}

ERC-20 Token Example

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

contract MyToken {
    string public name = "My Token";
    string public symbol = "MTK";
    uint8 public decimals = 18;
    uint256 public totalSupply;
    
    mapping(address => uint256) public balanceOf;
    mapping(address => mapping(address => uint256)) public allowance;
    
    event Transfer(address indexed from, address indexed to, uint256 value);
    event Approval(address indexed owner, address indexed spender, uint256 value);
    
    constructor(uint256 _initialSupply) {
        totalSupply = _initialSupply * 10 ** uint256(decimals);
        balanceOf[msg.sender] = totalSupply;
    }
    
    function transfer(address to, uint256 value) public returns (bool) {
        require(balanceOf[msg.sender] >= value, "Insufficient balance");
        balanceOf[msg.sender] -= value;
        balanceOf[to] += value;
        emit Transfer(msg.sender, to, value);
        return true;
    }
    
    function approve(address spender, uint256 value) public returns (bool) {
        allowance[msg.sender][spender] = value;
        emit Approval(msg.sender, spender, value);
        return true;
    }
    
    function transferFrom(address from, address to, uint256 value) public returns (bool) {
        require(balanceOf[from] >= value, "Insufficient balance");
        require(allowance[from][msg.sender] >= value, "Insufficient allowance");
        
        balanceOf[from] -= value;
        balanceOf[to] += value;
        allowance[from][msg.sender] -= value;
        emit Transfer(from, to, value);
        return true;
    }
}

Best Practices

  1. Always specify pragma version
  2. Use events for important state changes
  3. Implement proper access control
  4. Handle errors gracefully
  5. Optimize for gas efficiency
  6. Write comprehensive tests

Conclusion

Solidity is a powerful language for writing smart contracts. Understanding these fundamentals will help you build secure and efficient decentralized applications.

Share:

💬 Comments