目录
4、Solidity 0.8.0版本对算术运算有什么重大变化?
7、ERC20中的 transfer 和 transferFrom 之间有什么区别?
8、对于地址 allowlist,使用映射还是数组更好?为什么?
13、tx.origin 和 msg.sender 之间有什么区别?
1、私有、内部、公共和外部函数之间的区别?
1、私有函数(private)
- 只能在定义它的合约内部被访问
- 甚至是合约内的其他函数也无法访问该私有函数
- 提供了最高级别的隐私保护
2、内部函数(internal)
- 可以在定义它的合约内部以及从该合约继承的所有子合约中访问
- 类似于OOP中的"protected"访问修饰符
3、公共函数(public)
- 可以从合约外部调用,包括其他合约和以太坊账户
- 公共函数是开放的,能够在区块链上被任何人访问
4、外部函数(external)
- 只能从合约之外调用,包括其他合约和账户
- 内部函数无法直接调用外部函数
- 消耗的gas更少,因为它不需要通过EVM的上下文切换
- 通常用于编写公共函数
2、智能合约大小大约可以有多大?
Solidity智能合约的大小受到以太坊虚拟机(EVM)的限制,合约的最大大小取决于以下几个因素:
- 可用gas限制 每个交易在EVM中执行时都需要消耗一定的gas,gas的总量是有限的。合约的大小会影响部署和执行合约所需的gas消耗。
- 区块gas限制 每个区块只能包含有限的gas用于执行交易。如果合约代码过大,可能需要多个区块的gas才能部署。
- 区块大小限制 由于每个区块的大小有上限(当前约为1MB),如果合约代码过大,它可能无法被包含在一个区块中。
通常来说,一个典型的合约大小应该控制在24KB以内。更精确地说:
- 较小的合约(小于16KB)可以被很好地传播和执行
- 中等大小的合约(16-24KB)在部署和执行时需要更多gas
- 超过24KB的合约被认为非常大,可能会遇到gas不足或无法部署的问题
3、create 和 create2 之间有什么区别?
create
和create2
都是 Solidity 中用于部署新合约的操作码,但它们有以下区别:1、地址确定性
create
用于部署一个新合约,新合约的地址是由创建者的地址、创建者的nonce值以及部署合约的字节码通过一个确定性的计算得到的。这种方式无法预先确定新合约的地址。
create2
则可以在部署前就计算出新合约的地址。新合约的地址由4个参数通过一个哈希函数确定: 创建者地址、盐值(salt)、初始化代码和部署合约的字节码。只要这4个参数保持不变,新合约的地址就是确定的。2、重新部署
create
无法保证同一份字节码连续部署两次会得到同一个地址。
create2
由于地址是确定的,因此连续两次使用相同的4个参数部署同一个字节码,得到的合约地址将完全相同。这在一些需要可重入地址的场景下非常有用。3、版本
create
指令在 EVM 的最初版本中就有了。
create2
是在 EVM 的 Byzantine 分叉中引入的,用于增加地址确定性。总的来说,
create2
通过增加盐值作为额外的输入,解决了create
无法获得确定性地址的问题。这对于一些复杂的智能合约应用(如状态分片、钻石模式等)非常有帮助。但create
由于简单和广泛支持,在大多数情况下仍是更常用的选择。
4、Solidity 0.8.0版本对算术运算有什么重大变化?
Solidity 0.8.0版本对算术运算做出了一些重大变化,主要包括:
1. 溢出和下溢检查
在0.8.0版本之前,算术运算如果发生溢出或下溢,结果会自动进行环绕。从0.8.0开始,缺省情况下溢出和下溢会导致恢复失败(revert),从而避免了意外的结果。例如:
uint8 a = 255; a++; // 0.8.0之前结果为0, 现在会恢复失败
可以使用未检查的操作来获得旧有行为。
2. 除法的行为变化
在0.8.0之前,如果除数为0,除法运算会返回结果0。从0.8.0开始,任何被0除都会导致恢复失败。例如:
uint256 x = 5 / 0; // 0.8.0之前返回0, 现在会恢复失败
3. 新增的微调编码操作
引入了新的位移运算编码,使得二进制比特级编码更容易:
`>>>`无符号右移 `<<`左移 `&`按位与 `|` 按位或 `^`按位异或 `~`按位取反
这些操作使得在Solidity中进行低级别的按位运算成为可能。
0.8.0版本的这些变化增强了算术运算的安全性和可靠性,但也要求开发人员更加注意溢出和除零等边缘情况。这些变化符合其他高级语言的惯例,有助于编写更加健壮的智能合约代码。