Skip to content

Instantly share code, notes, and snippets.

@Amxx
Last active August 9, 2023 08:08
Show Gist options
  • Save Amxx/90e760a4bc98fea87b5b78903b7d584c to your computer and use it in GitHub Desktop.
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=
// 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