Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

erc721 mintable and bouncer updates #1020

2 changes: 2 additions & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
node_modules
coverage
2 changes: 2 additions & 0 deletions contracts/crowdsale/emission/AllowanceCrowdsale.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import "../../token/ERC20/ERC20.sol";
import "../../token/ERC20/ERC20Basic.sol";
import "../../token/ERC20/SafeERC20.sol";
import "../../math/SafeMath.sol";


/**
* @title AllowanceCrowdsale
* @dev Extension of Crowdsale where tokens are held by a wallet, which approves an allowance to the crowdsale.
Expand Down
29 changes: 29 additions & 0 deletions contracts/examples/SimpleERC721Token.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
pragma solidity ^0.4.24;

import "../token/ERC721/ERC721Token.sol";
import "../token/ERC721/MintableERC721Token.sol";
import "../token/ERC721/BurnableERC721Token.sol";


contract SimpleERC721Token is ERC721Token, BurnableERC721Token {
constructor(string name, string symbol)
ERC721Token(name, symbol)
public
{
}

// no access control, anyone can mint
function mint(address _to, uint256 _tokenId) public {
_mint(_to, _tokenId);
}

// no access control, anyone can burn
function burn(uint256 _tokenId) public {
_burn(ownerOf(_tokenId), _tokenId);
}

// no access control, anyone can set token URI
function setTokenURI(uint256 _tokenId, string _uri) public {
_setTokenURI(_tokenId, _uri);
}
}
2 changes: 2 additions & 0 deletions contracts/introspection/SupportsInterfaceWithLookup.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import "./ERC165.sol";
* @dev Implements ERC165 using a lookup table.
*/
contract SupportsInterfaceWithLookup is ERC165 {

// solium-disable-next-line uppercase
bytes4 public constant InterfaceId_ERC165 = 0x01ffc9a7;
/**
* 0x01ffc9a7 ===
Expand Down
14 changes: 14 additions & 0 deletions contracts/mocks/BurnableERC721TokenMock.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
pragma solidity ^0.4.24;

import "../token/ERC721/BurnableERC721Token.sol";


/**
* @title BurnableERC721TokenMock
* This mock just provides a public setter for metadata URI
*/
contract BurnableERC721TokenMock is BurnableERC721Token {
function mint(address _to, uint256 _tokenId) public {
super._mint(_to, _tokenId);
}
}
16 changes: 16 additions & 0 deletions contracts/mocks/DefaultTokenURIMock.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
pragma solidity ^0.4.24;

import "../token/ERC721/MintableERC721Token.sol";
import "../token/ERC721/DefaultTokenURI.sol";


contract DefaultTokenURIMock is DefaultTokenURI, MintableERC721Token {

constructor(string _name, string _symbol, string _tokenURI)
ERC721Token(_name, _symbol)
DefaultTokenURI(_tokenURI)
public
{

}
}
12 changes: 7 additions & 5 deletions contracts/mocks/ERC721TokenMock.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,21 @@ import "../token/ERC721/ERC721Token.sol";
* and a public setter for metadata URI
*/
contract ERC721TokenMock is ERC721Token {
constructor(string name, string symbol) public
constructor(string name, string symbol)
ERC721Token(name, symbol)
{ }
public
{
}

function mint(address _to, uint256 _tokenId) public {
super._mint(_to, _tokenId);
_mint(_to, _tokenId);
}

function burn(uint256 _tokenId) public {
super._burn(ownerOf(_tokenId), _tokenId);
_burn(ownerOf(_tokenId), _tokenId);
}

function setTokenURI(uint256 _tokenId, string _uri) public {
super._setTokenURI(_tokenId, _uri);
_setTokenURI(_tokenId, _uri);
}
}
13 changes: 13 additions & 0 deletions contracts/mocks/MintableERC721TokenImpl.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
pragma solidity ^0.4.24;

import "../token/ERC721/ERC721Token.sol";
import "../token/ERC721/MintableERC721Token.sol";


contract MintableERC721TokenImpl is ERC721Token, MintableERC721Token {
constructor(string name, string symbol)
ERC721Token(name, symbol)
public
{
}
}
1 change: 1 addition & 0 deletions contracts/mocks/RBACCappedTokenMock.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ pragma solidity ^0.4.24;
import "../token/ERC20/RBACMintableToken.sol";
import "../token/ERC20/CappedToken.sol";


contract RBACCappedTokenMock is CappedToken, RBACMintableToken {
constructor(
uint256 _cap
Expand Down
1 change: 1 addition & 0 deletions contracts/mocks/WhitelistMock.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ pragma solidity ^0.4.24;

import "../access/Whitelist.sol";


contract WhitelistMock is Whitelist {

function onlyWhitelistedCanDoThis()
Expand Down
19 changes: 19 additions & 0 deletions contracts/ownership/rbac/RBACMintable.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
pragma solidity ^0.4.24;

import "./RBAC.sol";


/**
* @title RBACMintable
* @author Matt Condon (@shrugs)
* @dev Mintable logic using RBAC.
* You must add any logic for addMinter/removeMinter yourself because security concerns will vary.
*/
contract RBACMintable is RBAC {
string public constant ROLE_MINTER = "minter";

modifier onlyMinter() {
checkRole(msg.sender, ROLE_MINTER);
_;
}
}
41 changes: 41 additions & 0 deletions contracts/ownership/rbac/RBACOwnable.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
pragma solidity ^0.4.24;

import "./RBAC.sol";


/**
* @title RBACOwnable
* @author Matt Condon (@shrugs)
* @dev Ownable logic using RBAC.
* @dev Use RBACOwnable if you could have many different owners and you're ok with
* @dev the security profile of any owner being able to add another owner.
* @dev Only difference from Ownable.sol is that the owners are not stored as public variables.
*/
contract RBACOwnable is RBAC {
string public constant ROLE_OWNER = "owner";

constructor()
public
{
addRole(msg.sender, ROLE_OWNER);
}

modifier onlyOwner() {
checkRole(msg.sender, ROLE_OWNER);
_;
}

function addOwner(address _owner)
onlyOwner
public
{
addRole(_owner, ROLE_OWNER);
}

function removeOwner(address _owner)
onlyOwner
public
{
removeRole(_owner, ROLE_OWNER);
}
}
9 changes: 2 additions & 7 deletions contracts/token/ERC20/RBACMintableToken.sol
Original file line number Diff line number Diff line change
@@ -1,20 +1,15 @@
pragma solidity ^0.4.24;

import "./MintableToken.sol";
import "../../ownership/rbac/RBAC.sol";
import "../../ownership/rbac/RBACMintable.sol";


/**
* @title RBACMintableToken
* @author Vittorio Minacori (@vittominacori)
* @dev Mintable Token, with RBAC minter permissions
*/
contract RBACMintableToken is MintableToken, RBAC {
/**
* A constant role name for indicating minters.
*/
string public constant ROLE_MINTER = "minter";

contract RBACMintableToken is MintableToken, RBACMintable {
/**
* @dev override the Mintable token modifier to add role based logic
*/
Expand Down
34 changes: 34 additions & 0 deletions contracts/token/ERC721/BurnableERC721Token.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
pragma solidity ^0.4.24;

import "./ERC721.sol";
import "./ERC721BasicToken.sol";


/**
* @title BurnableERC721Token
* @author Vittorio Minacori (@vittominacori), Matt Condon (@shrugs)
* @dev Burnable ERC721Token; owners and approve operators of a token can burn it.
*/
contract BurnableERC721Token is ERC721Burnable, ERC721BasicToken {

// solium-disable-next-line uppercase
bytes4 private constant InterfaceId_ERC721Burnable = 0x79cc6790;
/*
* 0x79cc6790 ===
* bytes4(keccak256('burnFrom(address,uin256)'))
*/


constructor ()
public
{
_registerInterface(InterfaceId_ERC721Burnable);
}

function burnFrom(address _from, uint256 _tokenId)
canTransfer(_tokenId)
public
{
_burn(_from, _tokenId);
}
}
31 changes: 31 additions & 0 deletions contracts/token/ERC721/DefaultTokenURI.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
pragma solidity ^0.4.24;

import "./ERC721Token.sol";


contract DefaultTokenURI is ERC721Token {
string private tokenURI_ = "";

constructor(string _tokenURI)
public
{
require(bytes(_tokenURI).length > 0);
tokenURI_ = _tokenURI;
}

/**
* @dev Returns a default URI for every tokenId unless a specific URI is set
* @param _tokenId uint256 ID of the token to query
*/
function tokenURI(uint256 _tokenId)
public
view
returns (string)
{
if (bytes(tokenURIs[_tokenId]).length != 0) {
return super.tokenURI(_tokenId);
}

return tokenURI_;
}
}
9 changes: 9 additions & 0 deletions contracts/token/ERC721/ERC721.sol
Original file line number Diff line number Diff line change
Expand Up @@ -38,3 +38,12 @@ contract ERC721Metadata is ERC721Basic {
*/
contract ERC721 is ERC721Basic, ERC721Enumerable, ERC721Metadata {
}


/**
* @title ERC721Burnable
* @dev Provides burnFrom(address,uint256) for burning tokens
*/
contract ERC721Burnable is ERC721Basic {
function burnFrom(address _from, uint256 _tokenId) public;
}
71 changes: 71 additions & 0 deletions contracts/token/ERC721/MintableERC721Token.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
pragma solidity ^0.4.24;

import "../../ownership/rbac/RBACOwnable.sol";
import "../../ownership/rbac/RBACMintable.sol";
import "./ERC721Token.sol";


/**
* @title MintableERC721Token
* @author Matt Condon (@shrugs), Vittorio Minacori (@vittominacori)
* @dev This is an ERC721Token than can be minted by any sender with the role
* ROLE_MINTER. This contract is designed to be used either directly by an Ethereum account
* or with some other access control and input verification like a Bouncer.
*/
contract MintableERC721Token is RBACOwnable, RBACMintable, ERC721Token {

event MintFinished();
bool public mintingFinished = false;

modifier onlyMinterOrOwner() {
require(
hasRole(msg.sender, ROLE_MINTER) ||
hasRole(msg.sender, ROLE_OWNER)
);
_;
}

modifier canMint() {
require(!mintingFinished);
_;
}

function mint(address _to, uint256 _tokenId, string _tokenURI)
canMint
onlyMinter
public
{
_mint(_to, _tokenId);
_setTokenURI(_tokenId, _tokenURI);
}

/**
* @dev add a minter role to an address
* @param minter address
*/
function addMinter(address minter) onlyOwner public {
addRole(minter, ROLE_MINTER);
}

/**
* @dev remove a minter role from an address
* @param minter address
*/
function removeMinter(address minter) onlyOwner public {
removeRole(minter, ROLE_MINTER);
}

/**
* @dev Enforce that no more tokens can be minted, callable by any minter
*/
function finishMinting()
canMint
onlyMinterOrOwner
public
returns (bool)
{
mintingFinished = true;
emit MintFinished();
return true;
}
}
Loading