Solidity 学习

Posted LiaoBin0608

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Solidity 学习相关的知识,希望对你有一定的参考价值。

这里写自定义目录标题

Solidity 与智能合约

Solidity 是一门面向合约,为实现智能合约而创建的高级编程语言
智能合约:


“一个智能合约是一套以数字形式定义的承诺(promises),包括合约参与方可以在上面执行这些承诺的协议。”

智能合约的本质:数字话合同
特点:代码代替人仲裁和执行合同,同时能够触发支付

Solidity 基础语法

数量类型

  • 值类型(值传递)
    • bool
      • true/false
        • 定义形式
          • bool flag:
          • bool flag = false:
    • 整形
      • 有符号整型 有正负 — 默认 int 是int256
      • 无符号整型 无正负---- 默认uint 是uint256
      • 以8位为区间
        • int8、int16、int24。。直到int256
        • uint同理,也是以8位为区间
    • 地址
      • balance
      • transfer
        -
    • 定长数组(字节类型)
      • byte1…byte32
    • 枚举
      • enum
    • 函数
      • 函数签名(返回值,参数类型,修饰符)
      • view/constant/pure
      • payable
      • 访问可见性 public/private
      • 返回值 returns
  • 引用类型(指针传递)
    • 字符串
    • 不定长数组
    • 数组
    • 枚举
    • 映射 mapping
    • 结构体

值传递和引用传递
值传递:值变了在传递过程中讲数值完整的copy一份,在赋值给新的变量,这种方式需要重新开辟新的内存空间, 两个变量完全独立,互不影响,修改一个不会影响到另外一个,缺点就是效率低
引用类型:solidity没有指针类型,对于复杂的结构进行高效传递方式是使用关键字storage进行修饰,简单来说,如果在变量之前添加storage就是引用传递,不加就是值传递,但是只对复杂类型有效,复杂类型,占用空间较大,所以考虑通过引用传递

Solidity 编译工具

https://remix.ethereum.org/#optimize=false&runs=200&evmVersion=null&version=soljson-v0.8.7+commit.e28d00a7.js

函数的关键字

修饰符说明
public共有,任何人(拥有以太坊账户的)都可以调用。
private私有,只有智能合约内部可以调用
external仅合约外部可以调用,合约内部可以使用this调用
interanl仅合约内部和继承的合约可以调用
view/constant函数会读取但是不会修改任何合约的状态变量
pure函数布使用任何智能合约的状态变量
payable调用函数需要付钱,钱付给了智能合约的账户
returns指定函数返回值

注释

可以使用单行注释 ( //) 和多行注释 ( //)。

HelloWorld.sol

// SPDX-License-Identifier: MIT
//SPDX(软件包数据交换) 许可证标识符:主要处理版权方面的法律问题

pragma  solidity 0.8.7;
//版本编译指示
// * 使用版本编译指示不会更改编译器的版本。它也不会启用或禁用编译器的功能。它只是指示编译器检查其版本是否与编译指示所需的版本匹配。如果不匹配,编译器会发出错误

// 定义合约用contract关键字
contract HelloWorld 

    string public myString = "hello world";
    // 

数据类型

// SPDX-License-Identifier: MIT
pragma  solidity 0.8.7;

contract ValueTypes 

    // 布尔
    bool public b = true;

    // uint 无符号整数,即正整数
    uint public u = 123; // uint = uint256,(0, 2**256-1)    
                         //        uint8, (0,2**8-1)
                         //        uint16,(0,2**16-1)
    
    // int 有符号整数,即负整数
    int public i = -123; // int = int256, -2**255 to 2*255-1

	// 获取int的最小值
    int public minInt = type(int).min;
    // 获取int的最大值
    int public maxInt = type(int).max;


    // address
    address public addr = 0xAb8483F64d9C6d1EcF9b849Ae677dD3315835cb2;

    // //byte
    // bytes32 public b32 = 0xAb8483F64d9C6d1EcF9b849Ae677dD3315835cb26123;



函数简介

// SPDX-License-Identifier: MIT
pragma  solidity 0.8.7;

contract FunctionIntro 

    // external : 外部函数
    // pure: 纯函数,不能读取状态变量和修改状态变量
    // returns: 返回值,可以是多个
    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 ;
    


变量

// SPDX-License-Identifier: MIT
pragma  solidity 0.8.7;


contract Variables 

    // 状态变量、局部变量、全局变量
    // 全局变量
    function globalVars() external view returns(address, uint, uint)
        address sender = msg.sender;
        uint timestamp = block.timestamp;
        uint blockNum = block.number;

        return (sender, timestamp, blockNum);
    

    // 状态变量
    uint public myUint = 123; // 如果不写修改方法,这个变量的值将永久存在区块链

    uint public i;
    bool public b;
    address public myAddress;


    function foo() external 
        // 局部变量
        // uint notStateVariable = 456;
        uint x = 123;
        bool f = false;

        x += 456;
        f = true;

        i = 123;
        b = true;
        myAddress = address(1);
    

只读函数

// SPDX-License-Identifier: MIT
pragma  solidity 0.8.7;

// view 修饰的函数可以读取状态变量,但是不能修改
// pure 修饰的函数,不可读取状态变量,也不能修改
contract ViewAndPureFunctions 

    uint public num;

    function ViewFunc() external view returns (uint)
        return num;
    


    function PureFunc() external pure returns (uint)
        // return num;
        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 ;
    


默认值

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

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


常量

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

contract Constants 
    address public constant MY_ADDRESS = 0xAb8483F64d9C6d1EcF9b849Ae677dD3315835cb2;
    uint public constant MY_UINT = 123;

If-Else

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


contract IfElse

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

    function ternary(uint _x) external pure returns (uint)
        // if (_x < 10)
        //     return 1;
        // 
        // return 2;
        // 三元运算符
        return  _x < 10 ? 1 : 2;

    

ForAndWhile

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


contract ForAndWhileLoops
    function loops() external pure 
        for (uint i = 0; i < 10; i++)
            if (i == 3)
                continue;
            
            if (i == 5)
                break;
            
        
        uint j = 0;
        while (j < 10) 
            j++;
        
    

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

Error

// SPDX-License-Identifier: MIT
pragma  solidity ^0.8.7;
// require ,
// revert,
// assert
// custom
contract ErrorDemo 

    function testRequire(uint _i) public pure 
        require (_i < 10, "i > 10");
    
    
    function testRevert(uint _i) public pure 
        if (_i > 10)
            revert ( "i > 10");
        
        
    
    uint public num = 123;
    function testAssert() public view 
        assert (num == 123);
    

    error MyError(address caller, uint i);

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



构造函数

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


contract Construct
    address public owner;
    uint public x;

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

返回值

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


contract FunctionOutputs
    // 返回多个值
    function returnMany() public pure returns (uint , bool)
        return (1, false);
    

    // 返回值命名
    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 destructingAssigment() public pure 
        // 调用2个返回值
        (uint x, bool b) = returnMany();
        // 调用单个返回值
        (,bool _b) = returnMany();
    


0基础学习solidity开发智能合约-初识solidity

本篇课程开始,我们来学习一下如何使用solidity开发智能合约,由于博主对于solidity的学习,也是自学的,所以一些不足或有纰漏之处还望指出,大家共同进步,本系列课程会分很多节课讲述,从入门到进阶、实战,在课程最后,我们会通过所学知识来搭建几个不同类型的智能合约如Token合约、NFT合约等等,感兴趣的小伙伴加个关注吧。

一、什么是智能合约

这里引用一段摘自网络的话语来解释一下 

智能合约是区块链中四大核心技术之一,这个概念最开始是在1994年,由知名密码学家尼克·萨博提出的,可由于技术以及其他的一些原因一直都没有落地,哪怕到了今天,智能合约已经在互联网中很多的应用,比如自动还款,无人机售货等等,也多是局限在个人和机构之间的智能合约,个人和个人之间的智能合约几乎没有,原因就在于“信任”问题,我们会发现,只要谈起合约,大多数都是陌生人跟陌生人之间有这种需求,而且还跟钱有关系,如果在没有第三方做担保的情况下我们之间做了个约定,我把钱打给你,结果你毁约了,不承认怎么办?所以智能合约一直没办法在个人与个人之间普及,后来随着区块链的出现,人们发现,区块链与智能合约十分的契合,因为区块链的很多特点,比如去中心化,数据的不可篡改等,可以从技术的角度,去解决陌生人之间的信任问题,这才使智能合约大规模的应用成为可能,这一阶段的开始以以太坊的诞生为标志。在区块链的基础上,以太坊应用了智能合约技术。智能合约使得以太坊可以实现更多功能,智能合约是一个非常重要的应用,于是,慢慢的,智能合约就成了区块链的核心技术之一。 

总结来说,智能合约就是一个写好的程序脚本,它会在一个虚拟机上运行,且不受外界的干扰,所以能保证最大化的公平、公正、公开性。

以太坊作为区块链2.0的代表,它的设计理念和底层系统设计,让它逐渐被大众所认可,从现在开始我们就准备在以太坊上进行智能合约的开发(你可能听过bsc、trc、matic 等等区块链,它们都是基于以太坊虚拟机EVM开发的区块链网络,所以在以太坊上编写的智能合约,在这些网络上均可以使用)

二、什么是solidity

solidity是用于实现智能合约的一种面向合约的高级编程语言,solidity受到C++、Python和JavaScript的影响,被设计为可运行在以太坊虚拟机(EVM)上,所以用户无需担心代码的可移植性和跨平台等问题。solidity是一种静态类型的语言,支持继承、库引用等特性,并且用户可自定义复杂的结构类型。

 三、合约文件

一个简单的合约文件大概如下图所示:

我们来看一段示例代码,里面有一些简单的注释,可以结合着查看

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;  //solidity编译版本声明

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";  //第三方文件引入

//合约声明
contract DemoToken is ERC20 
    address owner; //地址变量
    uint256 total = 5000000 * 10**18; //数字变量

    //构造器
    constructor() ERC20("demoToken", "DT") 
        owner = msg.sender;
        _mint(msg.sender, total);
    

    //方法
    function getTotal() public view onlyOwner returns (uint256) 
        return total;
    

    //修饰符
    modifier onlyOwner() 
        require(msg.sender == owner);
        _;
    

  • 首先,第一行表示代码许可说明,可选项很多,大家可以自行查询
// SPDX-License-Identifier: MIT
  •  第二行声明了我们编译合约代码的solidity版本,其中^表示最低版本为0.8.17,当前该合约也不会被0.9.0以上版本编译
pragma solidity ^0.8.17;  //solidity编译版本声明
  • 第三行,我们引入了一个其他合约文件,solidity里允许我们引用其他的合约文件,这个暂时先不展开讲解,后面课程里我们会具体说明,大家先有个印象即可
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";  //第三方文件引入
  •  第四行,我们声明了一个合约对象,它是以 contract开头的结构 (is ERC20 表示继承了ERC20合约,后面详细讲解)
contract DemoToken is ERC20 
  • 第五、六行,我们定义了两个变量,关于solidity的变量类型,下一章我们会仔细讲解
    address owner; //地址变量
    uint256 total = 5000000 * 10**18; //数字变量
  • 然后我们声明了一个结构体,它在合约部署的时候会调用,我们可以在里面写一些初始化逻辑,如变量赋值、方法调用等
constructor() ERC20("demoToken", "DT") 
        owner = msg.sender;
        _mint(msg.sender, total);
    
  •  接着,我们声明了一个函数,仔细看它的声明语法有点类似JavaScript,但是后面一些地方却与JavaScript又有一些不同,它多了一些 public、view 等字段(关于这些多出来的字段,后面也会进行详细介绍)
 //方法
    function getTotal() public view onlyOwner returns (uint256) 
        return total;
    
  •  最后,我们定义了一个修饰符,它在合约里可以说是有着举足轻重的地位,在这里大家有个印象即可,在后面的课程里都会一一介绍
  //修饰符
    modifier onlyOwner() 
        require(msg.sender == owner);
        _;
    

通过本节课程的学习,我们先是简单了解了智能合约的概念,接着又对一个智能合约的组成部分进行了简单的分析,让我们对智能合约有了一个基本的概念,下一节课,我们将要学习一下solidity里的变量类型有哪些

 

以上是关于Solidity 学习的主要内容,如果未能解决你的问题,请参考以下文章

区块链 solidity 零知识证明DApp开发实践身份证明/以太坊

区块链以太坊学习资源(by quqi99)

区块链以太坊学习资源(by quqi99)

《solidity学习笔记》chapter 2-solidity基础知识

以太坊开发完整去中心化应用 —— 区块链投票系统

以太坊区块链 Solidity solc是什么