# Solidity零基础速学

By [Benson](https://paragraph.com/@bensonxu) · 2023-08-27

---

配套视频教程

[https://www.youtube.com/@benson8836/featured](https://www.youtube.com/@benson8836/featured)

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 uintUnsupported embed; 
            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 uintUnsupported embed;
            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 uintpUnsupported embed;
            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();
        }    
    }

---

*Originally published on [Benson](https://paragraph.com/@bensonxu/solidity)*
