pragma solidity ^0.5.0; import "./ERC1155.sol"; import "./ICurio.sol"; import "./SafeMath.sol"; import "./Address.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; /** @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, msg.sender, 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, msg.sender, address(0), _ids, _quantities); } }