@@ -280,8 +280,12 @@ contract DN404Mirror {
280280
281281 /// @dev Equivalent to `safeTransferFrom(from, to, id, "")`.
282282 function safeTransferFrom (address from , address to , uint256 id ) public payable virtual {
283- transferFrom (from, to, id);
284- if (_hasCode (to)) _checkOnERC721Received (from, to, id, "" );
283+ bytes calldata emptyData;
284+ /// @solidity memory-safe-assembly
285+ assembly {
286+ emptyData.length := 0
287+ }
288+ safeTransferFrom (from, to, id, emptyData);
285289 }
286290
287291 /// @dev Transfers token `id` from `from` to `to`.
@@ -302,7 +306,34 @@ contract DN404Mirror {
302306 virtual
303307 {
304308 transferFrom (from, to, id);
305- if (_hasCode (to)) _checkOnERC721Received (from, to, id, data);
309+ /// @solidity memory-safe-assembly
310+ assembly {
311+ if extcodesize (to) {
312+ // Prepare the calldata.
313+ let m := mload (0x40 )
314+ let onERC721ReceivedSelector := 0x150b7a02
315+ mstore (m, onERC721ReceivedSelector)
316+ mstore (add (m, 0x20 ), caller ()) // The `operator`, which is always `msg.sender`.
317+ mstore (add (m, 0x40 ), shr (96 , shl (96 , from)))
318+ mstore (add (m, 0x60 ), id)
319+ mstore (add (m, 0x80 ), 0x80 )
320+ mstore (add (m, 0xa0 ), data.length )
321+ calldatacopy (add (m, 0xc0 ), data.offset, data.length )
322+ // Revert if the call reverts.
323+ if iszero (call (gas (), to, 0 , add (m, 0x1c ), add (data.length , 0xa4 ), m, 0x20 )) {
324+ if returndatasize () {
325+ // Bubble up the revert if the call reverts.
326+ returndatacopy (m, 0x00 , returndatasize ())
327+ revert (m, returndatasize ())
328+ }
329+ }
330+ // Load the returndata and compare it.
331+ if iszero (eq (mload (m), shl (224 , onERC721ReceivedSelector))) {
332+ mstore (0x00 , 0xd1a57ed6 ) // `TransferToNonERC721ReceiverImplementer()`.
333+ revert (0x1c , 0x04 )
334+ }
335+ }
336+ }
306337 }
307338
308339 /// @dev Returns true if this contract implements the interface defined by `interfaceId`.
@@ -498,14 +529,6 @@ contract DN404Mirror {
498529 }
499530 }
500531
501- /// @dev Returns if `a` has bytecode of non-zero length.
502- function _hasCode (address a ) private view returns (bool result ) {
503- /// @solidity memory-safe-assembly
504- assembly {
505- result := extcodesize (a) // Can handle dirty upper bits.
506- }
507- }
508-
509532 /// @dev More bytecode-efficient way to revert.
510533 function _rv (uint32 s ) private pure {
511534 /// @solidity memory-safe-assembly
@@ -514,46 +537,4 @@ contract DN404Mirror {
514537 revert (0x1c , 0x04 )
515538 }
516539 }
517-
518- /// @dev Perform a call to invoke {IERC721Receiver-onERC721Received} on `to`.
519- /// Reverts if the target does not support the function correctly.
520- function _checkOnERC721Received (address from , address to , uint256 id , bytes memory data )
521- private
522- {
523- /// @solidity memory-safe-assembly
524- assembly {
525- // Prepare the calldata.
526- let m := mload (0x40 )
527- let onERC721ReceivedSelector := 0x150b7a02
528- mstore (m, onERC721ReceivedSelector)
529- mstore (add (m, 0x20 ), caller ()) // The `operator`, which is always `msg.sender`.
530- mstore (add (m, 0x40 ), shr (96 , shl (96 , from)))
531- mstore (add (m, 0x60 ), id)
532- mstore (add (m, 0x80 ), 0x80 )
533- let n := mload (data)
534- mstore (add (m, 0xa0 ), n)
535- if n {
536- let dst := add (m, 0xc0 )
537- let end := add (dst, n)
538- for { let d := sub (add (data, 0x20 ), dst) } 1 {} {
539- mstore (dst, mload (add (dst, d)))
540- dst := add (dst, 0x20 )
541- if iszero (lt (dst, end)) { break }
542- }
543- }
544- // Revert if the call reverts.
545- if iszero (call (gas (), to, 0 , add (m, 0x1c ), add (n, 0xa4 ), m, 0x20 )) {
546- if returndatasize () {
547- // Bubble up the revert if the call reverts.
548- returndatacopy (m, 0x00 , returndatasize ())
549- revert (m, returndatasize ())
550- }
551- }
552- // Load the returndata and compare it.
553- if iszero (eq (mload (m), shl (224 , onERC721ReceivedSelector))) {
554- mstore (0x00 , 0xd1a57ed6 ) // `TransferToNonERC721ReceiverImplementer()`.
555- revert (0x1c , 0x04 )
556- }
557- }
558- }
559540}
0 commit comments