Solidity 智能合约开发 - 基础:基础语法 基础数据类型、以及用法和示例

news2024/9/28 15:32:15

 

 苏泽

大家好 这里是苏泽 一个钟爱区块链技术的后端开发者

本篇专栏 ←持续记录本人自学两年走过无数弯路的智能合约学习笔记和经验总结 如果喜欢拜托三连支持~


本篇主要是做一个知识的整理和规划 作为一个类似文档的作用 更为简要和明了  具体的实现案例和用法 后续会陆续给出一些demo~ 请持续关注~

目录

本篇主要是做一个知识的整理和规划 作为一个类似文档的作用 更为简要和明了  具体的实现案例和用法 后续会陆续给出一些demo~ 请持续关注~

数据类型

基本数据类型:

地址类型(address):

字符串类型(string):

数组类型(array):

结构体类型(struct):

Enum

映射类型(mapping):

关键字

"view" 关键字

"pure" 关键字

"public":

"private":

"external":

"internal":

"payable":

函数

函数定义和调用:

函数可见性(public、private等):

函数修饰器(modifier):

函数返回值:

数组

数组定义和初始化:

数组长度和访问元素:

动态数组和静态数组:

多维数组:

结构体

结构体定义和初始化:

结构体成员访问:

结构体作为函数参数和返回值:

结构体数组:

储存方式

memory:

storage:

calldata:

堆栈(Stack):

日志(Logs):

Code

Mappings

映射定义和初始化:

映射的键值对:

映射的访问和修改:

映射的迭代:


数据类型

  1. 基本数据类型:

    • 整型(uint、int):用于表示整数,可以指定位数,如 uint256。 示例:uint256 myNumber = 10;

    • 布尔型(bool):用于表示真(true)或假(false)。 示例:bool isTrue = true;

  1. 地址类型(address):

    • 用于存储以太坊地址,可以是外部账户或智能合约地址。 示例:address myAddress = 0xAbcdef1234567890;

  1. 字符串类型(string):

    • 用于存储文本字符串。 示例:string myString = "Hello, World!";

  1. 数组类型(array):

    • 用于存储相同类型的元素集合。 示例:uint256[] myArray = [1, 2, 3];

  2. 结构体类型(struct):

用于自定义复合类型,可以包含多个字段。 示例:

Copy Code
struct Person {
    string name;
    uint age;
}
Person myPerson;
myPerson.name = "Alice";
myPerson.age = 25;
  1. Enum

Enum 是枚举类型,可以通过以下语法来定义

enum Status {
    Unknown,
    Start,
    End,
    Pause
}
并通过以下语法来进行更新与初始化


// 实例化枚举类型
Status public status;

// 更新枚举值
function pause() public {
    status = Status.Pause;
}

// 初始化枚举值
function reset() public {
    delete status;
}
  1. 映射类型(mapping):

    1. 用于存储键值对数据结构。 示例:

Copy Code
mapping(address => uint256) balances;
balances[msg.sender] = 100;

关键字

  1. "view" 关键字

用于标识一个函数不会修改合约的状态,即它只能读取数据而不能修改数据。这意味着在调用视图函数时,不会产生任何交易费用,并且不会改变合约的状态。例如:

 
 

function getName() public view returns (string memory) {return name; }

  1. "pure" 关键字

用于标识一个函数既不会修改合约的状态,也不会读取或访问合约的存储数据。这种函数通常用于执行纯粹的计算操作,不涉及存储或外部调用。例如:

 

function add(uint256 a, uint256 b) public pure returns (uint256) {return ab; }

  1. "public":

  1. 将函数或变量声明为公共的,可以被合约内部和外部访问。例如:

string public name = "Alice";

  1. "private":

  1. 将函数或变量声明为私有的,只能在合约内部访问。例如:

uint256 private balance = 100;

  1. "external":

将函数声明为外部函数,只能从合约外部调用。与 "public" 关键字不同的是,外部函数不能在合约内部直接调用,也不能被合约继承。例如:

Copy Code function transfer(address recipient, uint256 amount) external { // transfer logic here }

  1. "internal":

将函数声明为内部函数,只能在合约内部或合约继承链上的合约中访问。例如:

function withdraw(uint256 amount) internal { // withdraw logic here }

  1. "payable":

将函数声明为可以接收以太、币的函数,在函数中可以接收以太币并进行转账操作。例如:

function purchase() public payable {// purchase logic here }

函数

  1. 函数定义和调用:

    • 定义函数并在需要时进行调用。 示例:

Copy Code
function sayHello(string memory name) public {// 函数逻辑// ...
}
sayHello("Alice");
  1. 函数可见性(public、private等):

    • 可以限制函数的访问权限。 示例:

Copy Code
function myFunction() public {// 可公开访问的函数
}
function privateFunction() private {// 私有函数,只能在合约内部调用
}
  1. 函数修饰器(modifier):

    • 用于修改函数的行为。 示例:

      Copy Code
      modifier onlyOwner() {
          require(msg.sender == owner, "Only owner can call this function.");_;
      }
      function changeName(string memory newName) public onlyOwner {// 只有合约所有者可以调用该函数
          name = newName;
      }

  2. 函数返回值:

    • 可以定义函数的返回类型,并在函数结束时返回相应的值。 示例:

Copy Code
function add(uint256 a, uint256 b) public pure returns (uint256) {return a + b;
}
uint256 result = add(2, 3);  // result = 5

数组

  1. 数组定义和初始化:

    • 定义数组并指定元素个数或直接初始化数组。 示例:


uint256[] myArray;  // 空数组uint256[] myArray2 = new uint256[](3);  // 长度为3的动态数组uint256[] myArray3 = [1, 2, 3];  // 直接初始化数组
  1. 数组长度和访问元素:

    • 可以使用 length 属性获取数组长度,并通过索引访问数组元素。 示例:

 uint256[] myArray = [1, 2, 3]; uint256 length = myArray.length; // length = 3uint256 secondElement = myArray[1]; // secondElement = 2
  1. 动态数组和静态数组:

    • 动态数组的长度可以在运行时更改,而静态数组的长度在编译时确定。 示例:


uint256[] dynamicArray;
uint256[3] staticArray;
  1. 多维数组:

    • 数组可以有多个维度,可以是二维、三维等。 示例:


uint256[][] twoDimensionalArray;
uint256[2][3] twoByThreeArray;

结构体

  1. 结构体定义和初始化:

    • 定义结构体类型并初始化结构体变量。 示例:


struct Person {
    string name;
    uint age;
}
Person myPerson;
myPerson.name = "Alice";
myPerson.age = 25;
  1. 结构体成员访问:

    • 可以通过结构体变量名和成员名访问结构体成员。 示例:

 
Person myPerson;
myPerson.name = "Alice";
string memory personName = myPerson.name;  // personName = "Alice"
  1. 结构体作为函数参数和返回值:

    • 可以将结构体作为函数的参数或返回值进行传递。 示例:

 
struct Person {
    string name;
    uint age;
}
function getPerson() public view returns (Person memory) {
    Person memory person;
    person.name = "Alice";
    person.age = 25;
    return person;
}
Person memory myPerson = getPerson();
  1. 结构体数组:

    • 结构体可以组成数组,并通过索引访问数组元素。 示例:

       
      struct Person {
          string name;
          uint age;
      }
      Person[] people;
      Person memory person1;
      person1.name = "Alice";
      person1.age = 25;
      people.push(person1);
      Person memory person2;
      person2.name = "Bob";
      person2.age = 30;
      people.push(person2);

储存方式

当在Solidity中声明变量时,可以使用不同的存储位置修饰符来指定变量应该存储在何处。共有三种存储位置:memorystoragecalldata。其中,memorystorage是最常用的两种。

  1. memory

    • memory 是一种临时存储位置,用于存储函数执行期间的临时数据。它适用于需要在函数内部进行临时计算或处理大量数据的情况。在函数执行完毕后,memory 中的数据会被清空。

    • 可以使用 memory 关键字将变量声明为 memory 类型,也可以在函数参数中使用 memory。 示例:

function processArray(uint256 memory myArray) public {// 在 memory 中处理数组// ... }
  1. storage

    • storage 是一种永久性存储位置,用于在合约的存储空间中存储和访问数据。它适用于需要在不同函数之间共享和保留数据的情况。在合约中声明的 state variables 默认是 storage 类型。

    • 可以直接在函数内部使用 storage 类型的变量,无需显式声明。 示例:

  1. calldata

    • calldata 是一种特殊的存储位置,用于存储函数参数和外部函数调用的输入数据。calldata 中的数据是只读的,不能被修改。此存储位置适用于函数参数传递和与外部合约交互。

    • 在函数参数中,默认情况下,所有的非 mapping 类型参数都被视为 calldata 类型。 示例:


function processInputData(uint256 calldata inputData) external {// 处理输入数据
}

function callExternalContract(address externalContract, bytes calldata data) external {
    (bool success, ) = externalContract.call(data);
    require(success, "External contract call failed.");
}

总结一下:

  • memory 用于临时存储函数执行期间的数据,适用于临时计算或处理大量数据的情况;

  • storage 用于永久性存储变量,适用于在不同函数之间共享和保留数据的情况;

  • calldata 用于存储函数参数和外部函数调用的输入数据,是只读的。

  1. 堆栈(Stack):

    • Solidity 中的堆栈主要用于函数调用的内部状态维护。每当一个函数被调用时,它会在堆栈上创建一个新的帧,该帧包含了这个函数的参数、局部变量、返回地址等信息。当函数执行完毕后,该帧将从堆栈中弹出。

    • 通常情况下,开发者不需要手动操作堆栈,Solidity 编译器会自动进行堆栈管理。但在一些需要优化调用栈空间的场景下,可能需要手动控制函数调用堆栈的大小和顺序。 示例:

      
      function foo(uint256 x, uint256 y) public pure returns (uint256) {
          uint256 result = bar(x) + y;return result;
      }
      
      function bar(uint256 x) public pure returns (uint256) {
          uint256 result = x * 2;return result;
      }

  1. 日志(Logs):

    • Solidity 中的日志主要用于记录合约内部的事件,如状态变更、交易处理等。通过日志,可以在区块链上查看合约的历史状态变化,并进行事件通知和监听。

    • 日志由合约的事件(event)和事件参数组成,可以通过 emit 关键字触发。日志数据会被写入到交易的日志中,不会影响合约状态,但会占用一定的 Gas。 示例:


event Transfer(address indexed from, address indexed to, uint256 value);
function transfer(address _to, uint256 _value) public {
    require(balances[msg.sender] >= _value, "Insufficient balance.");
    balances[msg.sender] -= _value;
    balances[_to] += _value;
    emit Transfer(msg.sender, _to, _value);
}
  1. Code

Solidity 中的一种特殊的数据类型,用于存储合约的字节码。

在 Solidity 中,合约代码(也称为字节码)可以通过 type 关键字将其存储在 bytesbytescode 类型的变量中。这样可以在合约内部或外部对代码进行处理和分析。

以下是一个简单的示例,展示了如何将合约代码存储在 bytes 类型的变量中:


pragma solidity ^0.8.0;

contract CodeExample {
    bytes public contractCode;
    constructor() {
        // 将合约代码存储在 contractCode 变量中
        contractCode = type(CodeExample).creationCode;
    }
}

Mappings

  1. 映射定义和初始化:

    • 定义映射类型,并通过键值对存储和访问数据。 示例:

 mapping(address => uint256) balances;

  1. 映射的键值对:

    • 映射由键值对组成,通过键来访问对应的值。 示例:

mapping(address => uint256) balances; 
address account = 0xAbcdef1234567890; balances[account] = 100;
  1. 映射的访问和修改:

    • 可以通过键来访问或修改映射中的值。 示例:


mapping(address => uint256) balances;
 address account = 0xAbcdef1234567890; uint256 balance = balances[account]; // 获取映射值 balances[account] = 200; // 修改映射值
  1. 映射的迭代:

  • Solidity 中的映射不支持直接迭代,需要结合其他数据结构或编写逻辑来实现迭代功能。

在 Solidity 中,映射(Mapping)是一种键值对的数据结构,类似于字典或哈希表。每个键对应一个唯一的值。但是,Solidity 中的映射并不支持直接迭代,这意味着你无法像遍历数组或列表那样直接对映射进行循环迭代。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1516820.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Milvus向量数据库检索

官方文档:https://milvus.io/docs/search.md   本节介绍如何使用 Milvus 搜索实体。   Milvus 中的向量相似度搜索会计算查询向量与具有指定相似度度量的集合中的向量之间的距离,并返回最相似的结果。您可以通过指定过滤标量字段或主键字段的布尔表达…

Redis及其数据类型和常用命令(一)

Redis 非关系型数据库,不需要使用sql语句对数据库进行操作,而是使用命令进行操作,在数据库存储时使用键值对进行存储,应用场景广泛,一般存储访问频率较高的数据。 一般关系型数据库(使用sql语句进行操作的…

市场复盘总结 20240314

仅用于记录当天的市场情况,用于统计交易策略的适用情况,以便程序回测 短线核心:不参与任何级别的调整,采用龙空龙模式 一支股票 10%的时候可以操作, 90%的时间适合空仓等待 二进三: 进级率中 25% 最常用的…

二.递归及实例(汉诺塔问题)

目录 5.递归 6-递归实例:汉诺塔问题 思路: 详细过程: 代码: 5.递归 调用自身 结束条件 6-递归实例:汉诺塔问题 思路: 结果: 详细过程: 代码: #n为盘子的个数 a,b,c分别为3个地方. def hannuta(n,a,b,c): ​if n>0:hannuta(n-1,a,c,b) #将n-1个从a经过c移到到b(a…

【C语言_C语言语句_复习篇】

目录 一、C语言的语句有哪些 1.1 空语句 1.2 表达式语句 1.3 函数调用语句 1.4 复合语句 1.5 控制语句 二、分支语句(两种) 1.1 if语句 1.1.1 普通分支语句(if、if_else) 1.1.2 嵌套if语句 1.1.3 else嵌套if两种写法的比较 1.1.4 else悬空问题 1.1.…

代码随想录算法训练营第四十七天|动态规划|198.打家劫舍、213.打家劫舍II、337.打家劫舍III

198.打家劫舍 文章 你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。 给定一个代…

Docker容器化技术(使用Docker搭建论坛)

第一步:删除容器镜像文件 [rootlocalhost ~]# docker rm -f docker ps -aq b09ee6438986 e0fe8ebf3ba1第二步:使用docker拉取数据库 [rootlocalhost ~]# docker run -d --name db mysql:5.7 02a4e5bfffdc81cb6403985fe4cd6acb0c5fab0b19edf9f5b8274783…

NLP:HanLP的下载与使用

昨天说到要做一个自定义的训练模型,但是很快这个想法就被扑灭了,因为这个手工标记的成本太大,而且我的上级并不是想要我做这个场景,而是希望我通过这个场景展示出可以接下最终需求的能力。换句话来说:可以,…

leetcode代码记录(找到小镇的法官

目录 1. 题目:2. 我的代码:小结: 1. 题目: 小镇里有 n 个人,按从 1 到 n 的顺序编号。传言称,这些人中有一个暗地里是小镇法官。 如果小镇法官真的存在,那么: 小镇法官不会信任任何…

【数据结构】树与堆 (向上/下调整算法和复杂度的分析、堆排序以及topk问题)

文章目录 1.树的概念1.1树的相关概念1.2树的表示 2.二叉树2.1概念2.2特殊二叉树2.3二叉树的存储 3.堆3.1堆的插入(向上调整)3.2堆的删除(向下调整)3.3堆的创建3.3.1使用向上调整3.3.2使用向下调整3.3.3两种建堆方式的比较 3.4堆排…

新 树莓派4B 温湿度监测 基于debian12的树莓派OS

前言 本文旨在完成通过外接温湿度传感器至树莓派使得树莓派不断记录并存储温湿度数据 这个领域有很多文章,但是部分文章已经缺乏了时效性,在最新系统不适用,本文目前适用 硬件 硬件连接 温湿度传感器常选用DHT11和DHT22,淘宝…

MTK的flash_tool.exe中,“Format-Download”、“Firmware-Upgrade”和“Download”是三种不同的刷机模式

在MTK的flash_tool.exe中,“Format-Download”、“Firmware-Upgrade”和“Download”是三种不同的刷机模式。具体分析如下: Format-Download:这种模式会执行全擦除,即清除存储器中的所有数据,然后下载新的固件。这种方…

图片编辑器tui-image-editor

提示:图片编辑器tui-image-editor 文章目录 前言一、安装tui-image-editor二、新建components/ImageEditor.vue三、修改App.vue四、效果五、遇到问题 this.getResolve is not a function总结 前言 需求:图片编辑器tui-image-editor 一、安装tui-image-ed…

DB算法原理与构建

参考: https://aistudio.baidu.com/projectdetail/4483048 Real-Time Scene Text Detection with Differentiable Binarization 如何读论文-by 李沐 DB (Real-Time Scene Text Detection with Differentiable Binarization) 原理 DB是一个基于分割的文本检测算…

IDEA自定义Maven仓库

Maven 是一款广泛应用于 Java 开发的工具,其作用类似于一个全自动的 JAR 包管理器,能够方便地导入开发所需的相关 JAR 包。在使用 Maven 进行 Java 程序开发时,开发者能够极大地提高开发效率。以下是关于如何安装 Maven 以及在 IDEA 中配置自…

电脑远程桌面选项变成灰色没办法勾选怎么办?

有些人在使用Windows系统自带的远程桌面工具时,会发现系统属性远程桌面选项卡中勾选启用“允许远程连接到此计算机”。 导致此问题出现的原因主要是由于组策略或者注册表设置错误造成的。 修复远程桌面选项变灰的两种方法! 方法一:设置本地组…

【LeetCode】84. 柱状图中最大的矩形(困难)——代码随想录算法训练营Day60

题目链接:84. 柱状图中最大的矩形 题目描述 给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。 求在该柱状图中,能够勾勒出来的矩形的最大面积。 示例 1: 输入:heights [2,1,5,…

Vue3调用钉钉api,内嵌H5微应用单点登录对接

钉钉内嵌H5微应用单点登录对接 https://open.dingtalk.com/document/isvapp/obtain-the-userid-of-a-user-by-using-the-log-free 前端需要的代码 1、安装 dingtalk-jsapi npm install dingtalk-jsapi2、在所需页面引入 import * as dd from dingtalk-jsapi; // 引入钉钉a…

python版本原因导致的grpcio-tools-1.48.2安装失败

因为工作需要使用python开发grpc客户端,在mac电脑上通以下命令安装python的grpc依赖库总是不成功 pip3 install --no-cache-dir --force-reinstall -Iv grpcio1.48.2 grpcio-tools1.48.2 clang -Wsign-compare -Wunreachable-code -fno-common -dynamic -DNDEBUG …

【string一些函数用法的补充】

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言 string类对象的修改操作 我们来看 c_str 返回c格式的字符串的操作: 我们来看 rfind 和 substr 的操作: string类非成员函数 我们来看 r…