Solidity 大神之路之内功修炼第一章

欢迎来到Solidity大神之路之内功修炼第一章!在第扫盲章节中,我们介绍了Solidity的基本概念,本文将带你深入了解Solidity的核心语法与特性,帮助你掌握编写智能合约的基础知识。无论你是初学者还是有一定编程经验的开发者,这篇文章将为你提供清晰、实用的指导

 为了快速上手Solidity开发,我们选择 Remix IDE 作为主要开发工具。Remix是一个功能强大、基于浏览器的集成开发环境(IDE),支持Solidity合约的编写、编译、测试和部署。它无需安装本地环境,直接在浏览器中使用,专为Solidity智能合约设计,适合初学者和专业开发者

打开浏览器,访问  Remix

接下来在contracts 文件夹中,新建  HelloWorld.sol 文件,我将在代码中,详细讲解每一行代码 

SPDX 

// SPDX-License-Identifier: MIT

  从Solidity 0.6.8开始,建议在文件开头添加SPDX许可证标识符,表明代码的开源许可类型。最常用的是MIT许可证

  如果代码无许可证,使用UNLICENSED

  许可证标识符不会影响代码执行,但有助于代码共享和合规性

  关于SPDX许可证的详细介绍:  https://spdx.org/licenses

pragma

pragma solidity ^0.8.0;

 任意一个 Solidity 文件中,pragma 指令必须是在代码的第一行。Pragma 是一个指令,它告诉编译器应该使用哪个

 编译器版本将人类可读的 Solidity 代码转换为机器可读的字节码。Solidity 是一门新语言,更新频率很高,所以不

 同版本的编译器在编译代码时会产生不同的结果。当使用较新的编译器版本编译时,一些较旧的 solidity 文件会抛出

 错误或警告。在较大的项目中,当你使用像 Hardhat 这样的工具时,可能需要指定多个编译器版本,因为导入的

 solidity 文件或你依赖的库是为旧版本的 solidity 编写的

 Solidity官方版本控制和pragma说明:

   https://docs.soliditylang.org/en/latest/layout-of-source-files.html#version-pragma

 pragma 指令遵循语义化版本控制 (SemVer),SemVer 是一个系统,其中每个数字表示该版本中包含的更改的类型和范围

 如果你想要 SemVer 的实际操作解释,请查看:https://semver.org/

 pragma 更加详细的使用

(1) pragma solidity

   用于指定Solidity编译器版本。

   示例: pragma solidity ^0.8.0;

    版本范围说明:

    ^0.8.0         允许使用0.8.x版本(例如0.8.1、0.8.2),但不允许0.9.0或更高版本

    >=0.7.0 <0.9.0 允许使用0.7.0到0.8.x的版本

    >0.7.0 <=0.8.5 允许版本高于0.7.0但不超过0.8.5

    =0.8.0         等价于精确版本指定 0.8.0

    0.8.0          严格要求使用0.8.0版本

    ~0.8.1           允许0.8.1、0.8.2等,但不允许0.8.0(更低的版本)或 0.9.0(更高的版本)

    0.7.6 || ^0.8.0  允许使用0.7.6版本或0.8.x系列版本

    0.8.*            等价于 >=0.8.0 <0.9.0,允许0.8.x的任意版本

    0.*.*            等价于 >=0.0.0 <1.0.0,允许0.x.x的任意版本

    0.8              等价于 >=0.8.0 <0.9.0,允许0.8.x的任意版本

    0                等价于 >=0.0.0 <1.0.0,允许0.x.x的任意版本

  (2) pragma experimental

  用于启用实验性功能,这些功能可能不稳定,仅用于测试或开发。

  示例:pragma experimental ABIEncoderV2;

  这启用了ABI编码器V2,允许更复杂的数据结构(如动态数组)在函数调用中传递。

  注意:实验性功能在生产环境中需谨慎使用。

  (3) pragma abicoder

  用于指定ABI编码器版本,通常与实验性功能相关。

  示例:pragma abicoder v2;

  从Solidity 0.8.0开始,abicoder v2 已成为默认设置,取代了旧的 ABIEncoderV2。

  (4) 其他 pragma

  例如 pragma optimize(用于设置优化参数,但目前较少使用)。

  未来可能会有新的 pragma 指令,具体取决于Solidity的发展。

contract

contract HelloWorld {}

关键字 contract 告诉编译器你正在声明一个智能合约。如果你熟悉面向对象编程,

 那么你可以将契约视为类。如果你不熟悉 OOP,那么可以将合约视为保存数据的对象

 ——包括变量和函数。你可以通过智能合约为区块链应用程序提供所需的功能

变量

string public greeting = "Hello, World!";
uint public public_val = 123;
uint internal internal_val = 234;
uint private private_val = 456;

string , uint 是变量的数据类型

public ,  internal , private 是变量的修饰符

修饰符后面的是变量名称

等号右边的是变量的值

变量作用域

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

contract HelloWorld {
  
    string public greeting = "Hello, World!";
  
    function public_fun() public {
       uint num = 1;
       address owner = msg.sender;
    }
 
}

状态变量:通过将值记录在区块链上,在智能合约中存储永久数据(称为持久状态)

        位置:状态变量通常位于智能合约内部,但位于函数外部 ,这里对应的就是 greeting 

局部变量:这些是暂时性数据,在运行计算时会在短时间内保存信息。这些值不会永久存储在区块链上

     位置:局部变量位于函数内部,不能从该函数之外访问,这里对应的是 num

全局变量:这些变量和函数由 Solidity注入到您的代码中,无需专门创建或从任何地方导入它们即可使用。这些提供了代码运行时的区块链环境信息,还包括程序中会用到的功能性函数

   位置:全局变量不是由你声明的,是由系统提供的,这里对应的是 msg.sender

constant 、immutable 关键字

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

contract HelloWorld {
    string public greeting = "Hello, World!";

    uint constant NUMBER = 123;
    bytes constant BYTE_ = "Hello";
    string constant TEXT = "abc";
    address constant OWNER = 0xD4a33860578De61DBAbDc8BFdb98FD742fA7028e;
    address immutable OWNER2;

    function public_fun() public {
        uint num = 1;
        address owner = msg.sender;
    }

    constructor(address _owner) {
        OWNER2 = _owner;
    }
}

 constant

      数据修饰符,代表常量,用于声明在编译时就确定值且运行时不可更改的变量

      变量名称一般使用大写,是一种约定,使用小写也不会报错

      常量的值必须在定义时指定,

      且无法在构造函数或运行时修改

      值是固定,变量的值在编译时必须是确定的(即硬编码或通过常量表达式计算)。

      存储位置:constant 变量不占用区块链存储空间,它们的值直接嵌入到合约的字节码中。

      适用类型:通常用于基本类型(如 uint, address, string, bytes 等)或值类型。

      Gas 优化:因为值直接嵌入字节码,读取 constant 变量不需要访问存储,Gas 成本极低。

      限制:

       不能用于引用类型(如动态数组或映射)

       不能在运行时或构造函数中初始化。

       不能被函数修改

immutable

  数据修饰符,代表不可变变量,用于声明在部署时(构造函数中)初始化且之后不可更改的变量

 相比 constant,immutable 提供了更大的灵活性,因为它的值可以在合约部署时动态设置

变量名称一般使用大写,是一种约定,使用小写也不会报错

值在部署时确定:immutable 变量的值可以在构造函数中设置,但一旦合约部署完成,值就不可更改

 存储位置:immutable 变量的值也嵌入到合约字节码中,不占用存储槽,读取时 Gas 成本低

适用类型:支持大多数类型,包括基本类型和引用类型(如数组、结构体等)

Gas 优化:与 constant 类似,immutable 变量的读取不涉及存储访问,Gas 成本低

限制:

    只能在声明时或构造函数中初始化

    初始化后不可修改

   不支持在函数中动态修改

构造函数(constructor)

 constructor(address _owner) {
        OWNER2 = _owner;
    }

 构造函数(constructor) 是一个特殊的函数,用于在智能合约部署时初始化合约的状态

     它在合约创建时自动执行一次,且只能执行一次

     定义方式:使用 constructor 关键字定义,无返回值

     执行时机:仅在合约部署时由以太坊虚拟机(EVM)自动调用,之后无法再次调用

     作用:用于初始化合约的状态变量、设置关键参数或执行部署时的逻辑

     可选性:构造函数是可选的,如果不定义,Solidity 会使用默认的空构造函数

     可见性:在 Solidity 0.7.0 之前,构造函数可以指定可见性(如 public 或 internal),

    但从 0.7.0 起,构造函数不再需要(也不允许)显式指定可见性,默认为 public,且只在部署时调用

构造函数被调用时机:

   智能合约创建的几个阶段:

        1. 编译成字节码,这个阶段称为编译时间

        2. 被创建(构造) - 这是构造函数开始运行的时候,这可以称为构造时间

        3. 字节码被部署到区块链,这就是部署

        4. 部署的智能合约字节码在区块链上运行(执行),这可以被认为是运行时

在 Solidity 中,与其他语言不同,程序(智能合约)仅在构造函数完成其创建

     智能合约的工作后才会部署。

     有趣的是,在 Solidity 中,最终部署的字节码并不包含构造函数代码。

     这是因为在 Solidity 中,构造函数代码是创建代码(构造时间)的一部分,

     而不是运行时代码的一部分。它在创建智能合约时用完了,因为它只会调用一次,

     在这个阶段过去后,就不需要被调用了,所以不会在最终部署的字节码中  

可见性标识符 public、external、internal 和 private

    uint public public_val = 123;
    uint internal internal_val = 234;
    uint private private_val = 456;

    function public_fun2() public {}

    function external_fun() external {}

    function internal_fun() internal {}

    function private_fun() private {}
  修饰变量:

       public:变量可被合约内外部访问,自动生成 getter 函数

       internal:变量只能在合约内部及其继承的子合约中访问

       private:变量仅在当前合约内访问,子合约无法访问

   如果不显式指定可见性,Solidity 0.8.0 及以上版本中,变量默认为 internal

修饰函数:

       public:函数可被合约内外部调用  

       external:函数只能被外部调用(通过交易或外部合约),不能被合约内部直接调用(除非使用 this)

       internal:函数只能在合约内部及其子合约中调用

       private:函数仅在当前合约内调用,子合约无法调用

  函数需要显式声明可见性

function 定义

 function public_fun2(
        uint num1,
        uint num2
    ) public pure returns (uint, uint) {
        return (num1 + 1, num2 + 1);
    }

函数是封装单个想法、特定功能、任务等的可执行代码单元。通常我们希望函数一次只做一件事。

尽管函数可以在智能合约代码块之外的文件中声明,当时它们通常还是出现在智能合约中。函数可以接受 0 个或多个参数,也可以返回 0 个或多个值。输入和输出是静态类型,这里的 pure returns ,我们留到下期再讲

总结:我们从一个最简单的智能合约出发, 从头到尾介绍了SPDX-License、solidity 版本申明 pragma,如何创建合约 contract,还有变量,函数,构造函数的定义,变量的作用域,以及变量与函数的修饰符,可见性修饰符..... , 这些内容都做了详细的解说,除了理解以外,还需要多多练习,才能彻底掌握,我会在讲完所有solidity 内容之后,创建一个代码仓库。下一章见,宝子们!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值