
这是一个不完整的笔记
参考文献:hackquest.io
abi函数编码
方法
abi.encodeWithSignature(SIGNATURE,...ARGS)
: 使用方法签名进行编码
abi.encodeWithSelector(SELECTOR,...ARGS)
: 使用selector进行编码。
EXAMPLE
使用 abi.encodeWithSignature 编码一个名为 transfer 的函数,传入的值为address类型的 msg.sender 和uint256类型的50。
1 | function transfer(address to, uint256 amount) {...} |
使用 abi.encodeWithSelector 函数编码一个名为 flashLoan 的函数,传入的参数为 address(this) 和 100。(手动计算函数选择器)
1 | function flashLoan(address to, uint256 amount) {...} |
扩展
获取Selector
- 方法.selector。
bytes4(keccak256("函数名(参数列表)"))
可以通过字符串获取方法的selector(是否有些多此一举?)
低级调用 low level call
就是与EVM(以太坊虚拟机)进行交互。(类似于JVM的unsafe)
address.call 最基础的低级调用
address.call
可以直接代表某地址执行合约的某个方法。
DOCS
(bool success, bytes memory data) = address(targetAddress).call{value: amount}(abiEncodedData);
- targetAddress: 目标地址
value: amount
: 发送以太币,可选参数- aboEncodeedData: 使用abi编码后的数据。
EXAMPLE
使用低级的 call 调用 targetAddress 地址的 dosome(uint256 amount) 函数,传参为5。(使用 abi.encodeWithSignature )
1 | address(targetAddress).call(abi.encodeWithSignature("dosome(uint256)",5)); |
address.delegatecall
与call类似。这个会将要调用的函数复制到当前合约的上下文执行。
==这个非常危险,经常发生安全漏洞和黑客攻击==
DOCS
1 | (bool success, bytes memory data) = address(targetAddress).delegatecall(abiEncodedData); |
场景
由于部署的 Solidity 合约不可更改,那我们希望更新函数功能的话怎么办呢?我们先部署一个代理合约 A,在里面 delegatecall 合约 B 的功能。
更新时,只需要更改合约 B 的地址变成合约 C,这样合约 A 就可以使用新版合约 C 的功能。
msg 全局变量
msg.value
获取调用者附加的以太币值
msg.data
bytes。包含了调用函数的原始数据
场景
当你调用合约的函数时,除了传递以太币外,还可以在函数调用中传递其他数据。这些数据可以是任何类型,包括字符串、字节数组等。通过使用 msg.data,您可以访问这些传递的数据,并在合约中执行相应的逻辑。