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.mfbz.cn/a/456851.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【应急响应靶场web1】

文章目录 前言 一、web1 1、应急响应 1)背景 2)报错处理 3)webshell查杀 4)网站日志排查 5)隐藏账户 6)挖矿程序 2、渗透复现 1)弱口令登录 2)插件上传 3)getshell 总结 …

还有没有免费裁剪音频的软件?15款音乐裁剪软件测评!(不断更新)

市面上有哪些免费裁剪音频的软件呢?今天,我们就来为大家详细介绍15款热门的音乐裁剪软件,并对其进行深度测评。 裁剪音频软件测评1:金舟音频大师 好评指数:4.5/5 优点罗列:支持音频格式转换、裁剪、降噪、…

Linux-vim显示乱码

Linux运维工具-ywtool 目录 一.问题二.解决2.1 编辑VIM的配置文件2.2 添加以下内容 一.问题 用vim编辑的时候,中文显示乱码 二.解决 2.1 编辑VIM的配置文件 vim ~/.vimrc #如果这个文件不存在,创建一个即可2.2 添加以下内容 添加完成以后就不会在出现中文乱码了 set fil…

爬虫的去重

去重基本原理 爬虫中什么业务需要使用去重 防止发出重复的请求防止存储重复的数据 在爬取网页数据时,避免对同一URL发起重复的请求,这样可以减少不必要的网络流量和服务器压力,提高爬虫的效率,在将爬取到的数据存储到数据库或其…

一个简单而绝妙的思维技巧

在文章的最开头,我想先问你一个问题: 你希望未来的你是什么样的?你希望未来的你比现在的你过得更好,还是过得更糟? 我想,应该没有人会选择后者吧? 尽管从客观上说,未来的我们很可能…

配置安装 Kuboard - kubernetes

目录 安装 Kuboard v3 - kubernetes | Kuboard 将官方yaml文件拿到本地 等待 Kuboard v3 就绪 访问 Kuboard 安装 Kuboard v3 - kubernetes | Kuboard Kuboard的官方非常丰富,大家也可以参考官网教程 将官方yaml文件拿到本地 ​kubectl apply -f https://add…

自定义指令控制权限

1.新建directives auth.ts 2.完整的auth.ts import { wmsStore } from "/store/pinia";//判断是否有某个角色的函数 function hasRoles(role: any) {const pinaRoles wmsStore().roles;if (typeof role string) {return pinaRoles.includes(role)} else if (Array…

docker部署Atheos云IDE平台

Codiad 是一个基于 Web 的 IDE 框架 部署 下载镜像 docker pull hlsiira/atheosvim docker-compose.yaml version: 3 services:atheos:image: hlsiira/atheosports:- 8565:80container_name: atheosrestart: always启动 docker-compose up -d访问 http://x.x.x.x:8565

ios开发错误积累

1.xcode 下载模拟器报错 Could not download iOS 报错: 解决: 1、去官网下载自己需要 地址(https://developer.apple.com/download/all) 2、下载完成后,执行以下命令添加:xcrun simctl runtime add /路径…

NLP:HanLP的下载与使用

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

类和对象练习题

第1题 import java.util.Scanner; public class Homework01{public static void main(String[] args){//创建一个double类型的数组double array[]new double[6];//创建一个输入对象Scanner inputnew Scanner(System.in);//提示信息:对数组元素进行赋值System.out.pr…

22-Java状态模式 ( State Pattern )

Java状态模式 摘要实现范例 状态模式(State Pattern)中类的行为是基于它的状态改变的 在状态模式中,我们创建表示各种状态的对象和一个行为随着状态对象改变而改变的 context 对象 状态模式属于行为型模式 摘要 1. 意图 允许对象在内部…

Qt之格栅布局(QGridLayout)控件填满整个单元格

Qt专栏:http://t.csdnimg.cn/GQN1M 目录 1.现象1 2.解决方案 3.现象2 4.解决方案 5.总结 1.现象1 今天在用QGridLayout布局的时候,添加到布局的QWidget有文本框、标签、组合框和按钮等等,布局两列,通过下面的方式添加进去的&…

Edge-TTS:微软推出的,免费、开源、支持多种中文语音语色的AI工具

项目地址:rany2/edge-tts: Use Microsoft Edges online text-to-speech service from Python WITHOUT needing Microsoft Edge or Windows or an API key (github.com) Edge-TTS是由微软推出的文本转语音Python库,通过微软Azure Cognitive Services转化文…

计算机网络——OSI网络层次模型

计算机网络——OSI网络层次模型 应用层表示层会话层传输层TCP和UDP协议复用分用 网络层数据链路层物理层OSI网络层次模型中的硬件设备MAC地址和IP地址MAC地址IP地址MAC地址和IP地址区别 OSI网络层次模型通信过程解释端到端点到点端到端和点到点的区别 我们之前简单介绍了一下网…

在【IntelliJ IDEA】中配置【Tomcat】【2023版】【中文】【图文详解】

作为一款功能强大的集成开发环境(IDE),IntelliJ IDEA为Web服务器提供了卓越的支持,从而极大地简化了程序员在Web开发过程中的工作流程。学习Java Web开发实质上就是掌握如何创造动态Web资源,这些资源在完成开发后&…

鸿蒙Harmony应用开发—ArkTS声明式开发(基础手势:Text)

显示一段文本的组件。 说明: 该组件从API Version 7开始支持。后续版本如有新增内容,则采用上角标单独标记该内容的起始版本。 子组件 可以包含Span和ImageSpan子组件。 接口 Text(content?: string | Resource, value?: TextOptions) 从API versi…

(码农福利) 介绍几个不用魔法 就能免费使用的AI工具

因为 AI的飞速发展 IT行业已经可以说非常的卷了 作为程序员 如果不具备 AI 使用的能力 很快就会被淘汰 但 在社区内 无法直接谈论魔法 大部分程序员 可能也不具备魔法 今天说一个不需要魔法 好用的 AI工具 我们打开官网 https://chandler.bet/#/overView 点击 Get Chrome Ex…

部署docker仓库harbor

1、下载包 1、包已上传有两个harbor.v2.6.0.tar与harbor.tar 2、harbor.tar解压后会生成harbor目录,将harbor.v2.6.0.tar移动到harbor目录下。 3、执行harbor目录下的install.sh 4、执行完后修改配置文件 2、修改配置文件 vim /root/harbor/make/ harbor.yml.tmpl …

微信小程序-day01

文章目录 前言微信小程序介绍 一、为什么要学习微信小程序?二、微信小程序的历史创建开发环境1.注册账号2.获取APPID 三、下载微信开发者工具1.创建微信小程序项目2.填写相关信息3.项目创建成功 四、小程序目录结构项目的主体组成结构 总结 前言 微信小程序介绍 微信小程序&…