/* Crafted with love by Fueled on Bacon https://fueledonbacon.com */ //SPDX-License-Identifier: MIT pragma solidity ^0.8.15; import '@openzeppelin/contracts/access/AccessControl.sol'; import '@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol'; import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import "./ERC721A.sol"; contract NFTWallet is AccessControl, IERC721Receiver { error NFTWalletCannotTransfer(); bytes32 public constant NFT_OWNER = keccak256("NFT_OWNER"); modifier canTransfer { if(!hasRole(DEFAULT_ADMIN_ROLE, _msgSender()) && !hasRole(NFT_OWNER, _msgSender())) revert NFTWalletCannotTransfer(); _; } constructor(address adminRole) { _setupRole(DEFAULT_ADMIN_ROLE, adminRole); } function attachUser(address user) external onlyRole(DEFAULT_ADMIN_ROLE) { _setupRole(NFT_OWNER, user); } function transferOut(address erc721, address receiver, uint256 tokenId) external canTransfer { ERC721A(erc721).transferFrom(address(this), receiver, tokenId); } function withdrawToken(address token) onlyRole(NFT_OWNER) external { ERC20 erc20 = ERC20(token); erc20.transfer(msg.sender, erc20.balanceOf(address(this))); } /// @inheritdoc IERC721Receiver function onERC721Received( address, /** operator */ address, /** from */ uint256, /** tokenId */ bytes calldata /** data */ ) external pure override returns (bytes4) { return bytes4(keccak256('onERC721Received(address,address,uint256,bytes)')); } }