我有一个总合同(合同A),它与另一个合同(合同B)相互作用。合同A具有使用'safeTransferFrom‘将令牌移动到合同B的功能,并且有一些需要语句需要在场,以确保只有某些令牌可以从合同A移动到合同B。
我的问题是--仅仅在合同B的"onERC721Received“函数中,而不是在合同A的传递函数中,包含这些要求语句是否足够安全?这是一个好的做法,是多余的,并包括两个要求的陈述(转移和接收)?
我的理解是,每次从合同A调用“onERC721Received”时,合同B都会调用safeTransferFrom,因此我认为这应该是足够的。只是想知道是否存在一些我不知道onERC721Received可以被绕过的边缘情况,或者这是否被认为是相当安全的。我知道不安全的传输等不会触发它,但这很好-所有有效的传输将通过safeTransferFrom。谢谢。
发布于 2023-01-01 14:12:04
我将在这里使用ERC721的ERC721实现来解释这个场景。
function _checkOnERC721Received(
address from,
address to,
uint256 tokenId,
bytes memory data
) private returns (bool) {
if (to.isContract()) {
try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, data) returns (bytes4 retval) {
return retval == IERC721Receiver.onERC721Received.selector;
} catch (bytes memory reason) {
if (reason.length == 0) {
revert("ERC721: transfer to non ERC721Receiver implementer");
} else {
/// @solidity memory-safe-assembly
assembly {
revert(add(32, reason), mload(reason))
}
}
}
} else {
return true;
}
}当调用合同A执行ERC721时,将执行在合同B中实现的onERC721Received函数。
在合同A中为选定的令牌is提供必需的语句不是一种好做法,而且
function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data) public override returns (bytes4) {
require(tokenId==1, "Unauthorized TokenId");
return this.onERC721Received.selector;
}如果造币和传输选项仅适用于您确信是安全的特定已知地址,则可以避免使用_safeTransfer和_safeMint,并使用_transfer和_mint函数。
发布于 2023-01-01 18:22:15
通常认为,在执行传输的函数中以及在onERC721Received函数中包含一个require语句是很好的做法。这是因为只有在传输成功的情况下才能调用onERC721Received函数,因此,如果require语句仅包含在onERC721Received函数中,而传递函数没有require语句,攻击者可能会通过进行不安全的传输来绕过需求。
还应该包括对safeTransferFrom函数返回值的检查,以确保传输成功。如果转移不成功,它可以表明转移函数中的require语句没有得到满足,转移也不应该进行。
一般来说,这样的检查是个好主意,这样的检查可以帮助确保合同的安全性。
https://ethereum.stackexchange.com/questions/142132
复制相似问题