solidity:智能合约结构介绍

这篇具有很好参考价值的文章主要介绍了solidity:智能合约结构介绍。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

合约结构介绍

1.SPDX 版权声明

bytecode metadata 介绍

2.pragma solidity 版本限制

3.contract 关键字

4.import 导入声明

5.interface: 接口

6.library:库合约


合约结构介绍

1.SPDX 版权声明

第 1 行 // SPDX-License-Identifier: MIT 就是合约的版权声明。其中 SPDX-License-Identifier(SPDX 许可标示) 是标注当前的智能合约采用什么样的对外开放标准,该标准规定了别人是否拥有商业开发,学习使用等权利。代码中使用的 MIT 规定了其他人随便用该代码,但出问题不负责。MIT 详细解释;SPDX 许可标示的注释在文件的任何位置都可以被编译器识别到的,按照规范建议把它放在文件的顶部第一行。

如果一个项目开源了智能合约的源代码,可以更好地建立社区信任。但是由于提供源代码就不可避免的涉及到版权或者法律问题。所以 solidity 鼓励开源,但是开源并不等于放弃版权。如果你不想指定任何许可证,或者代码就是不想开源,Solidity 推荐使用 UNLICENSED ;UNLICENSED 不存在于 SPDX 许可证列表中,与 UNLICENSE (授予所有人所有权利)不同,它比 UNLICENSE 多一个 D 字母。

需要注意: 源代码这里,编译器不会验证 SPDX 许可标示是否符合规范,比如我可以写为 // SPDX-License-Identifier: ANBANG ,并不会影响代码的运行。但是这里的标示会被打包在 bytecode metadata 里。

bytecode metadata 介绍

当我们使用 remix 编译合约的时候,会在根目录创建 artifacts 文件夹,其中包含 build-info 记录构建信息的文件夹,以及每个合约名字作为文件名的文件夹,比如 contract Hello 将生成

  • Hello.json 文件

  • Hello_metadata.json 文件

Hello.json 文件结构

{
  deploy: {},
  data: {
    bytecode: {},
    deployedBytecode: {},
    gasEstimates: {},
    methodIdentifiers: {},
  },
  abi: [],
};

Hello_metadata.json 文件结构

{
  compiler: {
    version: "0.8.17+commit.xxx",
  },
  language: "Solidity",
  output: {
    abi: [],
    devdoc: {},
    userdoc: {},
  },
  settings: {},
  sources: {
    "aaa.sol": {
      keccak256:
        "0x637c141739144cd991b9350336a1f8c3b948811d7ed743fefb4aad99d7bb362f",
      license: "kyp",
      urls: [
        "bzz-raw://9eea517225b90242d6e3761046f5f5a8f0a2393747c89f3af01f34ad00764dc4",
        "dweb:/ipfs/QmXp5wap9ZNC9fihdA7aLMe7bKWBjeAuv7khEuvKrgp9Bx",
      ],
    },
  },
  version: 1,
};

// SPDX-License-Identifier: kyp 中的 kyp 就是在 sources -> filename.sol -> license

2.pragma solidity 版本限制

第 2 行 pragma solidity ^0.8.17; 指令,它是告诉编译器,我当前的合约代码采用的是 Solidity 0.8.17 这个版本为基础编写的,解析部署时需要在匹配的版本下进行,在区块链浏览器上进行合约验证时,也需要选择匹配的版本。

⓵ 使用 ^ 的意义和优点

^0.8.17 中的 ^ 表示小版本兼容,大版本不兼容,相当于 pragma solidity >= 0.8.17 < 0.9.0;。他既不允许低于0.8.17的编译器编译,也不允许大于等于 0.9.0 版本的编译器进行编译。之所以这么写,不写死 pragma solidity 0.8.17; 是为了可以享受到编译器的补丁版,比如以后出来了 0.8.40 版本,那么当前合约是可以运行在未来的 0.8.40 这个新版本的编译器。但是如果是大版本升级到了 0.9.0,那么编译器不会用新版的0.9.x解析,会使用 0.8 的最后一个稳定版本来进行解析编译。这里如果不加 ^,直接写pragma solidity 0.8.17;,就是告诉编译器,当前合约只选择在 0.8.17 版本来编译和部署;这样做的缺点就是享受不到以后出的补丁版的编译器。

⓶ 跨大版本的合约

如果你打算跨大版本的合约,可以使用> />=/</<=来操作,比如 pragma solidity >=0.7.0 <0.9.0;

注意:pragma 指令只对当前的源文件起作用,如果把文件 B 导入到文件 A,文件 B 的 pragma 将不会自动应用于文件 A。

  • 总结:

    1. pragma solidity ^0.8.17; 是用来告诉编译器应该选择什么版本来解析编译当前代码。

    2. pragma 指令只对当前的源文件起作用。

注:一份源文件可以包含多个版本声明、多个导入声明和多个合约声明。

3.contract 关键字

第 3 行的 contract Hello {} 是合约的基本结构;其中 contract 声明了当前代码块内是一个完整的合约。而 Hello 是当前合约的名字,合约名称是必须的,首字母一般采用大写字母开头。

contract 代表特殊的意义,这种有特殊意义的词,在编程界里一般被称为 保留关键字;保留关键字是现在或者将来被用到的特殊代指,都有固定意义,所以保留关键字不能作为变量名和函数名字。

  • 总结:

    1. contract 基本结构是 contract ContractName {}

    2. Solidity 合约中,合约的名字是必须的。

    3. 合约的名称,一般约定为 大驼峰命名方式

    4. contract 是保留关键字

    5. 保留关键字不能作为变量名和函数名

  • 扩展:

    1. 合约的编写规范,参照 合约编码规范

    2. 更多保留关键字,参照 变量名命名规则 详细阅读。

注:一份源文件可以包含多个版本声明、多个导入声明和多个合约声明

⓵ 变量

合约内的 message 叫做状态变量,状态变量是永久地存储在合约存储中的值。关于变量的更多信息,会在后续 [变量] 那一章详细介绍

⓶ 函数

函数是代码的可执行单元,是一组逻辑的集合。关于变量的更多信息,会在后续 函数 那一章详细介绍

⓷ this 关键字

Solidity 中 this 代表合约对象本身;

  • 可以通过 address(this) 获取合约地址。

  • 可以通过 this.fnName 获取 external 函数

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
​
contract Demo {
    function contractAds() external view returns (address) {
        return address(this);
    }
​
    function testExternal() external view returns (address) {
        return this.contractAds();
    }
}

⓸ 合约地址/合约创建者地/合约调用者地址

这三个地址概念一定要完全理解。

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
​
// 这三个地址的概念一定要理解清楚
contract Demo {
    address public owner;
​
    constructor() {
        // 可以用在 constructor 内获取当前合约地址
        owner = address(this);
​
        // 不可以在构造函数内调用函数,因为此时合约还没有完成构建好。
        // this.caller(); 相当于从外部调用 caller 方法
        // owner = this.caller();
    }
​
    function caller() external view returns (address) {
        return this.contractAds(); // 内部调用 external 可见性的函数
    }
​
    function contractAds() external view returns (address) {
        return address(this);
    }
}

⓹ 合约属性:type 关键字

  • type(C).name:获得合约名

  • type(C).creationCode:获得包含创建合约字节码的内存字节数组。它可以在内联汇编中构建自定义创建例程,尤其是使用 create2 操作码。 不能在合约本身或派生的合约访问此属性。 因为会引起循环引用。

  • type(C).runtimeCode:获得合约的运行时字节码的内存字节数组。这是通常由 C 的构造函数部署的代码。 如果 C 有一个使用内联汇编的构造函数,那么可能与实际部署的字节码不同。 还要注意库在部署时修改其运行时字节码以防范定期调用(guard against regular calls)。 与 .creationCode 有相同的限制,不能在合约本身或派生的合约访问此属性。 因为会引起循环引用。

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
​
contract Hello {
    string public message = "Hello World!";
}
​
contract Demo {
    function name() external pure returns (string memory) {
        return type(Hello).name;
    }
​
    function creationCode() external pure returns (bytes memory) {
        return type(Hello).creationCode;
    }
    function runtimeCode() external pure returns (bytes memory) {
        return type(Hello).runtimeCode;
    }
}

除了上面介绍的版权声明,版本限制,contract 外,合约文件还包括 import, interface,library,一起展开介绍下

4.import 导入声明

功能:从其他文件内倒入需要的变量或者函数。

⓵ 导入方式

既可以导入本地文件,也可以导入 url(网络上的 ipfs,http 或者 git 文件)

  1. 导入所有的全局标志

    import "filename";

    到当前全局范围

    1. 导入本地文件:import "./ERC20.sol";,其中./表示当前目录,查找路径参考

    2. 导入网络文件:import "https://github.com/aaa/.../tools.sol";

    3. 导入本地 NPM 库:

      1. $ npm install @openzeppelin/contracts

      2. import "@openzeppelin/contracts/token/ERC721/ERC721.sol";

  2. 导入所有的全局标志,并创建新的全局符号

    1. 方式一: import * as symbolName from "filename";

    2. 方式二: import "filename" as symbolName;

  3. 按需导入,按需修改名称

    1. import {symbol1 as aliasName, symbol2} from "filename";

不推荐导入变量标示名到当前全局范围的方式,因为不可控,容易污染当前的命名空间。如果全局导入,推荐使用 import "filename" as symbolName;

注:一份源文件可以包含多个版本声明、多个导入声明多个合约声明。

⓶ 导入时候的本地路径

上文中的 filename 总是会按路径来处理,以 / 作为目录分割符、以 . 标示当前目录、以 .. 表示父目录。 当 ... 后面跟随的字符是 / 时,它们才能被当做当前目录或父目录。 只有路径以当前目录 . 或父目录 .. 开头时,才能被视为相对路径。

import "./x.sol" as x; 语句导入当前源文件同目录下的文件 x.sol 。 如果用import "x.sol" as x; 代替,可能会引入不同的文件(在全局 include directory 中)。

最终导入哪个文件取决于编译器(见下文)到底是怎样解析路径的。 通常,目录层次不必严格映射到本地文件系统, 它也可以映射到能通过诸如 ipfs,http 或者 git 发现的资源。

5.interface: 接口

⓵ 接口使用案例

在下面的例子中,定义了 cat 合约以及 dog 合约。他们都有 eat 方法.以此他们都可以被上面的 animalEat 接口所接收。

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
​
contract Cat {
    uint256 public age;
​
    function eat() public returns (string memory) {
        age++;
        return "cat eat fish";
    }
​
    function sleep1() public pure returns (string memory) {
        return "sleep1";
    }
}
​
contract Dog {
    uint256 public age;
​
    function eat() public returns (string memory) {
        age += 2;
        return "dog miss you";
    }
​
    function sleep2() public pure returns (string memory) {
        return "sleep2";
    }
}
​
interface AnimalEat {
    function eat() external returns (string memory);
}
​
contract Animal {
    function test(address _addr) external returns (string memory) {
        AnimalEat general = AnimalEat(_addr);
        return general.eat();
    }
}

type(I).interfaceId

返回接口Ibytes4 类型的接口 ID,接口 ID 参考: EIP-165 定义的, 接口 ID 被定义为 XOR (异或) 接口内所有的函数的函数选择器(除继承的函数。

上面的代码种,可以增加如下的函数来查看 interfaceId;

contract Animal {
    // ...
    function interfaceId() external pure returns (bytes4) {
        return type(AnimalEat).interfaceId;
    }
}

更多内容在interface:接口那一章详细介绍。

6.library:库合约

库与合约类似,但它的目的是在一个指定的地址,且仅部署一次,然后通过 EVM 的特性来复用代码。

library Set {
    struct Data { mapping(uint => bool) flags; }
    function test(){
    }
}

其他合约调用库文件的内容直接通过库文件名.方法名例如:Set.test()文章来源地址https://www.toymoban.com/news/detail-402731.html

到了这里,关于solidity:智能合约结构介绍的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • solidity实现智能合约教程(3)-空投合约

    猛戳订阅学习专栏🍁🍁 👉 solidity系列合约源码+解析 👈 🍁🍁 空投就是一种营销策略,通过空投活动将某种数字货币或代币分发给用户,通常需要用户完成一项简单的任务,如分享新闻、介绍朋友或拥有某种数字货币,目前也被广泛应用于宣传新币种,在数字货币市场中

    2024年02月07日
    浏览(78)
  • 以太坊智能合约开发(五):Solidity成绩录入智能合约实验

    每个学生分别部署合约Student.sol ,保证只有自己可以修改姓名。老师部署合约StudentScore.sol,用于录入学生成绩,查询学生信息。查询学生信息时,需要调用学生部署的合约Student.sol。 student.sol合约,用于学生对自己信息进行管理。 学生的基本信息作为状态变量: 声明构造函

    2024年02月07日
    浏览(49)
  • 【Solidity】智能合约案例——③版权保护合约

    目录 一、合约源码分析: 二、合约整体流程:         1.部署合约:         2.添加实体:          3.查询实体         4.审核版权:         5.版权转让         Copyright.sol:主合约,定义了版权局的实体,功能为:审核版权         Opus.sol:定义两个实体:作者和作

    2024年02月04日
    浏览(50)
  • Solidity 智能合约入门

    将一个数据放置在链上 我们对代码进行逐行分析,首先第一行 第一行表明此段代码是被GPL-3.0所授权。默认情况下,在发布源代码时加入机器可读许可证说明是很重要的。 GPL(GNU General Public License Versions) GPL协议一般还可以分为GPL2.0和GPL3.0两种,而GPL3.0是更新一代的开源标准

    2024年02月02日
    浏览(47)
  • 智能合约 Solidity – 构造函数

    构造函数是任何面向对象的编程语言中的一种特殊方法,每当初始化类的对象时都会调用它。Solidity 则完全不同,Solidity 在智能合约内部提供了一个构造函数声明,它只在合约部署时调用一次,用于初始化合约状态。如果没有明确定义的构造函数,则编译器会创建默认构造函

    2024年02月11日
    浏览(43)
  • solidity开发智能合约

    起源于以太坊(Ethereum),设计的目的是能在以太坊虚拟机(EVM)上运行。Solidity 是一门面向合约的、为实现智能合约而创建的高级编程语言。所以先从智能合约开始。 参考文档 Solidity文档:区块链技术-智能合约Solidity编程语言 solidity官方文档: https://solidity-cn.readthedocs.io/

    2023年04月08日
    浏览(83)
  • 【Solidity】智能合约案例——②供应链金融合约

    目录 一、合约源码分析: 二、合约整体流程:         1.部署合约:         2.添加实体         3.发送交易存证            ①.银行向公司交易(公司向银行提供交易存证)            ②.公司向银行交易(银行向公司提供交易存证)            ③.公司向公司交易

    2024年02月06日
    浏览(39)
  • Solidity contract智能合约概览

    Contracts in Solidity are similar to classes in object-oriented languages. They contain persistent data in state variables, and functions that can modify these variables. Calling a function on a different contract (instance) will perform an EVM function call and thus switch the context such that state variables in the calling contract are inaccessible. A con

    2024年02月11日
    浏览(46)
  • Solidity,智能合约的学习(1)

    Solidity是一种智能合约高级语言,运行在Ethereum虚拟机(EVM)上,Solidity是面向对象的高级语言,用于实现智能合约。智能合约是管理以太坊状态内的账户行为的程序。 BitPen认为,作为Web3的链上玩家,那么能够看懂Solidity代码将会是一项必备的技能,因为大多区块链项目都是在

    2024年01月23日
    浏览(54)
  • Solidity实现简单的智能合约

    Solidity是以太坊中编写智能合约的语言,编译成字节码之后可以运行在以太坊虚拟机上。solidity语法与JavaScript很相似,有编程基础的开发者可以轻松上手,智能合约一旦部署就无法修改。 首先介绍我们的编译工具: Remix remix是一款非常好用的在线编译工具,我们通过这个工具

    2023年04月09日
    浏览(37)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包