curio-wrapper-truffle/contracts/CurioERC1155Wrapper.sol

208 lines
9.5 KiB
Solidity

pragma solidity ^0.5.0;
import "./ERC1155.sol";
import "./ICurio.sol";
import "./SafeMath.sol";
import "./Address.sol";
import "./OpenSeaProxy.sol";
import "./IERC1155Metadata.sol";
contract CurioERC1155Wrapper is ERC1155, ERC1155Metadata_URI {
using SafeMath for uint256;
using Address for address;
// nft id => curio contract address
mapping (uint256 => address) public contracts;
// nft id => nft metadata IPFS URI
mapping (uint256 => string) public metadatas;
// OpenSea contract with an operator => proxy lister contract address
address public proxyRegistryAddress;
/**
@notice Initialize an nft id's data.
*/
function create(uint256 _id, address _contract, string memory _uri) internal {
require(contracts[_id] == address(0), "id already exists");
contracts[_id] = _contract;
// mint 0 just to let explorers know it exists
emit TransferSingle(msg.sender, address(0), msg.sender, _id, 0);
metadatas[_id] = _uri;
emit URI(_uri, _id);
}
constructor() public {
proxyRegistryAddress = 0xa5409ec958C83C3f309868babACA7c86DCB077c1;
create(1, 0x6Aa2044C7A0f9e2758EdAE97247B03a0D7e73d6c, "ipfs://QmWHUnrdfA4w89TeepZqrvygbaF9wV48k97Wf27skL5cry");
create(2, 0xE9A6A26598B05dB855483fF5eCc5f1d0C81140c8, "ipfs://QmVJn6B289Xt3cq9evzubdyk4f1usPAu277SmUusmdYYWU");
create(3, 0x3f8131B6E62472CEea9cb8Aa67d87425248a3702, "ipfs://QmWBb6T4nviPWdAyqGJTki7VA6fpTmcYP37U9jpYAfhzPP");
create(4, 0x4F1694be039e447B729ab11653304232Ae143C69, "ipfs://Qmbcw8ix8xdK1reFpDEjKtk9EWuRwrbMKqvEvWkttNzXkH");
create(5, 0x5a3D4A8575a688b53E8b270b5C1f26fd63065219, "ipfs://QmXmj9YdsvBVddzC352Xsh7bmyJtfZvbVJeetK7PXW21p8");
create(6, 0x1Ca6AC0Ce771094F0F8a383D46BF3acC9a5BF27f, "ipfs://Qmdf16YMPM7zG5QkSYB4HjbxQPaStYazsL6d1npdJG8J7h");
create(7, 0x2647bd8777e0C66819D74aB3479372eA690912c3, "ipfs://QmUGmWwrNR7JKBCSu3CkGnTYSFat7y2AiUzACcbAoZcj2d");
create(8, 0x2FCE2713a561bB019BC5A110BE0A19d10581ee9e, "ipfs://QmXQfBgJRsUQbf8UkViATdpsySXzREsifegWzLvw5QsQPj");
create(9, 0xbf4Cc966F1e726087c5C55aac374E687000d4d45, "ipfs://Qmctv89ppbYTuwCWVFA9waVCeE8g6YM3Ah54bZW1WGmEHh");
create(10, 0x72b34d637C0d14acE58359Ef1bF472E4b4c57125, "ipfs://QmaSBVrCcBsYHjVuvTsj6ev4Pua7NYX7sDNzdAYwCdAAne");
create(11, 0xb36c87F1f1539c5FC6f6e7b1C632e1840C9B66b4, "ipfs://QmZjSs71uBYYdLx5Ju443KiSYjxQcJQLL5ZnhuzWX6nC19");
create(12, 0xD15af10A258432e7227367499E785C3532b50271, "ipfs://QmQqMKDMKiRhgbFBrmAJPknzYHEKuH7VrqPZ7NS5vFoy78");
create(13, 0x2d922712f5e99428c65b44f09Ea389373d185bB3, "ipfs://QmeShnRPe6uiRcBy81nQXDZ9TWUpFNQfiAThf9ruAQGcRa");
create(14, 0x0565ac44e5119a3224b897De761a46A92aA28ae8, "ipfs://Qmdi8vQuQQWksiM5HCCVXfzSzcaemzQwYkUe4Tb94DP6vK");
create(15, 0xdb7F262237Ad8acca8922aA2c693a34D0d13e8fe, "ipfs://QmS3UF256kWHbX8Wi7CYExyCxzLNX1nsaMwpaGBN73rr31");
create(16, 0x1b63532CcB1FeE0595c7fe2Cb35cFD70ddF862Cd, "ipfs://Qmbj1YCmQidTzxgjLmu1b99PPdXZLSgk72YZQSt9LEEe1R");
create(17, 0xF59536290906F204C3c7918D40C1Cc5f99643d0B, "ipfs://QmbDsZABRUPMcuoFWePRH7YiGyR64udWHc4u1mQPJYmB2c");
create(18, 0xA507D9d28bbca54cBCfFad4BB770C2EA0519F4F0, "ipfs://QmXafwRpoJPiiQ9TZihhbSsFmgKqKMqrHSRLkp1wyQ3jUU");
create(19, 0xf26BC97Aa8AFE176e275Cf3b08c363f09De371fA, "ipfs://QmTWJR1XJ2svexE2NT3A6cCtks8rgh6TKYaLYXwfHapNDN");
create(20, 0xD0ec99E99cE22f2487283A087614AEe37F6B1283, "ipfs://Qmd3HzUX52MmZcj1Se3ocgYWEJWSvzSceEqQFV1YL7LRWL");
create(21, 0xB7A5a84Ff90e8Ef91250fB56c50a7bB92a6306EE, "ipfs://QmX6stsihT3SNUakiFQLWU1cjvH7rC3pqtCnToxNn2T8JS");
create(22, 0x148fF761D16632da89F3D30eF3dFE34bc50CA765, "ipfs://Qmc1sj8LRdfbPinoqKMmAe6UvJUG33VMmSU3XzNK2GnjJB");
create(23, 0xCDE7185B5C3Ed9eA68605a960F6653AA1a5b5C6C, "ipfs://Qmdwh3S4imtE5RxZ4ddAzy3DMqNrD11JL6SATTyREuvrtN");
create(24, 0xE67dad99c44547B54367E3e60fc251fC45a145C6, "ipfs://QmbfTxH6XvbgGcyWWaygmPko6NQ6tKuT6dJj5WjnQGp5g8");
create(25, 0xC7f60C2b1DBDfd511685501EDEb05C4194D67018, "ipfs://QmXHyK19F4sMAUi6XYz1BJJYzxsdp8koVnL4BwsFA93Q47");
create(26, 0x1cB5BF4Be53eb141B56f7E4Bb36345a353B5488c, "ipfs://QmYK88qy84rcL46CZGPqpKRm4fE2PQYJ931pV69ZNi4J1D");
create(27, 0xFb9F3fa2502d01d43167A0A6E80bE03171DF407E, "ipfs://QmcUTEkPpmRPHCHiXskd9daQcEZwGzkHgybZmCWmFYha1T");
create(28, 0x59D190e8A2583C67E62eEc8dA5EA7f050d8BF27e, "ipfs://QmTmi8j5BBE5FWhEDAg1bTqpmkkEcaPgTUeYFJ4z3PxXqN");
create(29, 0xD3540bCD9c2819771F9D765Edc189cBD915FEAbd, "ipfs://QmVTGJtgnUgnMPttJV2VkfonCUYLRnJqX66gJLiig5QVgC");
create(30, 0x7F5B230Dc580d1e67DF6eD30dEe82684dD113D1F, "ipfs://QmQBu8jYC3vEGzx59BUW4knBdNRyFd8aTVLLFCEprdjZ5e");
}
/**
@dev override ERC1155 uri function to return IPFS ref.
@param _id NFT ID
@return IPFS URI pointing to NFT ID's metadata.
*/
function uri(uint256 _id) public view returns (string memory) {
return metadatas[_id];
}
/**
@dev helper function to see if NFT ID exists, makes OpenSea happy.
@param _id NFT ID
@return if NFT ID exists.
*/
function exists(uint256 _id) external view returns(bool) {
return contracts[_id] != address(0);
}
/**
@dev for an NFT ID, queries and transfers tokens from the appropriate
curio contract to itself, and mints and transfers corresponding new
ERC-1155 tokens to caller.
*/
function wrap(uint256 _id, uint256 _quantity) external {
address tokenContract = contracts[_id];
require(tokenContract != address(0), "invalid id");
ICurio curio = ICurio(tokenContract);
// these are here for convenience because curio contract doesn't throw meaningful exceptions
require(curio.balanceOf(msg.sender) >= _quantity, "insufficient curio balance");
require(curio.allowance(msg.sender, address(this)) >= _quantity, "insufficient curio allowance");
curio.transferFrom(msg.sender, address(this), _quantity);
balances[_id][msg.sender] = balances[_id][msg.sender].add(_quantity);
// mint
emit TransferSingle(msg.sender, address(0), msg.sender, _id, _quantity);
address _to = msg.sender;
if (_to.isContract()) {
_doSafeTransferAcceptanceCheck(msg.sender, msg.sender, msg.sender, _id, _quantity, '');
}
}
/**
@dev batch version of wrap.
*/
function wrapBatch(uint256[] calldata _ids, uint256[] calldata _quantities) external {
require(_ids.length == _quantities.length, "ids and quantities must match");
address _to = msg.sender;
bool callerIsContract = _to.isContract();
for (uint256 i=0; i < _ids.length; ++i) {
uint256 _id = _ids[i];
uint256 _quantity = _quantities[i];
address tokenContract = contracts[_id];
require(tokenContract != address(0), "invalid id");
ICurio curio = ICurio(tokenContract);
require(curio.balanceOf(msg.sender) >= _quantity, "insufficient curio balance");
require(curio.allowance(msg.sender, address(this)) >= _quantity, "insufficient curio allowance");
curio.transferFrom(msg.sender, address(this), _quantity);
balances[_id][msg.sender] = balances[_id][msg.sender].add(_quantity);
if (callerIsContract) {
_doSafeTransferAcceptanceCheck(msg.sender, msg.sender, msg.sender, _id, _quantity, '');
}
}
// mint
emit TransferBatch(msg.sender, address(0), _to, _ids, _quantities);
}
/**
@dev for an NFT ID, burns ERC-1155 quantity and transfers curio ERC-20
tokens to caller.
*/
function unwrap(uint256 _id, uint256 _quantity) external {
address tokenContract = contracts[_id];
require(tokenContract != address(0), "invalid id");
ICurio curio = ICurio(tokenContract);
require(balances[_id][msg.sender] >= _quantity, "insufficient balance");
balances[_id][msg.sender] = balances[_id][msg.sender].sub(_quantity);
curio.transfer(msg.sender, _quantity);
// burn
emit TransferSingle(msg.sender, address(this), address(0), _id, _quantity);
}
/**
@dev batch version of unwrap.
*/
function unwrapBatch(uint256[] calldata _ids, uint256[] calldata _quantities) external {
require(_ids.length == _quantities.length, "ids and quantities must match");
for (uint256 i=0; i < _ids.length; ++i) {
uint256 _id = _ids[i];
uint256 _quantity = _quantities[i];
address tokenContract = contracts[_id];
require(tokenContract != address(0), "invalid id");
ICurio curio = ICurio(tokenContract);
require(balances[_id][msg.sender] >= _quantity, "insufficient balance");
balances[_id][msg.sender] = balances[_id][msg.sender].sub(_quantity);
curio.transfer(msg.sender, _quantity);
}
// burn
emit TransferBatch(msg.sender, address(this), address(0), _ids, _quantities);
}
/**
@dev override isApprovedForAll to whitelist user's OpenSea proxy
accounts to enable gas-free listings.
*/
function isApprovedForAll(address owner, address operator) public view returns (bool)
{
// Whitelist OpenSea proxy contract for easy trading.
ProxyRegistry proxyRegistry = ProxyRegistry(proxyRegistryAddress);
if (address(proxyRegistry.proxies(owner)) == operator) {
return true;
}
return super.isApprovedForAll(owner, operator);
}
}