在MakerDAO的执行中定义的DSProxy函数包含以下组装代码:
assembly {
let succeeded := delegatecall(sub(gas, 5000), _target, add(_data, 0x20), mload(_data), 0, 0)
let size := returndatasize
response := mload(0x40)
mstore(0x40, add(response, and(add(add(size, 0x20), 0x1f), not(0x1f))))
mstore(response, size)
returndatacopy(add(response, 0x20), 0, size)
switch iszero(succeeded)
case 1 {
revert(add(response, 0x20), size)
}
}在高层,我明白这是怎么回事。它在_target存储的上下文中委托对DSProxy契约上的函数的调用。它从剩余的津贴中减去5000股气体,以确保剩余的气体能够用于执行其余的装配代码。它将_data (定义为bytes memory的变量)传递为回调数据。然后,它将返回的值打包到response变量中(再次定义为bytes memory)。最后,它检查合同调用是否失败,如果失败,则恢复。
我很难理解这句话:
mstore(0x40, add(response, and(add(add(size, 0x20), 0x1f), not(0x1f))))为什么他们将0x20添加到size中,0x1f添加到它的值中,最后又否定了0x1f?我理解这些是指针,但我不知道它们为什么要从这些特定的值中读取。
发布于 2021-08-30 11:34:26
信息: 0x40是一个特殊地址:https://docs.soliditylang.org/en/v0.8.7/assembly.html#example
稳健性以以下方式管理内存。内存中的0x40位置有一个“空闲内存指针”。如果要分配内存,请从指针指向的位置开始使用该内存并更新它。
所以代码读为
// how much memory do we need to allocate for the response ?
let size := returndatasize
// load the response at the address given by the free memory pointer
response := mload(0x40)
// save at the free memory pointer address (0x40) the next position of the available memory
mstore(0x40, add(response, and(add(add(size, 0x20), 0x1f), not(0x1f)))) 这是为了更新空闲内存指针(0x40)
的倍数。
所以这基本上是
“将空闲内存指针(0x40)设置为响应起始位置(响应)之后下一个32字节的倍数,我通过添加响应大小(大小)来计算响应起始位置(响应)”
https://ethereum.stackexchange.com/questions/108022
复制相似问题