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.hqwc.cn/news/538738.html

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

相关文章

轻松驾驭时间流:MYSQL日期与时间函数的实用技巧

​🌈 个人主页:danci_🔥 系列专栏:《MYSQL应用》💪🏻 制定明确可量化的目标,坚持默默的做事。 轻松驾驭时间流:MYSQL日期与时间函数的实用技巧 MYSQL日期时间函数是数据库操作中不可…

【网络安全】-数字证书

数字证书 数字证书是互联网通讯中用于标志通讯各方身份信息的一串数字或数据,它为网络应用提供了一种验证通信实体身份的方式。具体来说,数字证书是由权威的证书授权(CA)中心签发的,包含公开密钥拥有者信息以及公开密…

搭建项目前端系统基础架构

Vue是什么 Vue 是一套用于构建用户界面的渐进式框架。与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。目前市面上有很多基于Vue重新封装的各种前端UI框…

MySQL死锁案例分析及避免办法

1. 什么是死锁2. 举个栗子:2.1. 栗子一:2.1.1 代码栗子:2.1.2 存储引擎状态分析2.1.2.1 第一部分:2.1.2.2 第二部分:2.1.2.3 第三部分: 2.1.3 解决方式2.1.3.1 注意资源的获取顺序2.1.3.2 大事务拆小 2.2. …

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

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

暗光增强——IAT网络推理测试(详细图文教程)

IAT模型由两个独立的分支组成,局部分支用于像素调整,并输出两个用于加法和乘法的特征图。全局分支用于全局调整并输出颜色矩阵和gamma值,全局分支受DETR启发,网络通过动态查询学习的方式更新颜色矩阵和gamma值。整个模型只有超过9…

Maven简单入门

Maven 一:什么是Maven: Maven是一个项目管理工具,用于构建和管理Java项目。它可以帮助开发人员自动化构建过程,管理项目依赖关系,并协助项目的发布和部署。通过Maven,开发人员可以定义项目的结构、依赖关…

为什么选择VR全景进行企业宣传,如何将VR全景运用在企业展示

引言: 随着科技的不断发展,VR全景技术逐渐成为企业宣传的热门选择。那么,为什么越来越多的企业选择使用VR全景技术进行宣传呢? 一.为什么选择VR全景技术进行企业宣传 1. 提升用户体验 VR全景技术可以为用户营造身临…

基于udp协议的网络通信(windows客户端版+简易聊天室版),重定向到终端

目录 和windows通信 引入 思路 WSADATA 代码 运行情况 简单的聊天室 思路 重定向 代码 terminal.hpp -- 重定向函数 服务端 客户端 运行情况 和windows通信 引入 linux和windows都需要联网,虽然他们系统设计不同,但网络部分一定是相同的,所以套接字也是一样的 这…

【学习记录】调试千寻服务+DTU+导远RTK过程的记录

最近调试车载定位的时候,遇到了一些问题,千寻服务已经正确配置到RTK里面了,但是导远的定位设备一直显示RTK浮动解,通过千寻服务后台查看状态,长时间显示不合法的GGA值。 首先,通过四处查资料,千…

一种基于宏和serde_json实现的rust web中统一返回类

本人rust萌新,写web碰到了这个,基于ChatGPT和文心一言学了宏,强行把这玩意实现出来了,做个学习记录,如果有更好的方法,勿喷。 先看效果,注意不支持嵌套,且kv映射要用>(因为它这个…

C语言实战——扫雷游戏

目录 1. 扫雷游戏分析和设计2.扫雷游戏的代码实现 1. 扫雷游戏分析和设计 1.1扫雷游戏的功能说明 使用控制台实现经典的扫雷游戏游戏可以通过菜单实现继续玩或者退出游戏扫雷的棋盘是9*9的格子默认随机布置10个雷可以排查雷 如果位置不是雷,就显示周围有几个雷 如果…