你好,当我想要访问一个双映射时,我被yul内联程序集卡住了。
mapping(address => mapping(address => uint256)) public approval_;
function approve(address spender, uint256 amount) external returns (bool) {
assembly {
// doc => https://docs.soliditylang.org/en/v0.8.9/internals/layout_in_storage.html
// keccak(keccak(spender) => keccak(caller => approve slot))
// load if user already approve this user
let msgsender
mstore(msgsender, caller()) // store msg.sender
let spender_
mstore(spender_, spender) // store spender
let ptr := mload(0x40) // load free memory
mstore(ptr, keccak256(spender_, 0x20)) // store hash spender
mstore(add(ptr, 0x20), msgsender) // store msg.sender after spender hash
mstore(add(ptr, 0x40), approval_.slot) // store approval slot after msg.sender
let googHash := keccak256(add(ptr, 0x20), 0x40) // hash msg.sender + approval slot
mstore(add(ptr, 0x20), googHash)
let approveSlot := keccak256(ptr, 0x40) // hash => hash spender + hash msg.sender + approval slot
let balanceApproved := sload(approveSlot) // load approve balance
// store the new value
sstore(approveSlot, add(balanceApproved, amount))
}
return true;}
不明白我做错了什么,谢谢你的帮助;)
发布于 2022-09-03 22:30:00
你几乎把一切都做对了,只有两个错误。
首先,当您将msg.sender和spender分配给内存时。看看发生了什么
let msgsender // msgsender = 0x00
mstore(msgsender, caller()) // memory(0x00) = caller()
let spender_ // spender_ = 0x00
mstore(spender_, spender) // memory(0x00) = spender基本上,对于这两个值,始终在槽0x00处使用内存,因此spender覆盖caller()。
第二个错误是将值用作approval_[owner][spender]的时隙:
keccak(keccak(spender) . keccak(owner . approval_.slot))正确的示例如下(请查看医生们中的示例):
keccak(spender . keccak(owner . approval_.slot))把这一切结合起来,简化结构:
mapping(address => mapping(address => uint256)) public approval_;
function approve(address spender, uint256 amount) external returns (bool) {
assembly {
// compute keccak(owner . approval_.slot)
mstore(0x00, caller())
mstore(0x20, approval_.slot)
let googHash := keccak256(0x00, 0x40) // hash msg.sender + approval slot
// compute keccak(spender . googHash) -> this is the final slot
// we can reuse the same memory
mstore(0x00, spender)
mstore(0x20, googHash)
let approveSlot := keccak256(0x00, 0x40)
// load approve balance
let balanceApproved := sload(approveSlot)
// store the new value
sstore(approveSlot, add(balanceApproved, amount))
}
return true;
}https://ethereum.stackexchange.com/questions/134326
复制相似问题