// File: openzeppelin-solidity/contracts/ownership/Ownable.sol
pragma solidity ^0.4.24;
/**
* @title Ownable
* @dev The Ownable contract has an owner address, and provides basic authorization control
* functions, this simplifies the implementation of "user permissions".
*/
contract Ownable {
address public owner;
event OwnershipRenounced(address indexed previousOwner);
event OwnershipTransferred(
address indexed previousOwner,
address indexed newOwner
);
/**
* @dev The Ownable constructor sets the original `owner` of the contract to the sender
* account.
*/
constructor() public {
owner = msg.sender;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(msg.sender == owner);
_;
}
/**
* @dev Allows the current owner to relinquish control of the contract.
* @notice Renouncing to ownership will leave the contract without an owner.
* It will not be possible to call the functions with the `onlyOwner`
* modifier anymore.
*/
function renounceOwnership() public onlyOwner {
emit OwnershipRenounced(owner);
owner = address(0);
}
/**
* @dev Allows the current owner to transfer control of the contract to a newOwner.
* @param _newOwner The address to transfer ownership to.
*/
function transferOwnership(address _newOwner) public onlyOwner {
_transferOwnership(_newOwner);
}
/**
* @dev Transfers control of the contract to a newOwner.
* @param _newOwner The address to transfer ownership to.
*/
function _transferOwnership(address _newOwner) internal {
require(_newOwner != address(0));
emit OwnershipTransferred(owner, _newOwner);
owner = _newOwner;
}
}
// File: openzeppelin-solidity/contracts/access/rbac/Roles.sol
pragma solidity ^0.4.24;
/**
* @title Roles
* @author Francisco Giordano (@frangio)
* @dev Library for managing addresses assigned to a Role.
* See RBAC.sol for example usage.
*/
library Roles {
struct Role {
mapping (address => bool) bearer;
}
/**
* @dev give an address access to this role
*/
function add(Role storage _role, address _addr)
internal
{
_role.bearer[_addr] = true;
}
/**
* @dev remove an address' access to this role
*/
function remove(Role storage _role, address _addr)
internal
{
_role.bearer[_addr] = false;
}
/**
* @dev check if an address has this role
* // reverts
*/
function check(Role storage _role, address _addr)
internal
view
{
require(has(_role, _addr));
}
/**
* @dev check if an address has this role
* @return bool
*/
function has(Role storage _role, address _addr)
internal
view
returns (bool)
{
return _role.bearer[_addr];
}
}
// File: openzeppelin-solidity/contracts/access/rbac/RBAC.sol
pragma solidity ^0.4.24;
/**
* @title RBAC (Role-Based Access Control)
* @author Matt Condon (@Shrugs)
* @dev Stores and provides setters and getters for roles and addresses.
* Supports unlimited numbers of roles and addresses.
* See //contracts/mocks/RBACMock.sol for an example of usage.
* This RBAC method uses strings to key roles. It may be beneficial
* for you to write your own implementation of this interface using Enums or similar.
*/
contract RBAC {
using Roles for Roles.Role;
mapping (string => Roles.Role) private roles;
event RoleAdded(address indexed operator, string role);
event RoleRemoved(address indexed operator, string role);
/**
* @dev reverts if addr does not have role
* @param _operator address
* @param _role the name of the role
* // reverts
*/
function checkRole(address _operator, string _role)
public
view
{
roles[_role].check(_operator);
}
/**
* @dev determine if addr has role
* @param _operator address
* @param _role the name of the role
* @return bool
*/
function hasRole(address _operator, string _role)
public
view
returns (bool)
{
return roles[_role].has(_operator);
}
/**
* @dev add a role to an address
* @param _operator address
* @param _role the name of the role
*/
function addRole(address _operator, string _role)
internal
{
roles[_role].add(_operator);
emit RoleAdded(_operator, _role);
}
/**
* @dev remove a role from an address
* @param _operator address
* @param _role the name of the role
*/
function removeRole(address _operator, string _role)
internal
{
roles[_role].remove(_operator);
emit RoleRemoved(_operator, _role);
}
/**
* @dev modifier to scope access to a single role (uses msg.sender as addr)
* @param _role the name of the role
* // reverts
*/
modifier onlyRole(string _role)
{
checkRole(msg.sender, _role);
_;
}
/**
* @dev modifier to scope access to a set of roles (uses msg.sender as addr)
* @param _roles the names of the roles to scope access to
* // reverts
*
* @TODO - when solidity supports dynamic arrays as arguments to modifiers, provide this
* see: https://github.com/ethereum/solidity/issues/2467
*/
// modifier onlyRoles(string[] _roles) {
// bool hasAnyRole = false;
// for (uint8 i = 0; i < _roles.length; i++) {
// if (hasRole(msg.sender, _roles[i])) {
// hasAnyRole = true;
// break;
// }
// }
// require(hasAnyRole);
// _;
// }
}
// File: openzeppelin-solidity/contracts/access/Whitelist.sol
pragma solidity ^0.4.24;
/**
* @title Whitelist
* @dev The Whitelist contract has a whitelist of addresses, and provides basic authorization control functions.
* This simplifies the implementation of "user permissions".
*/
contract Whitelist is Ownable, RBAC {
string public constant ROLE_WHITELISTED = "whitelist";
/**
* @dev Throws if operator is not whitelisted.
* @param _operator address
*/
modifier onlyIfWhitelisted(address _operator) {
checkRole(_operator, ROLE_WHITELISTED);
_;
}
/**
* @dev add an address to the whitelist
* @param _operator address
* @return true if the address was added to the whitelist, false if the address was already in the whitelist
*/
function addAddressToWhitelist(address _operator)
public
onlyOwner
{
addRole(_operator, ROLE_WHITELISTED);
}
/**
* @dev getter to determine if address is in whitelist
*/
function whitelist(address _operator)
public
view
returns (bool)
{
return hasRole(_operator, ROLE_WHITELISTED);
}
/**
* @dev add addresses to the whitelist
* @param _operators addresses
* @return true if at least one address was added to the whitelist,
* false if all addresses were already in the whitelist
*/
function addAddressesToWhitelist(address[] _operators)
public
onlyOwner
{
for (uint256 i = 0; i < _operators.length; i++) {
addAddressToWhitelist(_operators[i]);
}
}
/**
* @dev remove an address from the whitelist
* @param _operator address
* @return true if the address was removed from the whitelist,
* false if the address wasn't in the whitelist in the first place
*/
function removeAddressFromWhitelist(address _operator)
public
onlyOwner
{
removeRole(_operator, ROLE_WHITELISTED);
}
/**
* @dev remove addresses from the whitelist
* @param _operators addresses
* @return true if at least one address was removed from the whitelist,
* false if all addresses weren't in the whitelist in the first place
*/
function removeAddressesFromWhitelist(address[] _operators)
public
onlyOwner
{
for (uint256 i = 0; i < _operators.length; i++) {
removeAddressFromWhitelist(_operators[i]);
}
}
}
// File: openzeppelin-solidity/contracts/lifecycle/Pausable.sol
pragma solidity ^0.4.24;
/**
* @title Pausable
* @dev Base contract which allows children to implement an emergency stop mechanism.
*/
contract Pausable is Ownable {
event Pause();
event Unpause();
bool public paused = false;
/**
* @dev Modifier to make a function callable only when the contract is not paused.
*/
modifier whenNotPaused() {
require(!paused);
_;
}
/**
* @dev Modifier to make a function callable only when the contract is paused.
*/
modifier whenPaused() {
require(paused);
_;
}
/**
* @dev called by the owner to pause, triggers stopped state
*/
function pause() public onlyOwner whenNotPaused {
paused = true;
emit Pause();
}
/**
* @dev called by the owner to unpause, returns to normal state
*/
function unpause() public onlyOwner whenPaused {
paused = false;
emit Unpause();
}
}
// File: openzeppelin-solidity/contracts/math/SafeMath.sol
pragma solidity ^0.4.24;
/**
* @title SafeMath
* @dev Math operations with safety checks that throw on error
*/
library SafeMath {
/**
* @dev Multiplies two numbers, throws on overflow.
*/
function mul(uint256 _a, uint256 _b) internal pure returns (uint256 c) {
// Gas optimization: this is cheaper than asserting 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
if (_a == 0) {
return 0;
}
c = _a * _b;
assert(c / _a == _b);
return c;
}
/**
* @dev Integer division of two numbers, truncating the quotient.
*/
function div(uint256 _a, uint256 _b) internal pure returns (uint256) {
// assert(_b > 0); // Solidity automatically throws when dividing by 0
// uint256 c = _a / _b;
// assert(_a == _b * c + _a % _b); // There is no case in which this doesn't hold
return _a / _b;
}
/**
* @dev Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend).
*/
function sub(uint256 _a, uint256 _b) internal pure returns (uint256) {
assert(_b <= _a);
return _a - _b;
}
/**
* @dev Adds two numbers, throws on overflow.
*/
function add(uint256 _a, uint256 _b) internal pure returns (uint256 c) {
c = _a + _b;
assert(c >= _a);
return c;
}
}
// File: contracts/v2/interfaces/IKODAV2SelfServiceEditionCuration.sol
pragma solidity 0.4.24;
interface IKODAV2SelfServiceEditionCuration {
function createActiveEdition(
uint256 _editionNumber,
bytes32 _editionData,
uint256 _editionType,
uint256 _startDate,
uint256 _endDate,
address _artistAccount,
uint256 _artistCommission,
uint256 _priceInWei,
string _tokenUri,
uint256 _totalAvailable
) external returns (bool);
function artistsEditions(address _artistsAccount) external returns (uint256[1] _editionNumbers);
function totalAvailableEdition(uint256 _editionNumber) external returns (uint256);
function highestEditionNumber() external returns (uint256);
function updateOptionalCommission(uint256 _editionNumber, uint256 _rate, address _recipient) external;
function updateStartDate(uint256 _editionNumber, uint256 _startDate) external;
function updateEndDate(uint256 _editionNumber, uint256 _endDate) external;
function updateEditionType(uint256 _editionNumber, uint256 _editionType) external;
}
// File: contracts/v2/interfaces/IKODAAuction.sol
pragma solidity 0.4.24;
interface IKODAAuction {
function setArtistsControlAddressAndEnabledEdition(uint256 _editionNumber, address _address) external;
}
// File: contracts/v2/interfaces/ISelfServiceAccessControls.sol
pragma solidity 0.4.24;
interface ISelfServiceAccessControls {
function isEnabledForAccount(address account) public view returns (bool);
}
// File: contracts/v2/interfaces/ISelfServiceFrequencyControls.sol
pragma solidity 0.4.24;
interface ISelfServiceFrequencyControls {
/*
* Checks is the given artist can create another edition
* @param artist - the edition artist
* @param totalAvailable - the edition size
* @param priceInWei - the edition price in wei
*/
function canCreateNewEdition(address artist) external view returns (bool);
/*
* Records that an edition has been created
* @param artist - the edition artist
* @param totalAvailable - the edition size
* @param priceInWei - the edition price in wei
*/
function recordSuccessfulMint(address artist, uint256 totalAvailable, uint256 priceInWei) external returns (bool);
}
// File: contracts/v2/self-service/SelfServiceEditionCurationV4.sol
pragma solidity 0.4.24;
// One invocation per time-period
contract SelfServiceEditionCurationV4 is Whitelist, Pausable {
using SafeMath for uint256;
event SelfServiceEditionCreated(
uint256 indexed _editionNumber,
address indexed _creator,
uint256 _priceInWei,
uint256 _totalAvailable,
bool _enableAuction
);
// Calling address
IKODAV2SelfServiceEditionCuration public kodaV2;
IKODAAuction public auction;
ISelfServiceAccessControls public accessControls;
ISelfServiceFrequencyControls public frequencyControls;
// Default KO commission
uint256 public koCommission = 15;
// Config which enforces editions to not be over this size
uint256 public maxEditionSize = 100;
// Config the minimum price per edition
uint256 public minPricePerEdition = 0.01 ether;
/**
* @dev Construct a new instance of the contract
*/
constructor(
IKODAV2SelfServiceEditionCuration _kodaV2,
IKODAAuction _auction,
ISelfServiceAccessControls _accessControls,
ISelfServiceFrequencyControls _frequencyControls
) public {
super.addAddressToWhitelist(msg.sender);
kodaV2 = _kodaV2;
auction = _auction;
accessControls = _accessControls;
frequencyControls = _frequencyControls;
}
/**
* @dev Called by artists, create new edition on the KODA platform
*/
function createEdition(
bool _enableAuction,
address _optionalSplitAddress,
uint256 _optionalSplitRate,
uint256 _totalAvailable,
uint256 _priceInWei,
uint256 _startDate,
uint256 _endDate,
uint256 _artistCommission,
uint256 _editionType,
string _tokenUri
)
public
whenNotPaused
returns (uint256 _editionNumber)
{
require(frequencyControls.canCreateNewEdition(msg.sender), 'Sender currently frozen out of creation');
require(_artistCommission.add(_optionalSplitRate).add(koCommission) <= 100, "Total commission exceeds 100");
uint256 editionNumber = _createEdition(
msg.sender,
_enableAuction,
[_totalAvailable, _priceInWei, _startDate, _endDate, _artistCommission, _editionType],
_tokenUri
);
if (_optionalSplitRate > 0 && _optionalSplitAddress != address(0)) {
kodaV2.updateOptionalCommission(editionNumber, _optionalSplitRate, _optionalSplitAddress);
}
frequencyControls.recordSuccessfulMint(msg.sender, _totalAvailable, _priceInWei);
return editionNumber;
}
/**
* @dev Called by artists, create new edition on the KODA platform, single commission split between artists and KO only
*/
function createEditionSimple(
bool _enableAuction,
uint256 _totalAvailable,
uint256 _priceInWei,
uint256 _startDate,
uint256 _endDate,
uint256 _artistCommission,
uint256 _editionType,
string _tokenUri
)
public
whenNotPaused
returns (uint256 _editionNumber)
{
require(frequencyControls.canCreateNewEdition(msg.sender), 'Sender currently frozen out of creation');
require(_artistCommission.add(koCommission) <= 100, "Total commission exceeds 100");
uint256 editionNumber = _createEdition(
msg.sender,
_enableAuction,
[_totalAvailable, _priceInWei, _startDate, _endDate, _artistCommission, _editionType],
_tokenUri
);
frequencyControls.recordSuccessfulMint(msg.sender, _totalAvailable, _priceInWei);
return editionNumber;
}
/**
* @dev Caller by owner, can create editions for other artists
* @dev Only callable from owner regardless of pause state
*/
function createEditionFor(
address _artist,
bool _enableAuction,
address _optionalSplitAddress,
uint256 _optionalSplitRate,
uint256 _totalAvailable,
uint256 _priceInWei,
uint256 _startDate,
uint256 _endDate,
uint256 _artistCommission,
uint256 _editionType,
string _tokenUri
)
public
onlyIfWhitelisted(msg.sender)
returns (uint256 _editionNumber)
{
require(_artistCommission.add(_optionalSplitRate).add(koCommission) <= 100, "Total commission exceeds 100");
uint256 editionNumber = _createEdition(
_artist,
_enableAuction,
[_totalAvailable, _priceInWei, _startDate, _endDate, _artistCommission, _editionType],
_tokenUri
);
if (_optionalSplitRate > 0 && _optionalSplitAddress != address(0)) {
kodaV2.updateOptionalCommission(editionNumber, _optionalSplitRate, _optionalSplitAddress);
}
frequencyControls.recordSuccessfulMint(_artist, _totalAvailable, _priceInWei);
return editionNumber;
}
/**
* @dev Internal function for edition creation
*/
function _createEdition(
address _artist,
bool _enableAuction,
uint256[6] memory _params,
string _tokenUri
)
internal
returns (uint256 _editionNumber) {
uint256 _totalAvailable = _params[0];
uint256 _priceInWei = _params[1];
// Enforce edition size
require(msg.sender == owner || (_totalAvailable > 0 && _totalAvailable <= maxEditionSize), "Invalid edition size");
// Enforce min price
require(msg.sender == owner || _priceInWei >= minPricePerEdition, "Invalid price");
// If we are the owner, skip this artists check
require(msg.sender == owner || accessControls.isEnabledForAccount(_artist), "Not allowed to create edition");
// Find the next edition number we can use
uint256 editionNumber = getNextAvailableEditionNumber();
require(
kodaV2.createActiveEdition(
editionNumber,
0x0, // _editionData - no edition data
_params[5], //_editionType,
_params[2], // _startDate,
_params[3], //_endDate,
_artist,
_params[4], // _artistCommission - defaults to artistCommission if optional commission split missing
_priceInWei,
_tokenUri,
_totalAvailable
),
"Failed to create new edition"
);
// Enable the auction if desired
if (_enableAuction) {
auction.setArtistsControlAddressAndEnabledEdition(editionNumber, _artist);
}
// Trigger event
emit SelfServiceEditionCreated(editionNumber, _artist, _priceInWei, _totalAvailable, _enableAuction);
return editionNumber;
}
/**
* @dev Internal function for dynamically generating the next KODA edition number
*/
function getNextAvailableEditionNumber() internal returns (uint256 editionNumber) {
// Get current highest edition and total in the edition
uint256 highestEditionNumber = kodaV2.highestEditionNumber();
uint256 totalAvailableEdition = kodaV2.totalAvailableEdition(highestEditionNumber);
// Add the current highest plus its total, plus 1 as tokens start at 1 not zero
uint256 nextAvailableEditionNumber = highestEditionNumber.add(totalAvailableEdition).add(1);
// Round up to next 100, 1000 etc based on max allowed size
return ((nextAvailableEditionNumber + maxEditionSize - 1) / maxEditionSize) * maxEditionSize;
}
/**
* @dev Sets the KODA address
* @dev Only callable from owner
*/
function setKodavV2(IKODAV2SelfServiceEditionCuration _kodaV2) onlyIfWhitelisted(msg.sender) public {
kodaV2 = _kodaV2;
}
/**
* @dev Sets the KODA auction
* @dev Only callable from owner
*/
function setAuction(IKODAAuction _auction) onlyIfWhitelisted(msg.sender) public {
auction = _auction;
}
/**
* @dev Sets the default KO commission for each edition
* @dev Only callable from owner
*/
function setKoCommission(uint256 _koCommission) onlyIfWhitelisted(msg.sender) public {
koCommission = _koCommission;
}
/**
* @dev Sets the max edition size
* @dev Only callable from owner
*/
function setMaxEditionSize(uint256 _maxEditionSize) onlyIfWhitelisted(msg.sender) public {
maxEditionSize = _maxEditionSize;
}
/**
* @dev Sets minimum price per edition
* @dev Only callable from owner
*/
function setMinPricePerEdition(uint256 _minPricePerEdition) onlyIfWhitelisted(msg.sender) public {
minPricePerEdition = _minPricePerEdition;
}
/**
* @dev Checks to see if the account is currently frozen out
*/
function isFrozen(address account) public view returns (bool) {
return frequencyControls.canCreateNewEdition(account);
}
/**
* @dev Checks to see if the account can create editions
*/
function isEnabledForAccount(address account) public view returns (bool) {
return accessControls.isEnabledForAccount(account);
}
/**
* @dev Checks to see if the account can create editions
*/
function canCreateAnotherEdition(address account) public view returns (bool) {
if (!accessControls.isEnabledForAccount(account)) {
return false;
}
return frequencyControls.canCreateNewEdition(account);
}
/**
* @dev Allows for the ability to extract stuck ether
* @dev Only callable from owner
*/
function withdrawStuckEther(address _withdrawalAccount) onlyIfWhitelisted(msg.sender) public {
require(_withdrawalAccount != address(0), "Invalid address provided");
_withdrawalAccount.transfer(address(this).balance);
}
}
{
"compilationTarget": {
"SelfServiceEditionCurationV4.sol": "SelfServiceEditionCurationV4"
},
"evmVersion": "byzantium",
"libraries": {},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"constant":true,"inputs":[{"name":"_operator","type":"address"},{"name":"_role","type":"string"}],"name":"checkRole","outputs":[],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"ROLE_WHITELISTED","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_operator","type":"address"},{"name":"_role","type":"string"}],"name":"hasRole","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_operators","type":"address[]"}],"name":"removeAddressesFromWhitelist","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_withdrawalAccount","type":"address"}],"name":"withdrawStuckEther","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_operator","type":"address"}],"name":"removeAddressFromWhitelist","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"account","type":"address"}],"name":"isEnabledForAccount","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_enableAuction","type":"bool"},{"name":"_totalAvailable","type":"uint256"},{"name":"_priceInWei","type":"uint256"},{"name":"_startDate","type":"uint256"},{"name":"_endDate","type":"uint256"},{"name":"_artistCommission","type":"uint256"},{"name":"_editionType","type":"uint256"},{"name":"_tokenUri","type":"string"}],"name":"createEditionSimple","outputs":[{"name":"_editionNumber","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_koCommission","type":"uint256"}],"name":"setKoCommission","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"unpause","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"minPricePerEdition","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"koCommission","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_maxEditionSize","type":"uint256"}],"name":"setMaxEditionSize","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"kodaV2","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"paused","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"renounceOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"accessControls","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"maxEditionSize","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_operator","type":"address"}],"name":"addAddressToWhitelist","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"auction","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[],"name":"pause","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_operator","type":"address"}],"name":"whitelist","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"frequencyControls","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_enableAuction","type":"bool"},{"name":"_optionalSplitAddress","type":"address"},{"name":"_optionalSplitRate","type":"uint256"},{"name":"_totalAvailable","type":"uint256"},{"name":"_priceInWei","type":"uint256"},{"name":"_startDate","type":"uint256"},{"name":"_endDate","type":"uint256"},{"name":"_artistCommission","type":"uint256"},{"name":"_editionType","type":"uint256"},{"name":"_tokenUri","type":"string"}],"name":"createEdition","outputs":[{"name":"_editionNumber","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"account","type":"address"}],"name":"canCreateAnotherEdition","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_minPricePerEdition","type":"uint256"}],"name":"setMinPricePerEdition","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_auction","type":"address"}],"name":"setAuction","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_kodaV2","type":"address"}],"name":"setKodavV2","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_artist","type":"address"},{"name":"_enableAuction","type":"bool"},{"name":"_optionalSplitAddress","type":"address"},{"name":"_optionalSplitRate","type":"uint256"},{"name":"_totalAvailable","type":"uint256"},{"name":"_priceInWei","type":"uint256"},{"name":"_startDate","type":"uint256"},{"name":"_endDate","type":"uint256"},{"name":"_artistCommission","type":"uint256"},{"name":"_editionType","type":"uint256"},{"name":"_tokenUri","type":"string"}],"name":"createEditionFor","outputs":[{"name":"_editionNumber","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_operators","type":"address[]"}],"name":"addAddressesToWhitelist","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"account","type":"address"}],"name":"isFrozen","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[{"name":"_kodaV2","type":"address"},{"name":"_auction","type":"address"},{"name":"_accessControls","type":"address"},{"name":"_frequencyControls","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_editionNumber","type":"uint256"},{"indexed":true,"name":"_creator","type":"address"},{"indexed":false,"name":"_priceInWei","type":"uint256"},{"indexed":false,"name":"_totalAvailable","type":"uint256"},{"indexed":false,"name":"_enableAuction","type":"bool"}],"name":"SelfServiceEditionCreated","type":"event"},{"anonymous":false,"inputs":[],"name":"Pause","type":"event"},{"anonymous":false,"inputs":[],"name":"Unpause","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"operator","type":"address"},{"indexed":false,"name":"role","type":"string"}],"name":"RoleAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"operator","type":"address"},{"indexed":false,"name":"role","type":"string"}],"name":"RoleRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"previousOwner","type":"address"}],"name":"OwnershipRenounced","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"previousOwner","type":"address"},{"indexed":true,"name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"}]