Solidity零基础速学
August 27th, 2023

配套视频教程

1.Hello World

// SPDX-License-Identifier: MIT
// compiler version must be greater than or equal to 0.8.10 and less than 0.9.0
pragma solidity ^0.8.10;

contract HelloWorld {
    string public greet = "Hello World!";
}

2.类型和值

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

contract Primitives {
    bool public boo = true;

    /*
    uint stands for unsigned integer, meaning non negative integers
    different sizes are available
        uint8   ranges from 0 to 2 ** 8 - 1
        uint16  ranges from 0 to 2 ** 16 - 1
        ...
        uint256 ranges from 0 to 2 ** 256 - 1
    */
    uint8 public u8 = 1;
    uint public u256 = 456;
    uint public u = 123; // uint is an alias for uint256

    /*
    Negative numbers are allowed for int types.
    Like uint, different ranges are available from int8 to int256
    
    int256 ranges from -2 ** 255 to 2 ** 255 - 1
    int128 ranges from -2 ** 127 to 2 ** 127 - 1
    */
    int8 public i8 = -1;
    int public i256 = 456;
    int public i = -123; // int is same as int256

    // minimum and maximum of int
    int public minInt = type(int).min;
    int public maxInt = type(int).max;

    address public addr = 0xCA35b7d915458EF540aDe6068dFe2F44E8fa733c;

    /*
    In Solidity, the data type byte represent a sequence of bytes. 
    Solidity presents two type of bytes types :

     - fixed-sized byte arrays
     - dynamically-sized byte arrays.
     
     The term bytes in Solidity represents a dynamic array of bytes. 
     It’s a shorthand for byte[] .
    */
    bytes1 a = 0xb5; //  [10110101]
    bytes1 b = 0x56; //  [01010110]

    // Default values
    // Unassigned variables have a default value
    bool public defaultBoo; // false
    uint public defaultUint; // 0
    int public defaultInt; // 0
    address public defaultAddr; // 0x0000000000000000000000000000000000000000
}

3.函数

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

contract Function {
    function add(uint x, uint y) external pure returns (uint) {
        return x + y;
    }
    function sub(uint x, uint y) external pure returns (uint) {
        return x - y;
    }
}

4.状态变量

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.21;
//function <function name>(<parameter types>) {internal|external|public|private} [pure|view|payable] [returns (<return types>)]
contract StateVariables {
    uint public myUint = 123;

    function foo() external pure returns(int) {
        int s = 321;
        return s;
    }
}

5.局部变量

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.21;
//function <function name>(<parameter types>) {internal|external|public|private} [pure|view|payable] [returns (<return types>)]
contract StateVariables {
    uint public i;
    bool public b;
    address public myAddress;
    function foo() external {
            uint x = 123;
            bool f = false; 
            x +=456;
            f= true;
            i = 321;
            b = true;
            myAddress = address(1);                  
    }

}

6.全局变量

contract GlobalVariables {
    function globalVars() external view returns (address, uint, uint) {
        address sender = msg.sender;
        uint timestamp = block.timestamp;
        uint blockNum = block.number;
        return (sender,timestamp,blockNum);              
    }

}

7.只读函数

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

contract ViewAndPureFunction {
    uint public num;

    function viewFunc() external view returns (uint) {
        return num;
    }
    function pureFunc() external pure returns (uint) {
        return 1;
    }
    function addToNum(uint x) external view returns (uint) {
        return num + x;
    }
    function add(uint x, uint y) external pure returns (uint) {
        return x + y;
    }
}

8.计数器合约

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

contract Counter {
    uint public count;

    function inc() external {
        count += 1;
    }

    function dec() external {
        count -= 1;
    }

}

9.默认值

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

contract DefaultValues {
    bool public b; // false
    uint public u; // 0
    int public i; // 0
    address public a; // 0x0000000000000000000000000000000000000000
    bytes32 public b32; // 0x0000000000000000000000000000000000000000000000000000000000000000
}

10.常量

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

contract Constants {
    address public constant MY_ADDRESS = 0x5B38Da6a701c568545dCfcB03FcB875f56beddC4;
    uint public constant MY_UINT = 123;
}

contract Var {
    address public MY_ADDRESS = 0x5B38Da6a701c568545dCfcB03FcB875f56beddC4;
}

11.结构控制

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

contract IfElse {
    function example(uint _x) external pure returns (uint) {
        if (_x < 10) {
            return 1;
        } else if (_x < 20) {
            return 2;
        } else {
            return 3;
        }
    }

    function ternary(uint _x) external pure returns (uint) {
        // if (_x < 10) {
        //     return 1;
        // }
        // return 2;
        return _x < 10 ? 1 : 2;
    }

}

12.循环

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

contract ForAndWhileLoops {
    function loops() external pure {
        for (uint i = 0; i< 10; i++) {
            // code
            if (i == 3) {
                continue;
            }
            // more code
            if (i == 5) {
                break;
            }
        }

        uint j = 0;
        while (j < 10) {
            // code
            j++;
        }
    }

    function sum(uint _n) external pure returns (uint) {
        uint s;
        for (uint i = 1; i <= _n; i++) {
            s += i;
        }
        return s;
    }
}

13.报错控制

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

contract testError {
    function testRequire(uint _i) public pure {
        require(_i <= 10, "i > 10");
        // code     
    }

    function testRevert(uint _i) public pure {
        if (_i > 10) {
            revert("i > 10");
        }
    }

    uint public num = 123;

    function testAssert() public view {
        assert(num == 123);
    }

    function foo(uint _i) public {
        num += 1;
        require(_i < 10);
    }

    function testCustomError(uint _i) public pure {
        require(_i <= 10, "error msg xxxxxxxxxxxxxxxxxxxxxx");
        // code     
    }

    error MyError(address caller, uint i);

    function  testCustomSetError(uint _i) public view {
        if (_i > 10) {
            revert MyError(msg.sender, _i);
        }
    }
}

14.函数修改器

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

// basic input sandwich

// 原版本
contract FunctionModifier {
    bool public paused;
    uint public count;

    function setPause(bool _paused) external {
        paused = _paused;
    }

    function inc() external {
        require(!paused, "paused");
        count += 1;
    }

     function dec() external {
        require(!paused, "paused");
        count -= 1;   
    }
}

// 使用修改器后
contract FunctionModifier {
    bool public paused;
    uint public count;

    function setPause(bool _paused) external {
        paused = _paused;
    }
    
    modifier whenNotPaused() {
        require(!paused, "paused");
        _;
    }

    function inc() external whenNotPaused {
        count += 1;
    }

    function dec() external whenNotPaused{
        count -= 1;   
    }   


}

// 带参数修改器

contract FunctionModifier {
    bool public paused;
    uint public count;

    function setPause(bool _paused) external {
        paused = _paused;
    }
    
    modifier cap(uint _x) {
        require(_x < 100, "x > 100");
        _;
    
    
    }

    function incBy(uint _x) external whenNotPaused cap(_x) { 
        count += _x
    }


}

//三明治

contract FunctionModifier {
    bool public paused;
    uint public count;

    function setPause(bool _paused) external {
        paused = _paused;
    }
    
    modifier sandwitch() {
        // code
        count += 10;
        _;
        count *= 2;
    }

    function foo() external sandwitch{ 
        count += 1;
    }


}

15.构造函数

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

contract Constructor {
    address public owner;
    uint public x;

    constructor(uint _x) {
        owner = msg.sender;
        x = _x;
    }
}

16.Ownable

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

contract Ownable {
    address public owner;

    constructor() {
        owner = msg.sender;
    }

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

    function setOwner(address _newOwner) external onlyOwner {
        require(_newOwner != address(0), "invalid sender");
        owner = _newOwner;
    }

    function onlyOwnerCanCallThisFunc() external onlyOwner {
        // code
    }

    function anyOneCanCall() external {
        // code 
    } 

}

17.函数返回值

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

contract FunctionOutputs {
    function returnMany() public pure returns (uint, bool) {
        return (1, true);
    }

    function named() public pure returns (uint x, bool b) {
        return (1, true);
    }

    function assigned() public pure returns (uint x, bool b) {
        x = 1;
        b = true;
    }

    function destructingAssigments() public pure returns {
        (uint x, bool b) = returnMany();
        (, bool b) = returnMany();
    }

}

18.数组

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

contract Array {
    uint[] public nums = [1, 2, 3];
    uint[3] public numsFixed = [4, 5, 6];

    function examples() external {
        nums.push(4); // [1,2,3,4]
        uint x = nums[1];
        nums[2] = 777; // [1,2,777,4]
        delete nums[1]; // [1,0,777,4]
        nums.pop; // [1,0,777]
        uint len = nums.length;

        // create in memory 内存中只能创建定长数组,不能改变长度
        uint[] memory a = new uint[](5); 
        a[1] = 123;
    }

    function returnArray() external view returns (uint[] memory) {
        return nums;
    }

}


contract Array2 {
 
    // 通过元素移动位置删除数组元素(gas高,但顺序不乱)

    uint[] public arr;
    // [1,2,3] -remove(1)->[1,3,3]->[1,3]
    // [1,2,3,4,5,6] -removed(2)->[1,2,4,5,6,6]->[1,2,4,5,6]
    function remove(uint _index) public {
        require(_index < arr.length, "index out of bound");
        for (uint i = _index; i < arr.length - 1; i++) {
            arr[i] = arr[i + 1];           
        }
        arr.pop();
    }

    function test() external {
        arr = [1, 2, 3, 4, 5];
        remove(2);
        assert(arr[0] == 1);
        assert(arr[1] == 2);
        assert(arr[2] == 4);
        assert(arr[3] == 5);
        assert(arr.length == 4);

        arr = [1];
        remove(0);
        // []
        assert(arr.length == 0);
    }
}



contract Array3 {
    uint[] public arr;
    // 通过元素替换删除数组元素 (gas低,但顺序打乱)
    // 【1,2,3,4】-remove2(1) -> 【1,4,3,4】 ->[1,4,3]
    function remove(uint _index) public {
        arr[_index] = arr[arr.length - 1];
        arr.pop();
    }

    function test2() external {
        arr = [1, 2, 3, 4];

        remove(1);
        // [1, 4, 3]
        assert(arr.length == 3);
        assert(arr[0] == 1);
        assert(arr[1] == 4);
        assert(arr[2] == 3);
    }
}

19.映射

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

contract Mapping {
    mapping(address => uint) public balances;
    mapping(address => mapping(address => bool)) public isFriend;

    function examples() external {
        balances[msg.sender] = 123;
        uint bal = balances[msg.sender];
        uint bal2 = balances[address(1)]; // 0

        balances[msg.sender] += 456;

        delete balances[msg.sender];

        isFriend[msg.sender][address(this)] = true;
    }

}

// 结合遍历和映射
contract IterableMapping {
    mapping(address => uint) public balances;
    mapping(address => bool) public inserted; // 地址是否存在
    address[] public keys;

    function set(address _key, uint _val) external {
        balances[_key] = _val;

        if (!inserted[_key]) {
            inserted[_key] = true;
            keys.push(_key);
        }
    }

    function getSize() external view returns (uint) {
        return keys.length;
    }
    
    function first() external view returns (uint) {
        return balances[keys[0]];
    }

    function last() external view returns (uint) {
        return balances[keys[keys.length - 1]];
    }    

    function get(uint _i) external view returns (uint) {
        return balances[keys[_i]];
    }

}

20.结构体

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

contract Structs {
    struct Car {
        string model;
        uint year;
        address owner;
    }

    Car public car;
    Car[] public cars;
    mapping(address => Car[]) public carsByOwner;

    function examples() external {
        Car memory toyota = Car("Toyota", 1990, msg.sender);
        Car memory lambo = Car({model:"Lamborghini", year:1980, owner: msg.sender});
        Car memory tesla;
        tesla.model = "Tesla";
        tesla.year = 2010;
        tesla.owner = msg.sender;

        cars.push(toyota);
        cars.push(lambo);
        cars.push(tesla);

        cars.push(Car("Ferrari", 2020, msg.sender));

        //取读
        Car memory _car = cars[0];
        _car.model;

        //连带状态变量修改(带指针)
        Car storage _car2 = cars[0];
        _car2.year = 1999;        
        delete _car2.owner;
        
        delete cars[1];
    }
}

21.枚举

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

contract Enum {
    enum Status {
        None, // 默认
        Pending,
        Shipped,
        Completed,
        Rejected,
        Canceled
    }

    Status public status;

    struct Order {
        address buyer;
        Status status;
    }

    Order[] public orders;

    //获取
    function get() view external returns (Status) {
        return status;
    }

    //修改  通过索引
    function set(Status _status) external {
        status = _status;
    }

    //修改  通过值
    function ship() external {
        status = Status.Shipped;
    }

    //重置
    function reset() external {
        delete status;
    }


    
}

22.存储位置

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

// storage memory calldata

contract DataLocations {
    struct MyStruct {
        uint foo;
        string text;
    }

    mapping(address => MyStruct) public myStructs;

    function examples() external {
        myStructs[msg.sender] = MyStruct({foo: 123, text: "bar"});

        MyStruct storage myStruct = myStructs[msg.sender];
        myStruct.text = "foo";//存储:全局变量myStructs也被改变

        MyStruct memory myStructReadOnly = myStructs[msg.sender];
        myStruct.text = "xxx";//内存:局部变量myStructs不会改变        
    }

    //calldata
    function examples(uint[] memory y, string memory s) external return (uint[] memory){
        myStructs[msg.sender] = MyStruct({foo: 123, text: "bar"});

        MyStruct storage myStruct = myStructs[msg.sender];
        myStruct.text = "foo";//全局变量myStructs也被改变

        MyStruct memory myStructReadOnly = myStructs[msg.sender];
        myStruct.text = "xxx";//全局变量myStructs不会改变       

        uint[] memory memArr = new uint[](3);
        memArr[0] = 234;
        return memArr
    }

    //calldata 只能用在参数中,更节省gas
    function examples(uint[] calldata y, string calldata s) external return (uint[] memory){
        myStructs[msg.sender] = MyStruct({foo: 123, text: "bar"});

        MyStruct storage myStruct = myStructs[msg.sender];
        myStruct.text = "foo";//全局变量myStructs也被改变

        MyStruct memory myStructReadOnly = myStructs[msg.sender];
        myStruct.text = "xxx";//全局变量myStructs不会改变       

        _internal(y);

        uint[] memory memArr = new uintp[](3);
        memArr[0] = 234;
        return memArr;

        function _internal(uint[] calldata y) private {
            uint x = y[0];
        }
    }



}

23.事件

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

contract Event {
    event Log(string message, uint val);
    event IndexLog(address indexed sender, uint val); // 最多三个索引

    function example() external {
        emit Log("foo", 1234); //写入方法
        emit IndexLog(msg.sender, 789);
    }

    event Message(address indexed _from, address index _to, string message);

    function sendMessage(address _to, string calldata message) external {
        emit Message(msg.sender, _to, message);
    }
}

24.继承

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

contract A{
    function foo() public pure virtual returns (string memory) {
        return "A";
    }

    function bar() public pure virtual returns (string memory) {
        return "A";
    }

    // more code

}

contract B is A {
    function foo() public pure override returns (string memory) {
        return "B";
    }

    function bar() public pure virtual override returns (string memory) {
        return "B";
    }

    // more code
}

contract C is B {

    function bar() public pure override returns (string memory) {
        return "C";
    }


}

25.多线继承

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

/* 从最基础到最派生,从前到后

   X
 / | 
Y  |
 \ |
   Z

// X-Y-Z

   X
 /   \
Y     A
|     |
|     B
 \   /
   Z 

// X-Y-A-B-Z

*/

contract X {
    function foo() public pure virtual returns (string memory) {
        return "X";
    }

    function bar() public pure virtual returns (string memory) {
        return "X";
    }

    function x() public pure returns (string memory) {
        return "X";
    }

}

contract Y is X {
    function foo() public pure virtual override returns (string memory) {
        return "Y";
    }

    function bar() public pure virtual override returns (string memory) {
        return "Y";
    }

    function y() public pure returns (string memory) {
        return "Y";
    }

}

contract Z is X, Y {
    function foo() public pure override(X, Y) returns (string memory) {
        return "Z";
    }

    function bar() public pure override(X, Y) returns (string memory) {
        return "Z";
    }

}

26.父级合约构造函数及函数调用

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

contract S {
    string public name;

    constructor(string memory _name) {
        name = _name;
    }
}

contract T {
    string public text;

    constructor(string memory _text) {
        text = _text;
    }
}

// 知道需要什么初始参数的情况下
contract U is S("s"), T("t") {

}

// 不知道初始参数需要开始的时候输入
contract V is S, T {
    constructor(string memory _name, string memory _text) S(_name) T(_text) {
    }
}

// 混合的情况
contract VV is S("s"), T {
    constructor(string memory _text) T(_text) {

    }
}

// 初始化的顺序是根据继承顺序
// S-T-V0
contract V0 is S, T {
    constructor(string memory _name, string memory _text) S(_name) T(_text) {
    }
}
// S-T-V1
contract V1 is S, T {
    constructor(string memory _name, string memory _text) T(_text) S(_name) {
    }
}
// T-S-V2
contract V2 is T, S {
    constructor(string memory _name, string memory _text) T(_text) S(_name) {
    }
}


//调用父级

contract E {
    event Log(string message);

    function foo() public virtual {
        emit Log("E.foo");
    }

    function bar() public virtual {
        emit Log("E.bar");
    }
}

contract F is E {
    function foo() public virtual override {
        emit Log("F.foo");
        E.foo();
    }

    function bar() public virtual override {
        emit Log("F.bar");
        super.bar();
    }
}

contract G is E {
    function foo() public virtual override {
        emit Log("G.foo");
        E.foo();
    }

    function bar() public virtual override {
        emit Log("G.bar");
        super.bar();
    }
}

contract H is F, G {
    function foo() public override(F, G) {
        F.foo;
    }

    function bar() public override(F, G) {
        super.bar();
    }    
}
Subscribe to Benson
Receive the latest updates directly to your inbox.
Nft graphic
Mint this entry as an NFT to add it to your collection.
Verification
This entry has been permanently stored onchain and signed by its creator.
More from Benson

Skeleton

Skeleton

Skeleton