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

 

 苏泽

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

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


本篇主要是做一个知识的整理和规划 作为一个类似文档的作用 更为简要和明了  具体的实现案例和用法 后续会陆续给出一些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.mzph.cn/news/744835.shtml

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

相关文章

RUST 每日一省:rust logo收集

rust的logo集合,看看有没有你喜欢的,挑一个吧; GitHub - XuHugo/rust-logo: Collection of logo images for all rust languages 下边只是挑选了几个,更多的还是看github吧。

Apache Doris 2.1.0 版本发布:开箱盲测性能大幅优化,复杂查询性能提升 100%

亲爱的社区小伙伴们,我们很高兴地向大家宣布,在 3 月 8 日我们引来了 Apache Doris 2.1.0 版本的正式发布,欢迎大家下载使用。 在查询性能方面, 2.1 系列版本我们着重提升了开箱盲测性能,力争不做调优的情况下取得较好…

第四百零二回

文章目录 知识回顾示例代码经验总结 我们在上一章回中介绍了MethodChannel的使用方法,本章回中将介绍EventChannel的使用方法.闲话休提,让我们一起Talk Flutter吧。 知识回顾 我们在前面章回中介绍了通道的概念和作用,并且提到了通道有不同的…

Qt 线程池 QThreadPool

一.Qt 线程池 QThreadPool介绍 Qt线程池是一种管理多个线程的并发编程模型,通过使用线程池可以提高性能、控制并发度、提供任务队列和简化线程管理。 在Qt中,线程池的使用主要涉及以下几个步骤: 创建任务类:需要定义一个任务类&am…

javaweb数据传参类型(2)

前言 友友们好呀,今天来分享一下对于各种数据类型传参的问题,今天陪伴我们的云海 目录 前言 数组集合传参 补充 日期参数 补充 Json格式数据传参 补充 路径参数 补充 今日分享 ​​​​​​​数组集合传参 类似于我们之前进行的简单的参数传递…

【C++】string的底层剖析以及模拟实现

一、字符串类的认识 C语言中,字符串是以\0结尾的一些字符的集合,为了操作方便,C标准库中提供了一些str系列的库函数, 但是这些库函数与字符串是分离开的,不太符合OOP的思想,而且底层空间需要用户自己管理&a…

Android14之禁止vbmeta.img签名校验(一百九十)

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 优质专栏:多媒…

区别于传统家!三翼鸟定制智慧家电家居一体化场景

在这个科技创新、智能AI主导的时代,寻求更便捷智慧、舒心适宜、一体化的居家场景,成为一个时代的命题和竞赛,也是家居行业共同奔赴的使命。在纷繁复杂的竞争格局和方向答案中,一条清晰坚定的路径正在显露出来…… AWE前一天&…

Jsp在Javaweb中扮演什么角色?

1.什么是Jsp JSP(Java Server Pages,Java 服务器页面)是一种动态网页技术,它允许在 HTML 页面中嵌入 Java 代码,并由 Web 服务器在请求页面时动态生成 HTML 页面。JSP 通常用于创建动态 Web 内容,如交互式表…

影城管理系统|基于springboot框架+ Mysql+Java+B/S架构的影城管理系统设计与实现(可运行源码+数据库+设计文档+部署说明)

推荐阅读100套最新项目 最新ssmjava项目文档视频演示可运行源码分享 最新jspjava项目文档视频演示可运行源码分享 最新Spring Boot项目文档视频演示可运行源码分享 目录 前台功能效果图 管理员功能登录前台功能效果图 系统功能设计 数据库E-R图设计 lunwen参考 摘要 研究…

智慧文旅|AI数字人导览:让旅游体验不再局限于传统

AI数字人导览作为一种创新的展示方式,已经逐渐成为了VR全景领域的一大亮点,不仅可以很好的嵌入在VR全景中,更是能够随时随地为观众提供一种声情并茂的讲解介绍,结合VR场景的沉浸式体验,让观众仿佛置身于真实场景之中&a…

数据结构与算法--算法和算法分析

算法与数据结构之间存在密不可分的关系。简单来说,数据结构是存储和组织数据的方式,而算法则是操作和处理这些数据的方法。 首先,数据结构为算法提供了基础。算法是解决问题的步骤和流程,通过对数据结构进行操作,算法可…

【pyautogui】PyAutoGUI 的简单使用

文章目录 1 简介2 通用功能2.1 暂停/休眠/耗时2.2 自动防故障功能 3 鼠标控制3.1 移动鼠标3.2 获取鼠标指针位置3.3 点击鼠标3.4 拖动鼠标3.5 滚动鼠标3.6 常用方法 4 键盘控制4.1 输入字符串 write4.2 按键操作 press4.3 按下 & 释放4.4 组合键 hotkey4.5 键名 5 屏幕图像…

2.1 关系数据结构及形式化定义 数据库概论

目录 2.1.1 关系 关系:概念 1. 域(Domain) 2.笛卡尔积 元组(Tuple) 分量(Component) 基数(Cardinal number) 3. 关系 候选码(Candidate key&#xf…

软件设计师17--磁盘管理

软件设计师17--磁盘管理 考点1:存储管理 - 磁盘管理调度算法磁盘调度 - FCFS磁盘调度 - SSTF例题: 考点1:存储管理 - 磁盘管理 存取时间寻道时间等待时间,训导时间是指磁头移动到磁道所需的时间;等待时间为等待读写的扇…

网工内推 | 上市公司网工,IE认证优先,最高18K*13薪,包吃住

01 深圳市宝腾互联科技有限公司 招聘岗位:网络工程师 职责描述: 1、是整个数据中心的网络技术及安全问题的负责人,确保数据中心业务的正常进行; 2、负责规划、设计、搭建、维护数据中心的网络环境,确保IDC /云平台&a…

python INI文件操作与configparser内置库

目录 INI文件 configparser内置库 类与方法 操作实例 导入INI文件 查询所有节的列表 判断某个节是否存在 查询某个节的所有键的列表 判断节下是否存在某个键 增加节点 删除节点 增加节点的键 修改键值 保存修改结果 获取键值 获取节点所有键值 其他读取方式 …

[Kali] 安装Nessus及使用

在官方网站下载对应的 Nessus 版本:Download Tenable Nessus | TenableDownload Nessus and Nessus Managerhttp://www.tenable.com/products/nessus/select-your-operating-system这里选择 Kali 对应的版本 一、安装 Nessus 1、下载得到的是 deb 文件,与

【爬虫开发】爬虫从0到1全知识md笔记第1篇:爬虫概述【附代码文档】

爬虫开发从0到1全知识教程完整教程(附代码资料)主要内容讲述:爬虫概述。selenium的其它使用方法。Selenium课程概要。常见的反爬手段和解决思路。验证码处理。chrome浏览器使用方法介绍。JS的解析。Mongodb的介绍和安装,小结。mongodb的简单使…

为什localhost被forbidden而127.0.0.1不被绊?

原因: 判段网关的时候判127.0.0.1,所以最好改localhost 其他参考: 【计算机网络】localhost不能访问,127.0.0.1可以访问?_ping localhost和ping 127.0.0.1-CSDN博客