Blockchain 2—Solidity smart contract development

Blockchain index directory

1. Basics of smart contracts

1. Contract structure and syntax

Smart contracts are self-executing contracts written in code that run on the blockchain. These contracts define events and corresponding behaviors that occur under specific conditions.

1.1 Smart contract structure

  1. Version Declaration: Smart contracts usually start with a declaration version, specifying the Solidity compiler version that the contract should use. For example:

    pragma solidity ^0.8.0;
    
  2. Contract Declaration: The Contract Declaration defines the name and main content of the contract. Contract is the basic unit of smart contract.

    contract MyContract {
        // 合约内容
    }
    
  3. State Variables: defines the variables of the contract state, and the values ​​of these variables will be persistently stored on the blockchain.

    uint public myVariable;
    
  4. Constructor: The constructor is executed when the contract is created and is used to initialize the state variables of the contract.

    constructor() {
        myVariable = 100;
    }
    
  5. Functions: Smart contracts contain functions that can be called, and these functions define the behavior of the contract.

    function setValue(uint newValue) public {
        myVariable = newValue;
    }
    

1.2 Smart contract syntax

  • Data Types: Solidity language supports multiple data types, such as uint, string, address, etc.

  • Control Structures: Including if statements, for loops, while loops, etc., used to control the logical execution flow of the contract.

  • Function Modifiers: allows some logic to be added before and after function execution, such as permission control, status checking, etc.

    modifier onlyOwner() {
        require(msg.sender == owner);
        _;
    }
    
  • Events: Events are used to record specific activities on the blockchain to facilitate monitoring and processing by external applications.

    event ValueChanged(uint newValue);
    
  • Error Handling: Use require and assert to handle error situations and ensure the contract status Consistency and security.

  • Inheritance: Solidity supports inheritance relationships between contracts, allowing contracts to reuse code.

    contract MyContract is AnotherContract {
        // 合约内容
    }
    

1.3 Example

// 版本声明
pragma solidity ^0.8.0;

// 合约声明
contract MyContract {
    // 状态变量
    uint public myVariable;

    // 构造函数
    constructor() {
        myVariable = 100;
    }

    // 函数,修改状态变量的值并触发事件
    function setValue(uint newValue) public {
        myVariable = newValue;
        emit ValueChanged(newValue);
    }

    // 事件声明
    event ValueChanged(uint newValue);
}

In this example, the contract contains a public state variablemyVariable, a constructor for initializing the variable, and a function that can modify the variablesetValue, and an eventValueChanged for recording variable changes. By calling the setValue function, you can modify the value of the state variable and trigger the corresponding event.

2. Data types and variables

In Solidity, data types and variables are used to store and manipulate information.

2.1 Data types

  1. Integer Types: is used to represent integers, which can be signed or unsigned.

    • uint: unsigned integer, like uint256.
    • int: signed integer, such as int32.
    uint256 public myUint = 42;
    
  2. Boolean Type: is used to represent true or false.

    bool public isTrue = true;
    
  3. Address Type: is used to store Ethereum addresses.

    address public myAddress = 0x5B38Da6a701c568545dCfcB03FcB875f56beddC4;
    
  4. String Type: is used to store text data.

    string public myString = "Hello, World!";
    
  5. Dynamic Arrays: Arrays can store multiple elements of the same type.

    uint[] public myArray;
    
  6. Mapping: is used to associate key-value pairs.

    mapping(address => uint) public balances;
    

2.2 Variables

  1. State Variables: Contract status stored on the blockchain.

    uint public myStateVariable = 123;
    
  2. Local Variables: Variables declared inside a function only exist during the execution of the function.

    function myFunction() public {
        uint localVar = 456;
        // 在此使用局部变量
    }
    
  3. Global Variables: including msg.sender, msg.value, etc., providing information about transactions and blocks Information.

    address public sender = msg.sender;
    

2.3 Example

Simple smart contract containing various data types and variables:

pragma solidity ^0.8.0;

contract DataTypesAndVariables {
    // 整数类型
    uint256 public myUint = 42;

    // 布尔类型
    bool public isTrue = true;

    // 地址类型
    address public myAddress = 0x5B38Da6a701c568545dCfcB03FcB875f56beddC4;

    // 字符串类型
    string public myString = "Hello, World!";

    // 动态数组
    uint[] public myArray;

    // 映射
    mapping(address => uint) public balances;

    // 状态变量
    uint public myStateVariable = 123;

    // 函数使用局部变量
    function myFunction() public {
        uint localVar = 456;
        // 在此使用局部变量
    }

    // 全局变量
    address public sender = msg.sender;
}

3. Control structures and functions

3.1 Control structure

  1. if statement: allows different code blocks to be executed based on conditions.

    function checkValue(uint value) public {
        if (value > 50) {
            // 执行某些操作
        } else {
            // 执行其他操作
        }
    }
    
  2. for loop: allows the same block of code to be executed multiple times.

    function iterate(uint times) public {
        for (uint i = 0; i < times; i++) {
            // 执行循环中的操作
        }
    }
    
  3. while loop: Repeatsly executes a block of code while a condition is true.

    function repeatUntil(uint target) public {
        uint i = 0;
        while (i < target) {
            // 执行循环中的操作
            i++;
        }
    }
    
  4. do-while loop: Execute a block of code and then repeat based on a condition.

    function doWhile(uint target) public {
        uint i = 0;
        do {
            // 执行循环中的操作
            i++;
        } while (i < target);
    }
    

3.2 Function

  1. Function declaration and calling: Define and call reusable blocks of code.

    function add(uint a, uint b) public pure returns (uint) {
        return a + b;
    }
    
    // 调用
    uint result = add(3, 5);
    
  2. Function modifier: Attach some logic before and after the function is executed.

    modifier onlyOwner() {
        require(msg.sender == owner);
        _;
    }
    
    function changeOwner(address newOwner) public onlyOwner {
        owner = newOwner;
    }
    
  3. Internal functions: Only visible inside the contract.

    function internalFunction() internal {
        // 执行内部函数中的操作
    }
    
  4. External function: can be called externally or triggered by external transactions.

    function externalFunction() external {
        // 执行外部函数中的操作
    }
    
  5. Payment function: Function that allows receiving ether.

    function payMe() public payable {
        // 执行接收支付的操作
    }
    
  6. View functions and pure functions: View functions will not modify the state, and pure functions will not read the state.

    function viewFunction() public view returns (uint) {
        // 执行视图函数中的操作
    }
    
    function pureFunction(uint a, uint b) public pure returns (uint) {
        return a * b;
    }
    

2. Advanced concepts of smart contracts

1. Events and logs

Events and logs allow smart contracts to communicate with the outside world and record important activities.

1.1 Events

  1. Event Statement: Events are used to record specific activities on the blockchain.

    event Transfer(address indexed _from, address indexed _to, uint _value);
    
  2. Trigger events: Trigger events in smart contracts to record specific activities.

    function transfer(address _to, uint _value) public {
        // 执行转账操作
        emit Transfer(msg.sender, _to, _value);
    }
    
  3. Listening to events: External applications can listen to events to get notifications of specific activities in the contract.

    contractInstance.Transfer({
          
          }, function(error, event) {
          
          
        // 处理事件
    });
    

1.2 Logging

  1. Use logs: Record important information in smart contracts.

    function myFunction(uint param) public {
        // 记录日志
        emit Log("Function executed", param);
    }
    
  2. View logs: View the recorded log information through the Ethereum blockchain browser or specific tools.

1.3 The role of events and logs

  • Recording status changes: Record changes in contract status through events and logs, such as fund transfers or important operation executions.
  • External notifications: Allows external applications to listen to events and logs in order to respond promptly to activities in the smart contract.
  • Data Analysis: Recorded events and logs can be used for data analysis, auditing, and tracking the history of specific transactions or operations.

In actual smart contract projects, events and logs are usually used to record important transactions, state changes, or key information for contract execution. By using events and logs, the contract's transparency, traceability, and ability to interact with the outside world can be enhanced.

2. Exception handling

Exception handling allows smart contracts to take appropriate measures when an error occurs or conditions are not met, improving the robustness and security of the contract.

2.1 Exception Handling

  1. Throwing Exceptions: In the contract, use revert or require to throw exceptions .

    function requireExample(uint x) public pure {
        require(x > 0, "X must be greater than zero");
        // 继续执行操作
    }
    

    If the condition is not met,require will throw an exception and roll back the state.

  2. Customized exception information: When an exception is thrown, a custom error message can be provided.

    function customRevert(uint x) public pure {
        require(x != 42, "The value cannot be 42");
        // 继续执行操作
    }
    
  3. Handling exceptions: When calling contract functions, exceptions can be caught and appropriate measures taken.

    try {
          
          
        contractInstance.requireExample(0);
    } catch (error) {
          
          
        // 处理异常,例如输出错误消息或执行备用操作
    }
    
  4. State rollback: When an exception occurs, the contract's state will be rolled back to the state before the exception to ensure the consistency of the contract state.

2.2 Specific examples

Simple smart contract including exception handling:

pragma solidity ^0.8.0;

contract ExceptionHandlingExample {
    address public owner;

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

    function setOwner(address newOwner) public onlyOwner {
        require(newOwner != address(0), "Invalid new owner address");
        owner = newOwner;
    }

    function withdraw(uint amount) public onlyOwner {
        require(amount > 0, "Withdrawal amount must be greater than zero");
        // 执行提现操作
    }
}

In this example, theonlyOwner modifier is used to ensure that only the owner of the contract can perform certain actions. In the setOwner and withdraw functions, use require to verify the precondition. If the condition is not met, an exception will be thrown and the state will be rolled back.

3. Interaction with external contracts

The interaction of smart contracts with external contracts is an important aspect in blockchain projects. This interactivity enables contracts to call the functions of other contracts, thereby enabling more complex and powerful applications.

  1. Contract Address: On Ethereum, each deployed contract has a unique contract address. This address can be used to access and call the contract's functions.

  2. External contract reference: In Solidity, you can access functionality by declaring an external contract reference in a contract.

    contract ExternalContract {
        function externalFunction() public pure returns (uint) {
            return 42;
        }
    }
    
    contract MyContract {
        ExternalContract public externalContract;
    
        constructor(address externalContractAddress) {
            externalContract = ExternalContract(externalContractAddress);
        }
    
        function interactWithExternal() public view returns (uint) {
            return externalContract.externalFunction();
        }
    }
    
  3. Call external contract functions: Through external contract references, you can call its public functions.

    function interactWithExternal() public view returns (uint) {
        return externalContract.externalFunction();
    }
    
  4. Passing parameters and receiving return values: When calling an external function, you can pass parameters and receive return values.

    function interactWithExternalWithParams(uint param) public view returns (uint) {
        return externalContract.externalFunctionWithParams(param);
    }
    
  5. Pay and receive Ether: If the external contract contains a payment function, you can send Ether and receive payment from the external contract by calling it.

    function sendEtherToExternal() public payable {
        externalContract.receiveEther{value: msg.value}();
    }
    
  6. Handling exceptions: When calling external functions, consider using exception handling mechanisms to deal with possible errors and exceptions.

    function interactWithExternalSafely() public view returns (uint) {
        try externalContract.externalFunction() returns (uint result) {
            return result;
        } catch (bytes memory error) {
            // 处理异常,例如输出错误消息或执行备用操作
            return 0;
        }
    }
    
  7. Events and logging: Use events and logging to record important activities and state changes when interacting with external contracts.

  8. Permission control: When calling external contract functions, ensure that you have sufficient permissions and use appropriate permission control mechanisms.

Guess you like

Origin blog.csdn.net/weixin_49015143/article/details/134875462