/** * Source Code first verified at https://etherscan.io on Saturday, April 13, 2019 (UTC) */ pragma solidity ^0.4.24; /** * Utility library of inline functions on addresses */ library Address { /** * Returns whether the target address is a contract * @dev This function will return false if invoked during the constructor of a contract, * as the code is not actually created until after the constructor finishes. * @param account address of the account to check * @return whether the target address is a contract */ function isContract(address account) internal view returns (bool) { uint256 size; // XXX Currently there is no better way to check if there is a contract in an address // than to check the size of the code at that address. // See https://ethereum.stackexchange.com/a/14016/36603 // for more details about how this works. // TODO Check this again before the Serenity release, because all addresses will be // contracts then. // solium-disable-next-line security/no-inline-assembly assembly { size := extcodesize(account) } return size > 0; } } /** * @title Roles * @dev Library for managing addresses assigned to a Role. */ library Roles { struct Role { mapping (address => bool) bearer; } /** * @dev give an account access to this role */ function add(Role storage role, address account) internal { require(account != address(0)); require(!has(role, account)); role.bearer[account] = true; } /** * @dev remove an account's access to this role */ function remove(Role storage role, address account) internal { require(account != address(0)); require(has(role, account)); role.bearer[account] = false; } /** * @dev check if an account has this role * @return bool */ function has(Role storage role, address account) internal view returns (bool) { require(account != address(0)); return role.bearer[account]; } } contract PauserRole { using Roles for Roles.Role; event PauserAdded(address indexed account); event PauserRemoved(address indexed account); Roles.Role private _pausers; constructor () internal { _addPauser(msg.sender); } modifier onlyPauser() { require(isPauser(msg.sender)); _; } function isPauser(address account) public view returns (bool) { return _pausers.has(account); } function addPauser(address account) public onlyPauser { _addPauser(account); } function renouncePauser() public { _removePauser(msg.sender); } function _addPauser(address account) internal { _pausers.add(account); emit PauserAdded(account); } function _removePauser(address account) internal { _pausers.remove(account); emit PauserRemoved(account); } } /** * @title Pausable * @dev Base contract which allows children to implement an emergency stop mechanism. */ contract Pausable is PauserRole { event Paused(address account); event Unpaused(address account); bool private _paused; constructor () internal { _paused = false; } /** * @return true if the contract is paused, false otherwise. */ function paused() public view returns (bool) { return _paused; } /** * @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 onlyPauser whenNotPaused { _paused = true; emit Paused(msg.sender); } /** * @dev called by the owner to unpause, returns to normal state */ function unpause() public onlyPauser whenPaused { _paused = false; emit Unpaused(msg.sender); } } /** * @title SafeMath * @dev Math operations with safety checks that revert on error */ library SafeMath { /** * @dev Multiplies two numbers, reverts on overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { // Gas optimization: this is cheaper than requiring '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; } uint256 c = a * b; require(c / a == b); return c; } /** * @dev Integer division of two numbers truncating the quotient, reverts on division by zero. */ function div(uint256 a, uint256 b) internal pure returns (uint256) { require(b > 0); // Solidity only automatically asserts 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 c; } /** * @dev Subtracts two numbers, reverts on overflow (i.e. if subtrahend is greater than minuend). */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { require(b <= a); uint256 c = a - b; return c; } /** * @dev Adds two numbers, reverts on overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256) { uint256 c = a + b; require(c >= a); return c; } /** * @dev Divides two numbers and returns the remainder (unsigned integer modulo), * reverts when dividing by zero. */ function mod(uint256 a, uint256 b) internal pure returns (uint256) { require(b != 0); return a % b; } } /** * @title SafeMath32 * @dev SafeMath library implemented for uint32 */ library SafeMath32 { function mul(uint32 a, uint32 b) internal pure returns (uint32) { if (a == 0) { return 0; } uint32 c = a * b; assert(c / a == b); return c; } function div(uint32 a, uint32 b) internal pure returns (uint32) { // assert(b > 0); // Solidity automatically throws when dividing by 0 uint32 c = a / b; // assert(a == b * c + a % b); // There is no case in which this doesn't hold return c; } function sub(uint32 a, uint32 b) internal pure returns (uint32) { assert(b <= a); return a - b; } function add(uint32 a, uint32 b) internal pure returns (uint32) { uint32 c = a + b; assert(c >= a); return c; } } /** * @title SafeMath16 * @dev SafeMath library implemented for uint16 */ library SafeMath16 { function mul(uint16 a, uint16 b) internal pure returns (uint16) { if (a == 0) { return 0; } uint16 c = a * b; assert(c / a == b); return c; } function div(uint16 a, uint16 b) internal pure returns (uint16) { // assert(b > 0); // Solidity automatically throws when dividing by 0 uint16 c = a / b; // assert(a == b * c + a % b); // There is no case in which this doesn't hold return c; } function sub(uint16 a, uint16 b) internal pure returns (uint16) { assert(b <= a); return a - b; } function add(uint16 a, uint16 b) internal pure returns (uint16) { uint16 c = a + b; assert(c >= a); return c; } } /** * @title IERC165 * @dev https://github.com/ethereum/EIPs/blob/master/EIPS/eip-165.md */ interface IERC165 { /** * @notice Query if a contract implements an interface * @param interfaceId The interface identifier, as specified in ERC-165 * @dev Interface identification is specified in ERC-165. This function * uses less than 30,000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); } /** * @title ERC165 * @author Matt Condon (@shrugs) * @dev Implements ERC165 using a lookup table. */ contract ERC165 is IERC165 { bytes4 private constant _InterfaceId_ERC165 = 0x01ffc9a7; /** * 0x01ffc9a7 === * bytes4(keccak256('supportsInterface(bytes4)')) */ /** * @dev a mapping of interface id to whether or not it's supported */ mapping(bytes4 => bool) private _supportedInterfaces; /** * @dev A contract implementing SupportsInterfaceWithLookup * implement ERC165 itself */ constructor() internal { _registerInterface(_InterfaceId_ERC165); } /** * @dev implement supportsInterface(bytes4) using a lookup table */ function supportsInterface(bytes4 interfaceId) external view returns (bool) { return _supportedInterfaces[interfaceId]; } /** * @dev internal method for registering an interface */ function _registerInterface(bytes4 interfaceId) internal { require(interfaceId != 0xffffffff); _supportedInterfaces[interfaceId] = true; } } /** * @title ERC721 Non-Fungible Token Standard basic interface * @dev see https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md */ contract IERC721 is IERC165 { event Transfer( address indexed from, address indexed to, uint256 indexed tokenId ); event Approval( address indexed owner, address indexed approved, uint256 indexed tokenId ); event ApprovalForAll( address indexed owner, address indexed operator, bool approved ); function balanceOf(address owner) public view returns (uint256 balance); function ownerOf(uint256 tokenId) public view returns (address owner); function approve(address to, uint256 tokenId) public; function getApproved(uint256 tokenId) public view returns (address operator); function setApprovalForAll(address operator, bool _approved) public; function isApprovedForAll(address owner, address operator) public view returns (bool); function transferFrom(address from, address to, uint256 tokenId) public; function safeTransferFrom(address from, address to, uint256 tokenId) public; function safeTransferFrom( address from, address to, uint256 tokenId, bytes data ) public; } /** * @title ERC721 token receiver interface * @dev Interface for any contract that wants to support safeTransfers * from ERC721 asset contracts. */ contract IERC721Receiver { /** * @notice Handle the receipt of an NFT * @dev The ERC721 smart contract calls this function on the recipient * after a `safeTransfer`. This function MUST return the function selector, * otherwise the caller will revert the transaction. The selector to be * returned can be obtained as `this.onERC721Received.selector`. This * function MAY throw to revert and reject the transfer. * Note: the ERC721 contract address is always the message sender. * @param operator The address which called `safeTransferFrom` function * @param from The address which previously owned the token * @param tokenId The NFT identifier which is being transferred * @param data Additional data with no specified format * @return `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))` */ function onERC721Received( address operator, address from, uint256 tokenId, bytes data ) public returns(bytes4); } /** * @title ERC721 Non-Fungible Token Standard basic implementation * @dev see https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md */ contract ERC721 is ERC165, IERC721 { using SafeMath for uint256; using Address for address; // Equals to `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))` // which can be also obtained as `IERC721Receiver(0).onERC721Received.selector` bytes4 private constant _ERC721_RECEIVED = 0x150b7a02; // Mapping from token ID to owner mapping (uint256 => address) private _tokenOwner; // Mapping from token ID to approved address mapping (uint256 => address) private _tokenApprovals; // Mapping from owner to number of owned token mapping (address => uint256) private _ownedTokensCount; // Mapping from owner to operator approvals mapping (address => mapping (address => bool)) private _operatorApprovals; bytes4 private constant _InterfaceId_ERC721 = 0x80ac58cd; /* * 0x80ac58cd === * bytes4(keccak256('balanceOf(address)')) ^ * bytes4(keccak256('ownerOf(uint256)')) ^ * bytes4(keccak256('approve(address,uint256)')) ^ * bytes4(keccak256('getApproved(uint256)')) ^ * bytes4(keccak256('setApprovalForAll(address,bool)')) ^ * bytes4(keccak256('isApprovedForAll(address,address)')) ^ * bytes4(keccak256('transferFrom(address,address,uint256)')) ^ * bytes4(keccak256('safeTransferFrom(address,address,uint256)')) ^ * bytes4(keccak256('safeTransferFrom(address,address,uint256,bytes)')) */ constructor() public { // register the supported interfaces to conform to ERC721 via ERC165 _registerInterface(_InterfaceId_ERC721); } /** * @dev Gets the balance of the specified address * @param owner address to query the balance of * @return uint256 representing the amount owned by the passed address */ function balanceOf(address owner) public view returns (uint256) { require(owner != address(0)); return _ownedTokensCount[owner]; } /** * @dev Gets the owner of the specified token ID * @param tokenId uint256 ID of the token to query the owner of * @return owner address currently marked as the owner of the given token ID */ function ownerOf(uint256 tokenId) public view returns (address) { address owner = _tokenOwner[tokenId]; require(owner != address(0)); return owner; } /** * @dev Approves another address to transfer the given token ID * The zero address indicates there is no approved address. * There can only be one approved address per token at a given time. * Can only be called by the token owner or an approved operator. * @param to address to be approved for the given token ID * @param tokenId uint256 ID of the token to be approved */ function approve(address to, uint256 tokenId) public { address owner = ownerOf(tokenId); require(to != owner); require(msg.sender == owner || isApprovedForAll(owner, msg.sender)); _tokenApprovals[tokenId] = to; emit Approval(owner, to, tokenId); } /** * @dev Gets the approved address for a token ID, or zero if no address set * Reverts if the token ID does not exist. * @param tokenId uint256 ID of the token to query the approval of * @return address currently approved for the given token ID */ function getApproved(uint256 tokenId) public view returns (address) { require(_exists(tokenId)); return _tokenApprovals[tokenId]; } /** * @dev Sets or unsets the approval of a given operator * An operator is allowed to transfer all tokens of the sender on their behalf * @param to operator address to set the approval * @param approved representing the status of the approval to be set */ function setApprovalForAll(address to, bool approved) public { require(to != msg.sender); _operatorApprovals[msg.sender][to] = approved; emit ApprovalForAll(msg.sender, to, approved); } /** * @dev Tells whether an operator is approved by a given owner * @param owner owner address which you want to query the approval of * @param operator operator address which you want to query the approval of * @return bool whether the given operator is approved by the given owner */ function isApprovedForAll( address owner, address operator ) public view returns (bool) { return _operatorApprovals[owner][operator]; } /** * @dev Transfers the ownership of a given token ID to another address * Usage of this method is discouraged, use `safeTransferFrom` whenever possible * Requires the msg sender to be the owner, approved, or operator * @param from current owner of the token * @param to address to receive the ownership of the given token ID * @param tokenId uint256 ID of the token to be transferred */ function transferFrom( address from, address to, uint256 tokenId ) public { require(_isApprovedOrOwner(msg.sender, tokenId)); require(to != address(0)); _clearApproval(from, tokenId); _removeTokenFrom(from, tokenId); _addTokenTo(to, tokenId); emit Transfer(from, to, tokenId); } /** * @dev Safely transfers the ownership of a given token ID to another address * If the target address is a contract, it must implement `onERC721Received`, * which is called upon a safe transfer, and return the magic value * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise, * the transfer is reverted. * * Requires the msg sender to be the owner, approved, or operator * @param from current owner of the token * @param to address to receive the ownership of the given token ID * @param tokenId uint256 ID of the token to be transferred */ function safeTransferFrom( address from, address to, uint256 tokenId ) public { // solium-disable-next-line arg-overflow safeTransferFrom(from, to, tokenId, ""); } /** * @dev Safely transfers the ownership of a given token ID to another address * If the target address is a contract, it must implement `onERC721Received`, * which is called upon a safe transfer, and return the magic value * `bytes4(keccak256("onERC721Received(address,address,uint256,bytes)"))`; otherwise, * the transfer is reverted. * Requires the msg sender to be the owner, approved, or operator * @param from current owner of the token * @param to address to receive the ownership of the given token ID * @param tokenId uint256 ID of the token to be transferred * @param _data bytes data to send along with a safe transfer check */ function safeTransferFrom( address from, address to, uint256 tokenId, bytes _data ) public { transferFrom(from, to, tokenId); // solium-disable-next-line arg-overflow require(_checkOnERC721Received(from, to, tokenId, _data)); } /** * @dev Returns whether the specified token exists * @param tokenId uint256 ID of the token to query the existence of * @return whether the token exists */ function _exists(uint256 tokenId) internal view returns (bool) { address owner = _tokenOwner[tokenId]; return owner != address(0); } /** * @dev Returns whether the given spender can transfer a given token ID * @param spender address of the spender to query * @param tokenId uint256 ID of the token to be transferred * @return bool whether the msg.sender is approved for the given token ID, * is an operator of the owner, or is the owner of the token */ function _isApprovedOrOwner( address spender, uint256 tokenId ) internal view returns (bool) { address owner = ownerOf(tokenId); // Disable solium check because of // https://github.com/duaraghav8/Solium/issues/175 // solium-disable-next-line operator-whitespace return ( spender == owner || getApproved(tokenId) == spender || isApprovedForAll(owner, spender) ); } /** * @dev Internal function to mint a new token * Reverts if the given token ID already exists * @param to The address that will own the minted token * @param tokenId uint256 ID of the token to be minted by the msg.sender */ function _mint(address to, uint256 tokenId) internal { require(to != address(0)); _addTokenTo(to, tokenId); emit Transfer(address(0), to, tokenId); } /** * @dev Internal function to burn a specific token * Reverts if the token does not exist * @param tokenId uint256 ID of the token being burned by the msg.sender */ function _burn(address owner, uint256 tokenId) internal { _clearApproval(owner, tokenId); _removeTokenFrom(owner, tokenId); emit Transfer(owner, address(0), tokenId); } /** * @dev Internal function to add a token ID to the list of a given address * Note that this function is left internal to make ERC721Enumerable possible, but is not * intended to be called by custom derived contracts: in particular, it emits no Transfer event. * @param to address representing the new owner of the given token ID * @param tokenId uint256 ID of the token to be added to the tokens list of the given address */ function _addTokenTo(address to, uint256 tokenId) internal { require(_tokenOwner[tokenId] == address(0)); _tokenOwner[tokenId] = to; _ownedTokensCount[to] = _ownedTokensCount[to].add(1); } /** * @dev Internal function to remove a token ID from the list of a given address * Note that this function is left internal to make ERC721Enumerable possible, but is not * intended to be called by custom derived contracts: in particular, it emits no Transfer event, * and doesn't clear approvals. * @param from address representing the previous owner of the given token ID * @param tokenId uint256 ID of the token to be removed from the tokens list of the given address */ function _removeTokenFrom(address from, uint256 tokenId) internal { require(ownerOf(tokenId) == from); _ownedTokensCount[from] = _ownedTokensCount[from].sub(1); _tokenOwner[tokenId] = address(0); } /** * @dev Internal function to invoke `onERC721Received` on a target address * The call is not executed if the target address is not a contract * @param from address representing the previous owner of the given token ID * @param to target address that will receive the tokens * @param tokenId uint256 ID of the token to be transferred * @param _data bytes optional data to send along with the call * @return whether the call correctly returned the expected magic value */ function _checkOnERC721Received( address from, address to, uint256 tokenId, bytes _data ) internal returns (bool) { if (!to.isContract()) { return true; } bytes4 retval = IERC721Receiver(to).onERC721Received( msg.sender, from, tokenId, _data); return (retval == _ERC721_RECEIVED); } /** * @dev Private function to clear current approval of a given token ID * Reverts if the given address is not indeed the owner of the token * @param owner owner of the token * @param tokenId uint256 ID of the token to be transferred */ function _clearApproval(address owner, uint256 tokenId) private { require(ownerOf(tokenId) == owner); if (_tokenApprovals[tokenId] != address(0)) { _tokenApprovals[tokenId] = address(0); } } } /// @title ERC-721 Non-Fungible Token Standard, optional metadata extension /// @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md /// Note: the ERC-165 identifier for this interface is 0x5b5e139f. interface ERC721Metadata /* is ERC721 */ { /// @notice A descriptive name for a collection of NFTs in this contract function name() external view returns (string _name); /// @notice An abbreviated name for NFTs in this contract function symbol() external view returns (string _symbol); /// @notice A distinct Uniform Resource Identifier (URI) for a given asset. /// @dev Throws if `_tokenId` is not a valid NFT. URIs are defined in RFC /// 3986. The URI may point to a JSON file that conforms to the "ERC721 /// Metadata JSON Schema". function tokenURI(uint256 _tokenId) external view returns (string); } /// @title ERC-721 Non-Fungible Token Standard, optional enumeration extension /// @dev See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-721.md /// Note: the ERC-165 identifier for this interface is 0x780e9d63. interface ERC721Enumerable /* is ERC721 */ { /// @notice Count NFTs tracked by this contract /// @return A count of valid NFTs tracked by this contract, where each one of /// them has an assigned and queryable owner not equal to the zero address function totalSupply() external view returns (uint256); /// @notice Enumerate valid NFTs /// @dev Throws if `_index` >= `totalSupply()`. /// @param _index A counter less than `totalSupply()` /// @return The token identifier for the `_index`th NFT, /// (sort order not specified) function tokenByIndex(uint256 _index) external view returns (uint256); /// @notice Enumerate NFTs assigned to an owner /// @dev Throws if `_index` >= `balanceOf(_owner)` or if /// `_owner` is the zero address, representing invalid NFTs. /// @param _owner An address where we are interested in NFTs owned by them /// @param _index A counter less than `balanceOf(_owner)` /// @return The token identifier for the `_index`th NFT assigned to `_owner`, /// (sort order not specified) function tokenOfOwnerByIndex(address _owner, uint256 _index) external view returns (uint256); } /** * @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 private _owner; event OwnershipTransferred( address indexed previousOwner, address indexed newOwner ); /** * @dev The Ownable constructor sets the original `owner` of the contract to the sender * account. */ constructor() internal { _owner = msg.sender; emit OwnershipTransferred(address(0), _owner); } /** * @return the address of the owner. */ function owner() public view returns(address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { require(isOwner()); _; } /** * @return true if `msg.sender` is the owner of the contract. */ function isOwner() public view returns(bool) { return 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 OwnershipTransferred(_owner, address(0)); _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; } } /// @title 0x415254. Un contrato para creación de piezas de arte /// @author Daniel Fernando Perosio (http://danielperosio.com) e-mail [email protected] - [email protected] /// @notice Esto es Arte!!! Este contrato permite la creación, la mezcla y la transferencia de obras /// @dev Compatible con la implementación de OpenZeppelin de la especificación ERC721 Crypto Coleccionables /************************* ________________________ ||.......................| ||.......................| ||.......................| ||.......................| ||.......................| ||........0x415254.......| ||......THIS IS ART......| ||......-----------......| ||.......................| ||.......................| ||.......................| ||.......................| ||.......................| ||_______________________| *************************/ contract ART is Ownable, ERC721, Pausable { string public name = "0x415254"; string public symbol = "ART"; using SafeMath for uint256; using SafeMath32 for uint32; using SafeMath16 for uint16; event NewWork(uint workId, string title, uint8 red, uint8 green, uint8 blue, string _characterrand, uint _drawing); string public code = "[email protected]*35zl"; string public compiler = "Pyth"; uint16 public characterQuantity = 60; uint public randNonce = 0; string[] public character = [" ","!","#","$","%","'","(",")","*","+", ",","-",".","/","6","7","8","9", ":",";","<","=",">","?","@","A","C","D","F","H","I", "L","N","O","P","S","T","U","V","X","Y", "[","]","^","_","`", "c","l","n","o","p","q","s","v","x","y", "{","|","}","~"]; struct Art { string title; uint8 red; uint8 green; uint8 blue; string characterRand; uint drawing; string series; uint16 mixCount; uint16 electCount; } Art[] public works; mapping (uint => address) public workToOwner; mapping (address => uint) ownerWorkCount; function setCode(string _newCode, string _newCompiler ) external onlyOwner { code = _newCode; compiler = _newCompiler; } function setCharacter(string _value, uint16 _quantity ) external onlyOwner { character.push(_value); characterQuantity = _quantity; } function _createWork(string _title, uint8 _red, uint8 _green, uint8 _blue, string _characterRand, uint _drawing, string _series) internal whenNotPaused { uint id = works.push(Art(_title, _red, _green, _blue, _characterRand, _drawing, _series, 0, 0)) - 1; workToOwner[id] = msg.sender; ownerWorkCount[msg.sender] = ownerWorkCount[msg.sender].add(1); emit NewWork(id, _title, _red, _green, _blue, _characterRand, _drawing); } uint workFee = 0 ether; uint mixWorkFee = 0 ether; function withdraw() external onlyOwner { owner().transfer(address(this).balance); } function setUpFee(uint _feecreate, uint _feemix) external onlyOwner { workFee = _feecreate; mixWorkFee = _feemix; } function _createString(string _title) internal returns (string) { uint a = uint(keccak256(abi.encodePacked(_title, randNonce))) % characterQuantity; uint b = uint(keccak256(abi.encodePacked(msg.sender, randNonce))) % characterQuantity; uint c = uint(keccak256(abi.encodePacked(_title, msg.sender, randNonce))) % characterQuantity; uint d = uint(keccak256(abi.encodePacked(_title, _title, randNonce))) % characterQuantity; bytes memory characterRanda = bytes(abi.encodePacked(character[a])); bytes memory characterRandb = bytes(abi.encodePacked(character[b])); bytes memory characterRandc = bytes(abi.encodePacked(character[c])); bytes memory characterRandd = bytes(abi.encodePacked(character[d])); string memory characterRand = string (abi.encodePacked("'",characterRanda,"','", characterRandb,"','", characterRandc,"','", characterRandd,"'")); randNonce = randNonce.add(1); return characterRand; } function createArt( string _title) external payable whenNotPaused { require(msg.value == workFee); uint8 red = uint8(keccak256(abi.encodePacked(_title, randNonce))) % 255; uint8 green= uint8(keccak256(abi.encodePacked(msg.sender, randNonce))) % 255; uint8 blue = uint8(keccak256(abi.encodePacked(_title, msg.sender, randNonce))) % 255; uint drawing = uint(keccak256(abi.encodePacked(_title))); string memory characterRand = _createString(_title); string memory series = "A"; _createWork(_title, red, green, blue, characterRand, drawing, series); } function createCustom(string _title, uint8 _red, uint8 _green, uint8 _blue, string _characterRand ) external onlyOwner { uint drawing = uint(keccak256(abi.encodePacked(_title))); string memory series = "B"; _createWork(_title, _red, _green, _blue, _characterRand, drawing, series); } modifier onlyOwnerOf(uint _workId) { require(msg.sender == workToOwner[_workId]); _; } function _blendString(string _str, uint _startIndex, uint _endIndex) private pure returns (string) { bytes memory strBytes = bytes(_str); bytes memory result = new bytes(_endIndex-_startIndex); for(uint i = _startIndex; i < _endIndex; i++) { result[i-_startIndex] = strBytes[i]; } return string(result); } function _joinString (string _chrctrRands, string _chrctrRandi) private pure returns (string) { string memory characterRands = _blendString(_chrctrRands, 0, 8); string memory characterRandi = _blendString(_chrctrRandi, 0, 7); string memory result = string (abi.encodePacked(string(characterRands), string(characterRandi))); return string(result); } function _blendWork(string _title, uint _workId, uint _electRed , uint _electGreen , uint _electBlue, string _electCharacterRand, uint _electDrawing ) internal onlyOwnerOf(_workId) { Art storage myWork = works[_workId]; uint8 newRed = uint8(uint(myWork.red + _electRed) / 2); uint8 newGreen = uint8(uint(myWork.green + _electGreen) / 2); uint8 newBlue = uint8(uint(myWork.blue + _electBlue) / 2); uint newDrawing = uint(myWork.drawing + _electDrawing + randNonce) / 2; string memory newCharacterRand = _joinString(myWork.characterRand, _electCharacterRand); string memory series = "C"; _createWork(_title, newRed, newGreen, newBlue, newCharacterRand, newDrawing, series); } function blend(string _title, uint _workId, uint _electId) external payable onlyOwnerOf(_workId) whenNotPaused { require(msg.value == mixWorkFee); Art storage myWork = works[_workId]; Art storage electWork = works[_electId]; myWork.mixCount = myWork.mixCount.add(1); electWork.electCount = electWork.electCount.add(1); _blendWork(_title, _workId, electWork.red, electWork.green, electWork.blue, electWork.characterRand, electWork.drawing ); } function getWorksByOwner(address _owner) external view returns(uint[]) { uint[] memory result = new uint[](ownerWorkCount[_owner]); uint counter = 0; for (uint i = 0; i < works.length; i++) { if (workToOwner[i] == _owner) { result[counter] = i; counter++; } } return result; } modifier validDestination( address to ) { require(to != address(0x0)); require(to != address(this) ); _; } /*ERC721*/ mapping (uint => address) workApprovals; function balanceOf(address _owner) public view returns (uint256 _balance) { return ownerWorkCount[_owner]; } function ownerOf(uint256 _tokenId) public view returns (address _owner) { return workToOwner[_tokenId]; } function _transfer(address _from, address _to, uint256 _tokenId) private validDestination(_to) { ownerWorkCount[_to] = ownerWorkCount[_to].add(1); ownerWorkCount[_from] = ownerWorkCount[_from].sub(1); workToOwner[_tokenId] = _to; emit Transfer(_from, _to, _tokenId); } function transfer(address _to, uint256 _tokenId) public onlyOwnerOf(_tokenId) validDestination(_to) { _transfer(msg.sender, _to, _tokenId); } function approve(address _to, uint256 _tokenId) public onlyOwnerOf(_tokenId) validDestination(_to) { workApprovals[_tokenId] = _to; emit Approval(msg.sender, _to, _tokenId); } function takeOwnership(uint256 _tokenId) public { require(workApprovals[_tokenId] == msg.sender); address owner = ownerOf(_tokenId); _transfer(owner, msg.sender, _tokenId); } function totalSupply() public view returns (uint) { return works.length - 1; } }