38 lines
1.5 KiB
Solidity
38 lines
1.5 KiB
Solidity
|
// SPDX-License-Identifier: CC0-1.0
|
||
|
|
||
|
pragma solidity ^0.8.0;
|
||
|
|
||
|
import "@openzeppelin/contracts/utils/introspection/IERC165.sol";
|
||
|
import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
|
||
|
|
||
|
import "./ERC4671.sol";
|
||
|
import "./IERC4671Pull.sol";
|
||
|
|
||
|
abstract contract ERC4671Pull is ERC4671, IERC4671Pull {
|
||
|
using ECDSA for bytes32;
|
||
|
|
||
|
/// @notice Pull a token from the owner wallet to the caller's wallet
|
||
|
/// @param tokenId Identifier of the token to transfer
|
||
|
/// @param owner Address that owns tokenId
|
||
|
/// @param signature Signed data (tokenId, owner, recipient) by the owner of the token
|
||
|
function pull(uint256 tokenId, address owner, bytes memory signature) public virtual override {
|
||
|
Token storage token = _getTokenOrRevert(tokenId);
|
||
|
require(token.owner == owner, "Provided owner does not own the token");
|
||
|
|
||
|
address recipient = msg.sender;
|
||
|
bytes32 messageHash = keccak256(abi.encodePacked(tokenId, owner, recipient));
|
||
|
bytes32 signedHash = messageHash.toEthSignedMessageHash();
|
||
|
require(signedHash.recover(signature) == owner, "Invalid signature");
|
||
|
|
||
|
bool valid = token.valid;
|
||
|
_removeToken(tokenId);
|
||
|
_mintUnsafe(recipient, tokenId, valid);
|
||
|
}
|
||
|
|
||
|
function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC4671) returns (bool) {
|
||
|
return
|
||
|
interfaceId == type(IERC4671Pull).interfaceId ||
|
||
|
super.supportsInterface(interfaceId);
|
||
|
}
|
||
|
}
|