<<WTF-Solidity>>学习笔记(part 25-28)
part 25:
create2的实际应用场景
-
交易所为新用户预留创建钱包合约地址。
-
由
CREATE2
驱动的factory
合约,在Uniswap V2
中交易对的创建是在Factory
中调用CREATE2
完成。这样做的好处是: 它可以得到一个确定的pair
地址, 使得Router
中就可以通过(tokenA, tokenB)
计算出pair
地址, 不再需要执行一次Factory.getPair(tokenA, tokenB)
的跨合约调用。
1. CREATE2 的核心特性
- 使用
CREATE2
部署合约时,合约地址是通过以下信息计算的:- 部署者的地址(部署合约的地址)。
salt
(一个开发者定义的值,类似于一个种子值)。- 合约的初始化代码哈希。
生成地址的公式如下:
scss
Copy code
address = keccak256(0xff ++ 部署者地址 ++ salt ++ init_code_hash)[12:]
因此,合约地址是可预测的,只要部署参数一致,生成的地址也会保持一致。
part 26:
注意事项
- 对外提供合约销毁接口时,最好设置为只有合约所有者可以调用,可以使用函数修饰符
onlyOwner
进行函数声明。 - 当合约中有
selfdestruct
功能时常常会带来安全问题和信任问题,合约中的selfdestruct功能会为攻击者打开攻击向量(例如使用selfdestruct
向一个合约频繁转入token进行攻击,这将大大节省了GAS的费用,虽然很少人这么做),此外,此功能还会降低用户对合约的信心。
part 27:
ABI
(Application Binary Interface,应用二进制接口)是与以太坊智能合约交互的标准。数据基于他们的类型编码;并且由于编码后不包含类型信息,解码时需要注明它们的类型。
Solidity
中,ABI编码
有4个函数:abi.encode
, abi.encodePacked
, abi.encodeWithSignature
, abi.encodeWithSelector
。而ABI解码
有1个函数:abi.decode
,用于解码abi.encode
的数据。这一讲,我们将学习如何使用这些函数。
abi.encodePacked
将给定参数根据其所需最低空间编码。它类似 abi.encode
,但是会把其中填充的很多0
省略。比如,只用1字节来编码uint8
类型。当你想省空间,并且不与合约交互的时候,可以使用abi.encodePacked
,例如算一些数据的hash
时。需要注意,abi.encodePacked
因为不会做填充,所以不同的输入在拼接后可能会产生相同的编码结果,导致冲突,这也带来了潜在的安全风险。
ABI的使用场景
-
在合约开发中,ABI常配合call来实现对合约的底层调用。
bytes4 selector = contract.getValue.selector; bytes memory data = abi.encodeWithSelector(selector, _x); (bool success, bytes memory returnedData) = address(contract).staticcall(data); require(success); return abi.decode(returnedData, (uint256));
-
ethers.js中常用ABI实现合约的导入和函数调用。
const wavePortalContract = new ethers.Contract(contractAddress, contractABI, signer); /* * Call the getAllWaves method from your Smart Contract */ const waves = await wavePortalContract.getAllWaves();
-
对不开源合约进行反编译后,某些函数无法查到函数签名,可通过ABI进行调用。
- 0x533ba33a() 是一个反编译后显示的函数,只有函数编码后的结果,并且无法查到函数签名
- 这种情况无法通过构造interface接口或contract来进行调用
这种情况下,就可以通过ABI函数选择器来调用
bytes memory data = abi.encodeWithSelector(bytes4(0x533ba33a)); (bool success, bytes memory returnedData) = address(contract).staticcall(data); require(success); return abi.decode(returnedData, (uint256));
总结
在以太坊中,数据必须编码成字节码才能和智能合约交互。这一讲,我们介绍了4种abi编码
方法和1种abi解码
方法。
part 28:
Keccak256和sha3
这是一个很有趣的事情:
- sha3由keccak标准化而来,在很多场合下Keccak和SHA3是同义词,但在2015年8月SHA3最终完成标准化时,NIST调整了填充算法。所以SHA3就和keccak计算的结果不一样,这点在实际开发中要注意。
- 以太坊在开发的时候sha3还在标准化中,所以采用了keccak,所以Ethereum和Solidity智能合约代码中的SHA3是指Keccak256,而不是标准的NIST-SHA3,为了避免混淆,直接在合约代码中写成Keccak256是最清晰的。