Last active
August 9, 2023 08:08
-
-
Save Amxx/90e760a4bc98fea87b5b78903b7d584c to your computer and use it in GitHub Desktop.
Created using remix-ide: Realtime Ethereum Contract Compiler and Runtime. Load this file by pasting this gists URL or ID at https://remix.ethereum.org/#version=soljson-v0.8.7+commit.e28d00a7.js&optimize=false&runs=200&gist=
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// SPDX-License-Identifier: MIT | |
pragma solidity ^0.8.0; | |
import "@openzeppelin/contracts/interfaces/IERC20.sol"; | |
import "@openzeppelin/contracts/interfaces/IERC721.sol"; | |
import "@openzeppelin/contracts/interfaces/IERC721Receiver.sol"; | |
import "@openzeppelin/contracts/interfaces/IERC1155.sol"; | |
import "@openzeppelin/contracts/interfaces/IERC1155Receiver.sol"; | |
import "@openzeppelin/contracts/token/ERC1155/ERC1155.sol"; | |
import "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol"; | |
contract UniversalWrapper is | |
ERC1155(''), | |
IERC721Receiver, | |
IERC1155Receiver | |
{ | |
function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC1155) returns (bool) { | |
return interfaceId == type(IERC721Receiver).interfaceId | |
|| interfaceId == type(IERC1155Receiver).interfaceId | |
|| super.supportsInterface(interfaceId); | |
} | |
/** | |
* ERC20 | |
*/ | |
function wrapERC20(IERC20 instance, uint256 amount, address to) | |
public | |
{ | |
wrapERC20(instance, amount, to, bytes("")); | |
} | |
function wrapERC20(IERC20 instance, uint256 amount, address to, bytes memory data) | |
public | |
{ | |
// check that we are not trying to hide an ERC721 transfer and get multiple wrapped instances. | |
require(!ERC165Checker.supportsInterface(address(instance), type(IERC721).interfaceId)); | |
instance.transferFrom(msg.sender, address(this), amount); | |
_mint(to, getTokenId(address(instance), 0), amount, data); | |
} | |
function unwrapERC20(IERC20 instance, uint256 amount, address from, address to) | |
public | |
{ | |
require(from == msg.sender || isApprovedForAll(from, msg.sender)); | |
_burn(from, getTokenId(address(instance), 0), amount); | |
instance.transfer(to, amount); | |
} | |
/** | |
* ERC721 | |
*/ | |
function onERC721Received(address /* operator */, address /* from */, uint256 tokenId, bytes calldata data) | |
public | |
override | |
returns (bytes4) | |
{ | |
(address to, bytes memory mintData) = abi.decode(data, (address, bytes)); | |
_mint(to, getTokenId(msg.sender, tokenId), 1, mintData); | |
return IERC721Receiver.onERC721Received.selector; | |
} | |
function unwrapERC721(IERC721 instance, uint256 tokenId, address from, address to) | |
public | |
{ | |
unwrapERC721(instance, tokenId, from, to, bytes("")); | |
} | |
function unwrapERC721(IERC721 instance, uint256 tokenId, address from, address to, bytes memory data) | |
public | |
{ | |
require(from == msg.sender || isApprovedForAll(from, msg.sender)); | |
_burn(from, getTokenId(address(instance), tokenId), 1); | |
instance.safeTransferFrom(address(this), to, tokenId, data); | |
} | |
/** | |
* ERC1155 | |
*/ | |
function onERC1155Received(address /* operator */, address /* from */, uint256 tokenId, uint256 value, bytes calldata data) | |
public | |
override | |
returns (bytes4) | |
{ | |
(address to, bytes memory mintData) = abi.decode(data, (address, bytes)); | |
_mint(to, getTokenId(msg.sender, tokenId), value, mintData); | |
return IERC1155Receiver.onERC1155Received.selector; | |
} | |
function onERC1155BatchReceived(address /* operator */, address /* from */, uint256[] calldata tokenIds, uint256[] calldata values, bytes calldata data) | |
public | |
override | |
returns (bytes4) | |
{ | |
(address to, bytes memory mintData) = abi.decode(data, (address, bytes)); | |
uint256[] memory ids = new uint256[](tokenIds.length); | |
for (uint256 i = 0; i < tokenIds.length; ++i) { | |
ids[i] = getTokenId(msg.sender, tokenIds[i]); | |
} | |
_mintBatch(to, ids, values, mintData); | |
return IERC1155Receiver.onERC1155Received.selector; | |
} | |
function unwrapERC1155(IERC1155 instance, uint256 tokenId, uint256 amount, address from, address to) | |
public | |
{ | |
unwrapERC1155(instance, tokenId, amount, from, to, bytes("")); | |
} | |
function unwrapERC1155(IERC1155 instance, uint256 tokenId, uint256 amount, address from, address to, bytes memory data) | |
public | |
{ | |
require(from == msg.sender || isApprovedForAll(from, msg.sender)); | |
_burn(from, getTokenId(address(instance), tokenId), amount); | |
instance.safeTransferFrom(address(this), to, tokenId, amount, data); | |
} | |
function unwrapERC1155Batch(IERC1155 instance, uint256[] memory tokenIds, uint256[] memory amounts, address from, address to) | |
public | |
{ | |
unwrapERC1155Batch(instance, tokenIds, amounts, from, to, bytes("")); | |
} | |
function unwrapERC1155Batch(IERC1155 instance, uint256[] memory tokenIds, uint256[] memory amounts, address from, address to, bytes memory data) | |
public | |
{ | |
require(from == msg.sender || isApprovedForAll(from, msg.sender)); | |
uint256[] memory ids = new uint256[](tokenIds.length); | |
for (uint256 i = 0; i < tokenIds.length; ++i) { | |
ids[i] = getTokenId(address(instance), tokenIds[i]); | |
} | |
_burnBatch(from, ids, amounts); | |
instance.safeBatchTransferFrom(address(this), to, ids, amounts, data); | |
} | |
/** | |
* Utils | |
*/ | |
function getTokenId(address instance, uint256 tokenId) public pure returns (uint256) { | |
return uint256(keccak256(abi.encode(instance, tokenId))); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment