我正在Ethereum上检查一个气体标记代码。令牌创建一些使用CREATE2的虚拟智能契约,然后计算地址。后来,它摧毁了他们,以获得汽油退款。
造币部分如下所示
assembly {
mstore(0, 0x746d4946c0e9F43F4Dee607b0eF1fA1c3318585733ff6000526015600bf30000)
for {let i := div(value, 32)} i {i := sub(i, 1)} {
pop(create2(0, 0, 30, add(offset, 0))) pop(create2(0, 0, 30, add(offset, 1)))
pop(create2(0, 0, 30, add(offset, 2))) pop(create2(0, 0, 30, add(offset, 3)))
pop(create2(0, 0, 30, add(offset, 4))) pop(create2(0, 0, 30, add(offset, 5)))
pop(create2(0, 0, 30, add(offset, 6))) pop(create2(0, 0, 30, add(offset, 7)))
pop(create2(0, 0, 30, add(offset, 8))) pop(create2(0, 0, 30, add(offset, 9)))
pop(create2(0, 0, 30, add(offset, 10))) pop(create2(0, 0, 30, add(offset, 11)))
pop(create2(0, 0, 30, add(offset, 12))) pop(create2(0, 0, 30, add(offset, 13)))
pop(create2(0, 0, 30, add(offset, 14))) pop(create2(0, 0, 30, add(offset, 15)))
pop(create2(0, 0, 30, add(offset, 16))) pop(create2(0, 0, 30, add(offset, 17)))
pop(create2(0, 0, 30, add(offset, 18))) pop(create2(0, 0, 30, add(offset, 19)))
pop(create2(0, 0, 30, add(offset, 20))) pop(create2(0, 0, 30, add(offset, 21)))
pop(create2(0, 0, 30, add(offset, 22))) pop(create2(0, 0, 30, add(offset, 23)))
pop(create2(0, 0, 30, add(offset, 24))) pop(create2(0, 0, 30, add(offset, 25)))
pop(create2(0, 0, 30, add(offset, 26))) pop(create2(0, 0, 30, add(offset, 27)))
pop(create2(0, 0, 30, add(offset, 28))) pop(create2(0, 0, 30, add(offset, 29)))
pop(create2(0, 0, 30, add(offset, 30))) pop(create2(0, 0, 30, add(offset, 31)))
offset := add(offset, 32)
}
for {let i := and(value, 0x1F)} i {i := sub(i, 1)} {
pop(create2(0, 0, 30, offset))
offset := add(offset, 1)
}
} 代码显然创建了n个智能契约,但是在一开始使用mstore的意义是什么。另外,我不明白30在创建命令和使用pop中的意义。为什么需要他们?
燃烧的部分来了
契约尝试基于已刻录的令牌获取下一个可燃地址的地址,然后将其用作salt来生成令牌的地址。
function computeAddress2(uint256 salt) public view returns (address) {
bytes32 _data = keccak256(
abi.encodePacked(bytes1(0xff), address(this), salt, bytes32(0x3c1644c68e5d6cb380c36d1bf847fdbc0c7ac28030025a2fc5e63cce23c16348))
);
return address(uint256(_data));
}
function _destroyChildren(uint256 value) internal {
uint256 _totalBurned = totalBurned;
for (uint256 i = 0; i < value; i++) {
computeAddress2(_totalBurned + i).call("");
}
totalBurned = _totalBurned + value;
}打电话给合同怎么会毁了它?部署的虚拟合同代码在哪里?我需要帮助来理解流程。
发布于 2021-03-24 19:07:39
这里引用了另一个气体令牌的文档,解释了mstore正在做什么:
// EVM assembler of runtime portion of child contract:
// ;; Pseudocode: if (msg.sender != 0x000000000000cb2d80a37898be43579c7b616844) { throw; }
// ;; suicide(msg.sender)
// PUSH14 0xcb2d80a37898be43579c7b616856 ;; hardcoded address of this contract
// CALLER
// XOR
// JUMP
// JUMPDEST
// CALLER
// SELFDESTRUCT
// Or in binary: 6dcb2d80a37898be43579c7b6168563318565b33ff
// Since the binary is so short (21 bytes), we can get away
// with a very simple initcode:
// PUSH21 0x6dcb2d80a37898be43579c7b6168573318565b33ff
// PUSH1 0
// MSTORE ;; at this point, memory locations mem[10] through
// ;; mem[30] contain the runtime portion of the child
// ;; contract. all that's left to do is to RETURN this
// ;; chunk of memory.
// PUSH1 21 ;; length
// PUSH1 11 ;; offset
// RETURN
// Or in binary: 746dcb2d80a37898be43579c7b6168563318565b33ff6000526015600bf30000
// Almost done! All we have to do is put this short (30 bytes) blob into
// memory and call CREATE with the appropriate offsets.https://ethereum.stackexchange.com/questions/87830
复制相似问题