Skip to content
This repository has been archived by the owner on Sep 15, 2022. It is now read-only.

Commit

Permalink
Rename to OpenSea creatures
Browse files Browse the repository at this point in the history
  • Loading branch information
dfinzer committed Nov 6, 2018
1 parent e8ca74d commit e2d0180
Show file tree
Hide file tree
Showing 12 changed files with 192 additions and 133 deletions.
1 change: 1 addition & 0 deletions .gitignore
@@ -1,3 +1,4 @@
build/
flattened/
node_modules/
.env
4 changes: 2 additions & 2 deletions README.md
@@ -1,6 +1,6 @@
## CryptoPuffs ERC721 contracts
## OpenSeaCreatures ERC721 contracts

### About CryptoPuffs.
### About OpenSeaCreatures.

This is a very simple sample ERC721 for the purposes of demonstrating integration with the [OpenSea](https://opensea.io) marketplace. We include a script for minting the items.

Expand Down
16 changes: 16 additions & 0 deletions contracts/Creature.sol
@@ -0,0 +1,16 @@
pragma solidity ^0.4.24;

import "./TradeableERC721Token.sol";
import "openzeppelin-solidity/contracts/ownership/Ownable.sol";

/**
* @title Creature
* Creature - a contract for my non-fungible creatures.
*/
contract Creature is TradeableERC721Token {
constructor(address _proxyRegistryAddress) TradeableERC721Token("Creature", "OSC", _proxyRegistryAddress) public { }

function baseTokenURI() public view returns (string) {
return "https://opensea-creatures-api.herokuapp.com/api/creature/";
}
}
132 changes: 132 additions & 0 deletions contracts/CreatureFactory.sol
@@ -0,0 +1,132 @@
pragma solidity ^0.4.24;

import "openzeppelin-solidity/contracts/ownership/Ownable.sol";
import "./Factory.sol";
import "./Creature.sol";
import "./CreatureLootBox.sol";
import "./Strings.sol";

contract CreatureFactory is Factory, Ownable {
using Strings for string;

address public proxyRegistryAddress;
address public nftAddress;
address public lootBoxNftAddress;
string public baseURI = "https://opensea-creature-api.herokuapp.com/api/factory/";

/**
* Enforce the existence of only 100 OpenSea creatures.
*/
uint256 PUFF_SUPPLY = 100;

/**
* Three different options for minting Creatures (basic, premium, and gold).
*/
uint256 NUM_OPTIONS = 3;
uint256 SINGLE_PUFF_OPTION = 0;
uint256 MULTIPLE_PUFF_OPTION = 1;
uint256 LOOTBOX_OPTION = 2;
uint256 NUM_PUFFS_IN_MULTIPLE_PUFF_OPTION = 4;

constructor(address _proxyRegistryAddress, address _nftAddress) public {
proxyRegistryAddress = _proxyRegistryAddress;
nftAddress = _nftAddress;
lootBoxNftAddress = new CreatureLootBox(_proxyRegistryAddress, this);
}

function name() external view returns (string) {
return "OpenSeaCreature Item Sale";
}

function symbol() external view returns (string) {
return "CPF";
}

function supportsFactoryInterface() public view returns (bool) {
return true;
}

function numOptions() public view returns (uint256) {
return NUM_OPTIONS;
}

function mint(uint256 _optionId, address _toAddress) public {
require(msg.sender == owner || msg.sender == lootBoxNftAddress);

// Must be sent from the owner proxy or owner.
ProxyRegistry proxyRegistry = ProxyRegistry(proxyRegistryAddress);
assert(proxyRegistry.proxies(owner) == msg.sender || owner == msg.sender);
require(canMint(_optionId));

Creature openSeaCreature = Creature(nftAddress);
if (_optionId == SINGLE_PUFF_OPTION) {
openSeaCreature.mintTo(_toAddress);
} else if (_optionId == MULTIPLE_PUFF_OPTION) {
for (uint256 i = 0; i < NUM_PUFFS_IN_MULTIPLE_PUFF_OPTION; i++) {
openSeaCreature.mintTo(_toAddress);
}
} else if (_optionId == LOOTBOX_OPTION) {
CreatureLootBox openSeaCreatureLootBox = CreatureLootBox(lootBoxNftAddress);
openSeaCreatureLootBox.mintTo(_toAddress);
}
}

function canMint(uint256 _optionId) public view returns (bool) {
if (_optionId >= NUM_OPTIONS) {
return false;
}

Creature openSeaCreature = Creature(nftAddress);
uint256 puffSupply = openSeaCreature.totalSupply();

uint256 numItemsAllocated = 0;
if (_optionId == SINGLE_PUFF_OPTION) {
numItemsAllocated = 1;
} else if (_optionId == MULTIPLE_PUFF_OPTION) {
numItemsAllocated = NUM_PUFFS_IN_MULTIPLE_PUFF_OPTION;
} else if (_optionId == LOOTBOX_OPTION) {
CreatureLootBox openSeaCreatureLootBox = CreatureLootBox(lootBoxNftAddress);
numItemsAllocated = openSeaCreatureLootBox.itemsPerLootbox();
}
return puffSupply < (PUFF_SUPPLY - numItemsAllocated);
}

function tokenURI(uint256 _optionId) public view returns (string) {
return Strings.strConcat(
baseURI,
Strings.uint2str(_optionId)
);
}

/**
* Hack to get things to work automatically on OpenSea.
* Use transferFrom so the frontend doesn't have to worry about different method names.
*/
function transferFrom(address _from, address _to, uint256 _tokenId) public {
mint(_tokenId, _to);
}

/**
* Hack to get things to work automatically on OpenSea.
* Use isApprovedForAll so the frontend doesn't have to worry about different method names.
*/
function isApprovedForAll(
address _owner,
address _operator
)
public
view
returns (bool)
{
if (owner == _owner && _owner == _operator) {
return true;
}

ProxyRegistry proxyRegistry = ProxyRegistry(proxyRegistryAddress);
if (owner == _owner && proxyRegistry.proxies(_owner) == _operator) {
return true;
}

return false;
}
}
22 changes: 13 additions & 9 deletions contracts/CryptoPuffLootBox.sol → contracts/CreatureLootBox.sol
@@ -1,29 +1,29 @@
pragma solidity ^0.4.21;

import "./TradeableERC721Token.sol";
import "./CryptoPuff.sol";
import "./Creature.sol";
import "./Factory.sol";
import 'openzeppelin-solidity/contracts/ownership/Ownable.sol';
import "openzeppelin-solidity/contracts/ownership/Ownable.sol";

/**
* @title CryptoPuffLootBox
* @title CreatureLootBox
*
* CryptoPuffLootBox - a tradeable loot box of CryptoPuffs.
* CreatureLootBox - a tradeable loot box of Creatures.
*/
contract CryptoPuffLootBox is TradeableERC721Token {
uint256 NUM_PUFFS_PER_BOX = 3;
contract CreatureLootBox is TradeableERC721Token {
uint256 NUM_CREATURES_PER_BOX = 3;
uint256 OPTION_ID = 0;
address factoryAddress;

constructor(address _proxyRegistryAddress, address _factoryAddress) TradeableERC721Token("CryptoPuffLootBox", "PUFFBOX", _proxyRegistryAddress) public {
constructor(address _proxyRegistryAddress, address _factoryAddress) TradeableERC721Token("CreatureLootBox", "PUFFBOX", _proxyRegistryAddress) public {
factoryAddress = _factoryAddress;
}

function unpack(uint256 _tokenId) public {
require(ownerOf(_tokenId) == msg.sender);

// Insert custom logic for configuring the item here.
for (uint256 i = 0; i < NUM_PUFFS_PER_BOX; i++) {
for (uint256 i = 0; i < NUM_CREATURES_PER_BOX; i++) {
// Mint the ERC721 item(s).
Factory factory = Factory(factoryAddress);
factory.mint(OPTION_ID, msg.sender);
Expand All @@ -34,6 +34,10 @@ contract CryptoPuffLootBox is TradeableERC721Token {
}

function baseTokenURI() public view returns (string) {
return "https://cryptopuffs-api.herokuapp.com/api/box/";
return "https://opensea-creature-api.herokuapp.com/api/box/";
}

function itemsPerLootbox() public view returns (uint256) {
return NUM_CREATURES_PER_BOX;
}
}
16 changes: 0 additions & 16 deletions contracts/CryptoPuff.sol

This file was deleted.

89 changes: 0 additions & 89 deletions contracts/CryptoPuffFactory.sol

This file was deleted.

12 changes: 10 additions & 2 deletions contracts/Factory.sol
@@ -1,13 +1,21 @@
pragma solidity ^0.4.24;

import 'openzeppelin-solidity/contracts/ownership/Ownable.sol';

/**
* This is a generic factory contract that can be used to mint tokens. The configuration
* for minting is specified by an _optionId, which can be used to delineate various
* ways of minting.
*/
interface Factory {
/**
* Returns the name of this factory.
*/
function name() external view returns (string);

/**
* Returns the symbol for this factory.
*/
function symbol() external view returns (string);

/**
* Number of options the factory supports.
*/
Expand Down
3 changes: 3 additions & 0 deletions flatten.sh
@@ -0,0 +1,3 @@
./node_modules/.bin/truffle-flattener contracts/Creature.sol > flattened/Creature.sol
./node_modules/.bin/truffle-flattener contracts/CreatureFactory.sol > flattened/CreatureFactory.sol
./node_modules/.bin/truffle-flattener contracts/CreatureLootBox.sol > flattened/CreatureLootBox.sol
8 changes: 4 additions & 4 deletions metadata-api/app.py
Expand Up @@ -68,8 +68,8 @@ def box(token_id):
_add_attribute(attributes, 'number_inside', [3], token_id)

return jsonify({
'name': "CryptoPuff Loot Box",
'description': "This lootbox contains some cryptopuffs! It can also be traded!",
'name': "Creature Loot Box",
'description': "This lootbox contains some OpenSea Creatures! It can also be traded!",
'imageUrl': image_url,
'externalUrl': 'https://cryptopuff.io/%s' % token_id,
'attributes': attributes
Expand All @@ -85,8 +85,8 @@ def factory(token_id):
_add_attribute(attributes, 'number_inside', [1], token_id)

return jsonify({
'name': "CryptoPuff Sale",
'description': "Buy a magical CryptoPuff of random variety!",
'name': "Creature Sale",
'description': "Buy a magical Creature of random variety!",
'imageUrl': image_url,
'externalUrl': 'https://cryptopuff.io/%s' % token_id,
'attributes': attributes
Expand Down

0 comments on commit e2d0180

Please sign in to comment.