美文网首页
20230315Solidity智能合约开发手册学习笔记

20230315Solidity智能合约开发手册学习笔记

作者: 李荣强Justin | 来源:发表于2023-03-14 16:32 被阅读0次

原文: https://www.freecodecamp.org/chinese/news/learn-solidity-handbook/#what-is-contract-state

这是一篇我学习上面链接的学习笔记.

全局变量: msg.data. msg.value. msg.send msg.gas.  block.timestamp

状态变量: 合约内,函数外的变量(类似java中的成员变量)

局部变量: 就是函数内部变量(类似java中函数内的内部变量)

1 ETH = 10**18 WEI

1 GWEI = 10**9 WEI

1个字节=8个bit ,8个字节=一个word

const 常量,必须是硬编码写死的东西

immutable :不可变量,可以赋值一次,通常是构造函数中赋值,之后就再也不能修改了。

可见性修饰符: public external internal private

对于状态变量来说。

  public变量是最大的访问权限,合约内部,合约外部,以及外部账户都可以访问,并且加了public函数默认会生成get方法。

  状态变量默认的访问权限就是internal,其根private权限类似,只在合约内部访问,唯一的区别就是internal的变量可以访问派生类中使用标识位

  internal的变量。

  private 标识的状态变量是只有在当前合约内部才可以访问

  external不适用于状态变量,只有函数才有这个修饰符

对于函数来说,标识为public 的函数可以在合约内部,合约外部以及其他合约中调用。

声明为external的函数,只能是合约外部才可以访问,合约内部不能调用声明为external的函数。当然外部账户也可以访问external的函数

internal的函数可以在子类中访问到,外部合约账户外部账户都不能访问internal函数。

private的函数也是只有在当前合约内部才能访问,这体现了封装性。

构造函数编译之后是不在字节码文件中了。

calldata 是memory的只读部分

constant 和immutable关键词对应的变量,只编译后都硬编码到合约的字节码中。

solidity是静态类型的语言

payable(msg.sender).transfer(address(this).balance);这句话的意思是将当前合约的所有余额,转账给调用方,也就是msg.sender

转出合约地址

回退函数有两种情况下被调用,一种是向合约转账,一种就是调用合约不存在的方法.

一个合约只有一个fallback方法

//没有function关键字 ,只用来接收主币,不接收相关的参数.

receive() external payable{

}

receive() 和fallback()函数的调用顺序

调用时发送了eth,那么就判断msg.data是否为空

如果msg.data为空,则继续判断receive()方法是否存在,如果存在,调用receive方法,否则调用fallback方法

如果msg.data不为空,则调用fallback方法

payable 的时候,gas必须设置为2300

销毁合约的时候,会给合约发送剩余的资金eth,无论接收方是不是有receive和fallback函数(正常逻辑下,没有这两个函数无法接受eth转账)

但是通常情况下,如无必要,合约是尽量不要销毁.

如果确实有类似想禁用方法弃用合约的时候,尽量使用状态变量的值范围进行判断,从而实现类似的功能

合约销毁之后还是可以调用,只是大部分的方法都失效了.

unicode字面变量的用法,比如传递中文

address(this).balance == 取当前地址的余额

涉及到余额修改等操作,遵循三步走

第一是判断对方是否有权限,限额,调用方的身份等操作.

第二是有了权限之后再去改状态.

第三部才是执行正式的转账操作

后面是发出事件通知

数组通过push函数进行增加元素

为什么有transferFrom这个函数,就是因为我们给了某个合约转账我们当前账户某个币的权限,因此对方才可以调用

某个币的transferFrom函数,从我们地址转token到其他地方,原因是因为我们给了授权,因此要非常谨慎的给出授权.

在solidity当中,固定大小的数组按照值来传递,而动态大小的数组按照引用传递.

固定大小的数组按值传递(在代码中传递时复制),动态大小的数组按引用传递(指向内存地址的指针在代码中传递)。

动态大小的数组可以使用push方法增加元素,而固定大小的数组是不能使用push方法的

solidity中三种抛出错误的方式: require() assert() revert()

为什么要使用require() 的好处是它会返回未使用的 gas,而如果在require之前调用的语句,那是不能的.

虽然assert也有类似的功能,我们称之为断言,确定某个值不会发生改变,跟我们预想的一样,也是执行后续操作的先决条件.

在sol0.8版本之前,assert是要用光所有的gas. 因此我们需要更多的使用require而不是assert

同时,使用revert抛出自定义异常,可以提高代码的可读性和精准的暴露更多问题,同时他的gas费消耗会更低.

未使用的gas将返回给调用者。

关于override 和overload,其实在java中也有类似的,所谓的override是子类对于父类函数的逻辑覆盖.

而overload发生在同一个类的不同函数之间,只是名称相同,但是参数不一样,但是通常不建议这么写.

同时在合约编译的时候,有多个父合约的情况,编译完之后其实是将父类的代码装配到子类中,是一个组合的合约代码

类型转换导致数据丢失的情况要非常注意.

Keccak256是一种哈希算法,不管是什么值,输出的都是256位数的hash编码,通常用来比较两个字符串是否一样,

原理就是调用keccak256函数,分别取每个字符串的字节码,然后两个字节码进行比对.

EOA: external owner account

关于receive函数和fallback函数,fallback函数是默认当没有方法去处理对应的合约调用请求时,fallback方法去处理.

如何使得你的合约能够接受ether转账.

1. 定义receiv函数,或者将fallback函数加上payable关键词

2. selfdestruct函数,将当前合约的余额转到调用方.

当前合约向其他合约或者外部地址转eth有三种方式 transfer send call,目前transfer和send处于安全考虑不推荐使用,但是仍然可以用,推荐使用call方法

由于 Solidity 库是无状态的,也就是没有任何除常量外的可变的状态变量,并且所有的方法都是实例,不能是抽象的.

即所有的方法都是view或者pure关键词.

在定义事件的时候,加了indexed关键词数据都是由evm进行索引,索引事件参数在solidity中称为topics,一个事件最多有四个参数,而非匿名的topics最多允许自定义三个索引参数,其中一个用于指定ABI编码的十六进制形式的事件签名

subgraph是通过监听区块链的事件,然后去区块链浏览区中获取日志信息,从而建立相关的索引.

相关文章

网友评论

      本文标题:20230315Solidity智能合约开发手册学习笔记

      本文链接:https://www.haomeiwen.com/subject/sclkrdtx.html