原文: 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是通过监听区块链的事件,然后去区块链浏览区中获取日志信息,从而建立相关的索引.
网友评论