WEB3之路(一)-- solidity学习笔记

这篇具有很好参考价值的文章主要介绍了WEB3之路(一)-- solidity学习笔记。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

学习资料:GitHub - AmazingAng/WTFSolidity: 我最近在重新学solidity,巩固一下细节,也写一个“Solidity极简入门”,供小白们使用(编程大佬可以另找教程),每周更新1-3讲。

变量类型

  • 数值类型(Value Type):包括布尔型,整数型等等,这类变量赋值时候直接传递数值。
  • 引用类型(Reference Type):包括数组和结构体,这类变量占空间大,赋值时候直接传递地址(类似指针)。
  • 映射类型(Mapping Type)Solidity里的哈希表。
  • 函数类型(Function Type)Solidity文档里把函数归到数值类型,但我觉得他跟其他类型差别很大,所以单独分一类。

一、数值类型

1.布尔型(bool):true 或者 false

2.整型(uint):uint、uint8、uint16、uint32、uint256

        整型数值没有负数

3.地址类型(address):地址类型(address)存储一个 20 字节的值(以太坊地址的大小)

4.定长字节数组:字节数组bytes分两种,一种定长(bytebytes8bytes32),另一种不定长

5.枚举型(enum):枚举(enum)是solidity中用户定义的数据类型

二、引用类型

1.数组(Array):数组(Array)是solidity常用的一种变量类型,用来存储一组数据(整数,字节,地址等等)。数组分为固定长度数组和可变长度数组两种

数组成员:

  • length: 数组有一个包含元素数量的length成员,memory数组的长度在创建后是固定的。
  • push()动态数组bytes拥有push()成员,可以在数组最后添加一个0元素。
  • push(x)动态数组bytes拥有push(x)成员,可以在数组最后添加一个x元素。
  • pop()动态数组bytes拥有pop()成员,可以移除数组最后一个元素。

2.结构体(struct):Solidity支持通过构造结构体的形式定义新的类型

// 结构体用法
    struct Student{
        uint256 id;
        uint256 score; 
    }

三、映射类型

Mapping:声明映射的格式为mapping(_KeyType => _ValueType)

映射的规则:

  • 规则1:映射的_KeyType只能选择solidity默认的类型,比如uintaddress等,不能用自定义的结构体。
  • 规则2:映射的存储位置必须是storage,因此可以用于合约的状态变量,函数中的storage变量。不能用于public函数的参数或返回结果中,因为mapping记录的是一种关系 (key - value pair)。

  • 规则3:如果映射声明为public,那么solidity会自动给你创建一个getter函数,可以通过Key来查询对应的Value

  • 规则4:给映射新增的键值对的语法为_Var[_Key] = _Value,其中_Var是映射变量名,_Key_Value对应新增的键值对

四、函数类型

1.function:声明函数时的固定用法,想写函数,就要以function关键字开头。

2.(<parameter types>):圆括号里写函数的参数,也就是要输入到函数的变量类型和名字。

3.{internal|external|public|private}:函数可见性说明符,一共4种。没标明函数类型的,默认internal

  • public: 内部外部均可见。(也可用于修饰状态变量,public变量会自动生成 getter函数,用于查询数值).
  • private: 只能从本合约内部访问,继承的合约也不能用(也可用于修饰状态变量)。
  • external: 只能从合约外部访问(但是可以用this.f()来调用,f是函数名)
  • internal: 只能从合约内部访问,继承的合约可以用(也可用于修饰状态变量)。

4.[pure|view|payable]:决定函数权限/功能的关键字。

pure和view都不需要付gas

  • pure:不能读取也不能写入
  • view:只能读取
  • payable:可支付

5.[returns ()]:函数返回的变量类型和名称。

常量

一、constant

constant变量必须在声明的时候初始化,之后再也不能改变。尝试改变的话,编译不通过。

二、immutable

immutable变量可以在声明时或构造函数中初始化,因此更加灵活。

常用方法

1.修饰器(modifier)

修饰器(modifier)是solidity特有的语法,类似于面向对象编程中的decorator,声明函数拥有的特性,并减少代码冗余。

   // 定义modifier
   modifier onlyOwner {
      require(msg.sender == owner); // 检查调用者是否为owner地址
      _; // 如果是的话,继续运行函数主体;否则报错并revert交易
   }

2.构造函数(constructor)

构造函数(constructor)是一种特殊的函数,每个合约可以定义一个,并在部署合约的时候自动运行一次。它可以用来初始化合约的一些参数,例如初始化合约的owner地址:

 address owner; // 定义owner变量

   // 构造函数
   constructor() public {
      owner = msg.sender; // 在部署合约的时候,将owner设置为部署者的地址
   }

3.事件(events)

Solidity中的事件(event)是EVM上日志的抽象,它具有两个特点:

  • 响应:应用程序(ether.js)可以通过RPC接口订阅和监听这些事件,并在前端做响应。
  • 经济:事件是EVM上比较经济的存储数据的方式,每个大概消耗2,000-5,000 gas不等。相比之下,存储一个新的变量至少需要20,000 gas

事件的声明由event关键字开头,然后跟事件名称,括号里面写好事件需要记录的变量类型和变量名。以ERC20代币合约的Transfer事件为例:

event Transfer(address indexed from, address indexed to, uint256 value);

4.继承(inheritance)

规则

virtual: 父合约中的函数,如果希望子合约重写,需要加上virtual关键字。

override:子合约重写了父合约中的函数,需要加上override关键。

简单继承

contract Baba is Yeye{}

多重继承

contract Erzi is Yeye, Baba{}

修饰器的继承

用法同函数继承

构造函数的继承

  1. 在继承时声明父构造函数的参数,例如:contract B is A(1)
  2. 在子合约的构造函数中声明构造函数的参数

5.异常(errors)

error:方便高效省gas

error TransferNotOwner(); // 自定义error,在执行当中,error必须搭配revert(回退)命令使用。
  function transferOwner1(uint256 tokenId, address newOwner) public {
        if(_owners[tokenId] != msg.sender){
            revert TransferNotOwner();
        }
        _owners[tokenId] = newOwner;
    }

require:gas随着描述异常的字符串长度增加

使用方法:require(检查条件,”异常的描述”),当检查条件不成立的时候,就会抛出异常。

我们用require命令重写一下上面的transferOwner函数:

 function transferOwner2(uint256 tokenId, address newOwner) public {
        require(_owners[tokenId] == msg.sender, "Transfer Not Owner");
        _owners[tokenId] = newOwner;
    }

assert命令一般用于程序员写程序debug,因为他不能解释抛出异常的原因(比require少个字符串)。他的用法很简单,assert(检查条件),当检查条件不成立的时候,就会抛出异常。

function transferOwner3(uint256 tokenId, address newOwner) public {
        assert(_owners[tokenId] == msg.sender);
        _owners[tokenId] = newOwner;
    }

6.安全数学(SafeMath)

SafeMath用来防止溢出,有四个方法 — add, sub, mul, 以及 div。

using SafeMath for uint256;

uint256 a = 5;
uint256 b = a.add(3); // 5 + 3 = 8
uint256 c = a.mul(2); // 5 * 2 = 10

7.import

solidity支持利用import关键字导入其他源代码中的合约,让开发更加模块化。

// 通过文件相对位置import
import './Yeye.sol';

8.接收ETH

Solidity支持两种特殊的回调函数,receive()fallback(),他们主要在两种情况下被使用:

  1. 接收ETH
  2. 处理合约中不存在的函数调用(代理合约proxy contract

接收ETH函数 receive

receive()只用于处理接收ETH。一个合约最多有一个receive()函数,声明方式与一般函数不一样,不需要function关键字:receive() external payable { ... }

receive()函数不能有任何的参数,不能返回任何值,必须包含externalpayable

当合约接收ETH的时候,receive()会被触发。

回退函数 fallback

fallback()函数会在调用合约不存在的函数时被触发。可用于接收ETH,也可以用于代理合约proxy contractfallback()声明时不需要function关键字,必须由external修饰,一般也会用payable修饰,用于接收ETH:fallback() external payable { ... }

receivefallback都能够用于接收ETH,他们触发的规则如下:

触发fallback() 还是 receive()?
           接收ETH
              |
         msg.data是空?
            /  \
          是    否
          /      \
receive()存在?   fallback()
        / \
       是  否
      /     \
receive()   fallback()

9.发送ETH

transfer

  • 用法是transfer(发送ETH数额)
  • transfer()gas限制是2300,足够用于转账,但对方合约的fallback()receive()函数不能实现太复杂的逻辑。
  • transfer()如果转账失败,会自动revert(回滚交易)。

send

  • 用法是send(发送ETH数额)
  • send()gas限制是2300,足够用于转账,但对方合约的fallback()receive()函数不能实现太复杂的逻辑。
  • send()如果转账失败,不会revert
  • send()的返回值是bool,代表着转账成功或失败,需要额外代码处理一下。

call

  • 用法是call{value: 发送ETH数额}("")
  • call()没有gas限制,可以支持对方合约fallback()receive()函数实现复杂逻辑。
  • call()如果转账失败,不会revert
  • call()的返回值是(bool, data),其中bool代表着转账成功或失败,需要额外代码处理一下。

10.call

call 是address类型的低级成员函数,它用来与其他合约交互。它的返回值为(bool, data),分别对应call是否成功以及目标函数的返回值。

call的使用规则

call的使用规则如下:

目标合约地址.call(二进制编码);

其中二进制编码利用结构化编码函数abi.encodeWithSignature获得:

abi.encodeWithSignature("函数签名", 逗号分隔的具体参数)

函数签名"函数名(逗号分隔的参数类型)"。例如abi.encodeWithSignature("f(uint256,address)", _x, _addr)

另外call在调用合约时可以指定交易发送的ETH数额和gas

目标合约地址.call{value:发送ETH数额, gas:gas数额}(二进制编码);

11.ABI编码解码

abi.encode

将给定参数利用ABI规则编码。ABI被设计出来跟智能合约交互,他将每个参数转填充为32字节的数据,并拼接在一起。

abi.decode

abi.decode用于解码abi.encode生成的二进制编码,将它还原成原本的参数。

12.函数选择器(Selector)

 selector定义为函数签名的哈希的前4个字节

函数签名,为"函数名(逗号分隔的参数类型)"。举个例子,mint的函数签名为"mint(address)"。在智能合约中,不同的函数有不同的函数签名,因此我们可以通过函数签名来确定要调用哪个函数。

13.try-catch

solidity中,try-catch只能被用于external函数或创建合约时constructor(被视为external函数)的调用。基本语法如下:

        try externalContract.f() {
            // call成功的情况下 运行一些代码
        } catch {
            // call失败的情况下 运行一些代码
        }

其中externalContract.f()时某个外部合约的函数调用,try模块在调用成功的情况下运行,而catch模块则在调用失败时运行。

应用

1.ERC20

IERC20ERC20代币标准的接口合约,规定了ERC20代币需要实现的函数和事件。

事件

IERC20定义了2个事件:Transfer事件和Approval事件,分别在转账和授权时被释放

    /**
     * @dev 释放条件:当 `value` 单位的货币从账户 (`from`) 转账到另一账户 (`to`)时.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev 释放条件:当 `value` 单位的货币从账户 (`owner`) 授权给另一账户 (`spender`)时.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);

函数

IERC20定义了6个函数,提供了转移代币的基本功能,并允许代币获得批准,以便其他链上第三方使用。

  • totalSupply()返回代币总供给
  • balanceOf()返回账户余额
  • transfer()转账
  • allowance()返回授权额度
  • approve()授权
  • transferFrom()授权转账

2.erc721

IERC721事件

IERC721包含3个事件,其中TransferApproval事件在ERC20中也有。

  • Transfer事件:在转账时被释放,记录代币的发出地址from,接收地址totokenid
  • Approval事件:在授权时释放,记录授权地址owner,被授权地址approvedtokenid`。
  • ApprovalForAll事件:在批量授权时释放,记录批量授权的发出地址owner,被授权地址operator和授权与否的approved

IERC721函数

  • balanceOf:返回某地址的NFT持有量balance
  • ownerOf:返回某tokenId的主人owner
  • transferFrom:普通转账,参数为转出地址from,接收地址totokenId
  • safeTransferFrom:安全转账(如果接收方是合约地址,会要求实现ERC721Receiver接口)。参数为转出地址from,接收地址totokenId
  • approve:授权另一个地址使用你的NFT。参数为被授权地址approvetokenId
  • getApproved:查询tokenId被批准给了哪个地址。
  • setApprovalForAll:将自己持有的该系列NFT批量授权给某个地址operator
  • isApprovedForAll:查询某地址的NFT是否批量授权给了另一个operator地址。
  • safeTransferFrom:安全转账的重载函数,参数里面包含了data

3.erc1155

面是ERC1155的元数据接口合约IERC1155MetadataURI文章来源地址https://www.toymoban.com/news/detail-784666.html

/**
 * @dev ERC1155的可选接口,加入了uri()函数查询元数据
 */
interface IERC1155MetadataURI is IERC1155 {
    /**
     * @dev 返回第`id`种类代币的URI
     */
    function uri(uint256 id) external view returns (string memory);

IERC1155事件

  • TransferSingle事件:单类代币转账事件,在单币种转账时释放。
  • TransferBatch事件:批量代币转账事件,在多币种转账时释放。
  • ApprovalForAll事件:批量授权事件,在批量授权时释放。
  • URI事件:元数据地址变更事件,在uri变化时释放。

IERC1155函数

  • balanceOf():单币种余额查询,返回account拥有的id种类的代币的持仓量。
  • balanceOfBatch():多币种余额查询,查询的地址accounts数组和代币种类ids数组的长度要相等。
  • setApprovalForAll():批量授权,将调用者的代币授权给operator地址。。
  • isApprovedForAll():查询批量授权信息,如果授权地址operatoraccount授权,则返回true
  • safeTransferFrom():安全单币转账,将amount单位id种类的代币从from地址转账给to地址。如果to地址是合约,则会验证是否实现了onERC1155Received()接收函数。
  • safeBatchTransferFrom():安全多币转账,与单币转账类似,只不过转账数量amounts和代币种类ids变为数组,且长度相等。如果to地址是合约,则会验证是否实现了onERC1155BatchReceived()接收函数。

到了这里,关于WEB3之路(一)-- solidity学习笔记的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • Web3 solidity订单池操作

    前面一篇文章因为一些原因 被设为了进自己可见 需要的朋友可以私信我 之前 我们编写的程序上来看 交易所无非是一个代币的托管上 只是它会更加专业 本文 我们继续来看交易所的一个功能 叫游泳池 例如 我们 100grToken 兑换 1ETH 前提 我们的代币已经能被估值了 例如 你想用

    2024年02月12日
    浏览(49)
  • web3教学-Solidity 入门上手

    步骤大纲 1.Nodejs 2.Solidity编译器,作为npm依赖包 3.Visual Studio Code编译语法的突出显示 4.为开发人员构建的以太坊客户端ethereumjs-testrpc npm install -g solc 然后通过 solcjs-v查看版本 使用vs code进行智能合约的编写 我们打开vs code然后在里面搜索插件Solidity,然后安装 可以在vs终端输入

    2024年02月03日
    浏览(60)
  • 基于web3+solidity的众筹项目

    基本配置:`node`、`npm`、`yarn`,安装`ganache`,`chrome`,`chrome`安装插件`MetaMask`, 主要功能:目的是实现一个简单的众筹平台,允许用户发起筹款项目、捐款、提出使用资金请求以及证明人证明。  部分合约:  1.首先打开ganache软件,进行如下配置,    2.然后通过私钥在metam

    2024年02月02日
    浏览(87)
  • 前端Vue项目调用页面web3.js:连接metaMask钱包,(查询钱包ETH余额,查询代币余额,ETH转账,代币转账,代币授权,查询授权数量,计算价格)等功能

    这里分享下相关文档 1.web3.js中文文档 https://learnblockchain.cn/docs/web3.js/getting-started.html 2.metamask官方文档:https://docs.metamask.io/ 第一种方法:连接钱包 源码: 第二种方法: 连接钱包 安装依赖直接可以使用 源码: 其他功能: 1、在 mounted 中自动检测浏览器是否安装MetaMask钱包 2、查询

    2024年02月11日
    浏览(51)
  • web3 solidity 基础 ERC20 大白话搞懂

    ERC20 是 eth 的一个标准,怎么理解标准一词呢? 标准是大家遵循的一个协议,根据这个协议大家都知道该怎么去做,例如去吃饭的时候人多,你就需要排队,然后去窗口跟阿姨说你要吃什么,阿姨就会帮你打;若你不准守这个标准,直接冲进后厨,翻开泔水,大喊着我要吃饭

    2024年01月22日
    浏览(49)
  • Web3 solidity编写cancelorder取消订单函数 并梳理讲述逻辑

    上文 Web3 solidity订单池操作 中 我们讲述了订单池的基本概念 并手动编写了创建订单的操作 最近的 我们还是先将 ganache 环境起起来 然后 我们打开项目 上文中 我们写了makeOrder创建订单的函数 但是 也带出一个问题 我们创建之后 如果不要了 怎么干掉呀? js中我们有 splice 但

    2024年02月09日
    浏览(47)
  • 欢迎来到Web3.0的世界:Solidity智能合约安全漏洞分析

    智能合约是运行在区块链网络中的一段程序,经由多方机构自动执行预先设定的逻辑,程序执行后,网络上的最终状态将不可改变。智能合约本质上是传统合约的数字版本,由去中心化的计算机网络执行,而不是由政府或银行等中央集权机构执行。智能合约程序可以用Solidi

    2024年02月03日
    浏览(45)
  • 目录(文章更新中...)《实战NFT web3 solidity(新版本0.8.+)》

    注:由于是付费专栏内容,若有错误请及时联系@1_bit,博客链接:https://blog.csdn.net/A757291228 ,或在文章下留言,收到后将会对错误进行改正,若是版本更新导致的问题也希望大家对错误进行提交,尽力去保证付费用户该得到的权益。 友情提示:本系列文章读者最好学过一门编

    2024年02月16日
    浏览(47)
  • Web3时代:探索DAO的未来之路

    Web3 的兴起不仅代表着技术进步,更是对人类协作、创新和价值塑造方式的一次重大思考。在 Web3 时代,社区不再仅仅是共同兴趣的聚集点,而变成了一个价值交流和创新的平台。 去中心化:超越技术的革命 去中心化不仅仅是 Web3 的技术基础,它在更深层次上改变了我们对组

    2024年02月06日
    浏览(52)
  • 【Web3】Web3Js高频Api

    目录 Web3Js方法 初始化Web3实例 Web3Api 创建账号Api 获取余额Api 单位转换工具函数 Web3Js方法 web3.eth:用于与以太坊区块链和智能合约之间的交互。 web3.utils:包含一些辅助方法。 web3.shh:用于协议进行通信的P2P和广播。 web3.bzz:用于与群网络交互的Bzz模块。 初始化Web3实例 npm

    2024年02月13日
    浏览(41)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包