//Write your own contracts here. Currently compiles using solc v0.4.15+commit.bbb8e64f. pragma solidity ^0.4.18; /** * @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; /** * @dev The Ownable constructor sets the original `owner` of the contract to the sender * account. */ function Ownable() { 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 transfer control of the contract to a newOwner. * @param newOwner The address to transfer ownership to. */ function transferOwnership(address newOwner) onlyOwner { if (newOwner != address(0)) { owner = newOwner; } } } /// @title Interface for contracts conforming to ERC-721: Non-Fungible Tokens /// @author Dieter Shirley <dete@axiomzen.co> (https://github.com/dete) contract ERC721 { // Required methods function totalSupply() public view returns (uint256 total); function balanceOf(address _owner) public view returns (uint256 balance); function ownerOf(uint256 _tokenId) external view returns (address owner); function approve(address _to, uint256 _tokenId) external; function transfer(address _to, uint256 _tokenId) external; function transferFrom(address _from, address _to, uint256 _tokenId) external; // Events event Transfer(address from, address to, uint256 tokenId); event Approval(address owner, address approved, uint256 tokenId); // Optional // function name() public view returns (string name); // function symbol() public view returns (string symbol); // function tokensOfOwner(address _owner) external view returns (uint256[] tokenIds); // function tokenMetadata(uint256 _tokenId, string _preferredTransport) public view returns (string infoUrl); // ERC-165 Compatibility (https://github.com/ethereum/EIPs/issues/165) function supportsInterface(bytes4 _interfaceID) external view returns (bool); } /// @title A facet of that manages special access privileges. /// @author Axiom Zen (https://www.axiomzen.co) /// @dev See the KittyCore contract documentation to understand how the various contract facets are arranged. contract ContentAccessControl { // This facet controls access control for CryptoKitties. There are four roles managed here: // // - The CEO: The CEO can reassign other roles and change the addresses of our dependent smart // contracts. It is also the only role that can unpause the smart contract. It is initially // set to the address that created the smart contract in the KittyCore constructor. // // - The CFO: The CFO can withdraw funds from KittyCore and its auction contracts. // // - The COO: The COO can release gen0 kitties to auction, and mint promo cats. // // It should be noted that these roles are distinct without overlap in their access abilities, the // abilities listed for each role above are exhaustive. In particular, while the CEO can assign any // address to any role, the CEO address itself doesn't have the ability to act in those roles. This // restriction is intentional so that we aren't tempted to use the CEO address frequently out of // convenience. The less we use an address, the less likely it is that we somehow compromise the // account. /// @dev Emited when contract is upgraded - See README.md for updgrade plan event ContractUpgrade(address newContract); // The addresses of the accounts (or contracts) that can execute actions within each roles. address public ceoAddress; address public cfoAddress; address public cooAddress; // @dev Keeps track whether the contract is paused. When that is true, most actions are blocked bool public paused = false; /// @dev Access modifier for CEO-only functionality modifier onlyCEO() { require(msg.sender == ceoAddress); _; } /// @dev Access modifier for CFO-only functionality modifier onlyCFO() { require(msg.sender == cfoAddress); _; } /// @dev Access modifier for COO-only functionality modifier onlyCOO() { require(msg.sender == cooAddress); _; } modifier onlyCLevel() { require( msg.sender == cooAddress || msg.sender == ceoAddress || msg.sender == cfoAddress ); _; } /// @dev Assigns a new address to act as the CEO. Only available to the current CEO. /// @param _newCEO The address of the new CEO function setCEO(address _newCEO) external onlyCEO { require(_newCEO != address(0)); ceoAddress = _newCEO; } /// @dev Assigns a new address to act as the CFO. Only available to the current CEO. /// @param _newCFO The address of the new CFO function setCFO(address _newCFO) external onlyCEO { require(_newCFO != address(0)); cfoAddress = _newCFO; } /// @dev Assigns a new address to act as the COO. Only available to the current CEO. /// @param _newCOO The address of the new COO function setCOO(address _newCOO) external onlyCEO { require(_newCOO != address(0)); cooAddress = _newCOO; } } contract RegistryBase is ContentAccessControl { event Transfer( address from, address to, uint256 tokenId); event Register( uint256 contentId, address owner, string contentTitle); struct Content { string contentType; string contentTitle; string metadataAddress; string ownerName; uint32 ownStartDate; uint32 ownEndDate; uint32[] territories; uint32[] medias; bool exclusive; } /* struct Sale { string title; string metadataAddress; string licenseeName; uint32 ownStartDate; uint32 ownEndDate; uint16[] territories; uint16[] medias; bool exclusive; } /* CONSTANTS */ uint32[7] public territories = [ uint32(1), uint32(2), uint32(3), uint32(4), uint32(5), uint32(6), uint32(7) ]; uint32[7] public medias = [ uint32(1), uint32(2), uint32(3), uint32(4), uint32(5), uint32(6), uint32(7) ]; Content[] contents; // map content's ID to owner address mapping (uint256 => address) public contentIndexToOwner; // @dev A mapping from owner address to count of tokens that address owns. // Used internally inside balanceOf() to resolve ownership count. mapping (address => uint256) ownershipTokenCount; /// @dev A mapping from KittyIDs to an address that has been approved to call /// transferFrom(). Each Kitty can only have one approved address for transfer /// at any time. A zero value means no approval is outstanding. //mapping (uint256 => address) public contentIndexToApproved; function _transfer(address _from, address _to, uint256 _tokenId) internal { // adds a token to owner's balance ownershipTokenCount[_to]++; // transfer ownership contentIndexToOwner[_tokenId] = _to; if (_from != address(0)) { ownershipTokenCount[_from]--; // clear any previously approved ownership exchanges //delete contentIndexToApproved[_tokenId]; } // emit transfer event Transfer(_from, _to, _tokenId); } function _createContent( string _contentType, string _contentTitle, string _metadataAddress, string _ownerName, address _owner, uint32 _ownStartDate, uint32 _ownEndDate, uint32[] _territories, uint32[] _medias, bool _exclusive ) internal returns (uint) { Content memory _content = Content({ contentType: _contentType, contentTitle: _contentTitle, metadataAddress: _metadataAddress, ownerName: _ownerName, ownStartDate: _ownStartDate, ownEndDate: _ownEndDate, territories: _territories, medias: _medias, exclusive: _exclusive }); uint256 newTitleId = contents.push(_content) - 1; require(newTitleId == uint256(uint32(newTitleId))); Register( newTitleId, _owner, _contentTitle ); _transfer(0, _owner, newTitleId); return newTitleId; } } /// @title The external contract that is responsible for generating metadata for the kitties, /// it has one function that will return the data as bytes. contract ERC721Metadata { /// @dev Given a token Id, returns a byte array that is supposed to be converted into string. function getMetadata(uint256 _tokenId, string) public view returns (bytes32[4] buffer, uint256 count) { if (_tokenId == 1) { buffer[0] = "Hello World! :D"; count = 15; } else if (_tokenId == 2) { buffer[0] = "I would definitely choose a medi"; buffer[1] = "um length string."; count = 49; } else if (_tokenId == 3) { buffer[0] = "Lorem ipsum dolor sit amet, mi e"; buffer[1] = "st accumsan dapibus augue lorem,"; buffer[2] = " tristique vestibulum id, libero"; buffer[3] = " suscipit varius sapien aliquam."; count = 128; } } event Transfer(address from, address to, uint256 tokenId); event Approval(address owner, address approved, uint256 tokenId); } contract ContentOwnership is RegistryBase, ERC721 { string public constant name = "ContentCoins"; string public constant symbol = "COC"; ERC721Metadata public erc721Metadata; bytes4 constant InterfaceSignature_ERC165 = bytes4(keccak256('supportsInterface(bytes4)')); bytes4 constant InterfaceSignature_ERC721 = bytes4(keccak256('name()')) ^ bytes4(keccak256('symbol()')) ^ bytes4(keccak256('totalSupply()')) ^ bytes4(keccak256('balanceOf(address)')) ^ bytes4(keccak256('ownerOf(uint256)')) ^ bytes4(keccak256('approve(address,uint256)')) ^ bytes4(keccak256('transfer(address,uint256)')) ^ bytes4(keccak256('transferFrom(address,address,uint256)')) ^ bytes4(keccak256('tokensOfOwner(address)')) ^ bytes4(keccak256('tokenMetadata(uint256,string)')); /// @notice Introspection interface as per ERC-165 (https://github.com/ethereum/EIPs/issues/165). /// Returns true for any standardized interfaces implemented by this contract. We implement /// ERC-165 (obviously!) and ERC-721. function supportsInterface(bytes4 _interfaceID) external view returns (bool) { // DEBUG ONLY //require((InterfaceSignature_ERC165 == 0x01ffc9a7) && (InterfaceSignature_ERC721 == 0x9a20483d)); return ((_interfaceID == InterfaceSignature_ERC165) || (_interfaceID == InterfaceSignature_ERC721)); } /// @dev Set the address of the sibling contract that tracks metadata. /// CEO only. function setMetadataAddress(address _contractAddress) public onlyCEO { erc721Metadata = ERC721Metadata(_contractAddress); } // Internal utility functions: These functions all assume that their input arguments // are valid. We leave it to public methods to sanitize their inputs and follow // the required logic. /// @dev Checks if a given address is the current owner of a particular Content. /// @param _claimant the address we are validating against. /// @param _tokenId content id, only valid when > 0 function _owns(address _claimant, uint256 _tokenId) internal view returns (bool) { return contentIndexToOwner[_tokenId] == _claimant; } /// @dev Checks if a given address currently has transferApproval for a particular Content. /// @param _claimant the address we are confirming kitten is approved for. /// @param _tokenId kitten id, only valid when > 0 /* function _approvedFor(address _claimant, uint256 _tokenId) internal view returns (bool) { return contentIndexToApproved[_tokenId] == _claimant; } /// @dev Marks an address as being approved for transferFrom(), overwriting any previous /// approval. Setting _approved to address(0) clears all transfer approval. /// NOTE: _approve() does NOT send the Approval event. This is intentional because /// _approve() and transferFrom() are used together for putting Content on auction, and /// there is no value in spamming the log with Approval events in that case. function _approve(uint256 _tokenId, address _approved) internal { contentIndexToApproved[_tokenId] = _approved; } */ /// @notice Returns the number of Content owned by a specific address. /// @param _owner The owner address to check. /// @dev Required for ERC-721 compliance function balanceOf(address _owner) public view returns (uint256 count) { return ownershipTokenCount[_owner]; } function transfer( address _to, uint256 _tokenId ) external { // Safety check to prevent against an unexpected 0x0 default. require(_to != address(0)); // Disallow transfers to this contract to prevent accidental misuse. // The contract should never own any kitties (except very briefly // after a gen0 cat is created and before it goes on auction). require(_to != address(this)); // Disallow transfers to the auction contracts to prevent accidental // misuse. Auction contracts should only take ownership of kitties // through the allow + transferFrom flow. //require(_to != address(saleAuction)); //require(_to != address(siringAuction)); // You can only send your own cat. require(_owns(msg.sender, _tokenId)); // Reassign ownership, clear pending approvals, emit Transfer event. _transfer(msg.sender, _to, _tokenId); } /// @notice Grant another address the right to transfer a specific Kitty via /// transferFrom(). This is the preferred flow for transfering NFTs to contracts. /// @param _to The address to be granted transfer approval. Pass address(0) to /// clear all approvals. /// @param _tokenId The ID of the Kitty that can be transferred if this call succeeds. /// @dev Required for ERC-721 compliance. function approve( address _to, uint256 _tokenId ) external { // Only an owner can grant transfer approval. require(_owns(msg.sender, _tokenId)); // Register the approval (replacing any previous approval). //_approve(_tokenId, _to); // Emit approval event. Approval(msg.sender, _to, _tokenId); } /// @notice Transfer a Kitty owned by another address, for which the calling address /// has previously been granted transfer approval by the owner. /// @param _from The address that owns the Kitty to be transfered. /// @param _to The address that should take ownership of the Kitty. Can be any address, /// including the caller. /// @param _tokenId The ID of the Kitty to be transferred. /// @dev Required for ERC-721 compliance. function transferFrom( address _from, address _to, uint256 _tokenId ) external { // Safety check to prevent against an unexpected 0x0 default. require(_to != address(0)); // Disallow transfers to this contract to prevent accidental misuse. // The contract should never own any kitties (except very briefly // after a gen0 cat is created and before it goes on auction). require(_to != address(this)); // Check for approval and valid ownership //require(_approvedFor(msg.sender, _tokenId)); require(_owns(_from, _tokenId)); // Reassign ownership (also clears pending approvals and emits Transfer event). _transfer(_from, _to, _tokenId); } /// @notice Returns the total number of Content currently in existence. /// @dev Required for ERC-721 compliance. function totalSupply() public view returns (uint) { return contents.length - 1; } /// @notice Returns the address currently assigned ownership of a given content. /// @dev Required for ERC-721 compliance. function ownerOf(uint256 _tokenId) external view returns (address owner) { owner = contentIndexToOwner[_tokenId]; require(owner != address(0)); } /// @notice Returns a list of all Kitty IDs assigned to an address. /// @param _owner The owner whose Kitties we are interested in. /// @dev This method MUST NEVER be called by smart contract code. First, it's fairly /// expensive (it walks the entire Kitty array looking for cats belonging to owner), /// but it also returns a dynamic array, which is only supported for web3 calls, and /// not contract-to-contract calls. function tokensOfOwner(address _owner) external view returns(uint256[] ownerTokens) { uint256 tokenCount = balanceOf(_owner); if (tokenCount == 0) { // Return an empty array return new uint256[](0); } else { uint256[] memory result = new uint256[](tokenCount); uint256 totalContentReg = totalSupply(); uint256 resultIndex = 0; // We count on the fact that all cats have IDs starting at 1 and increasing // sequentially up to the totalCat count. uint256 totalContentId; for (totalContentId = 1; totalContentId <= totalContentReg; totalContentId++) { if (contentIndexToOwner[totalContentId] == _owner) { result[resultIndex] = totalContentId; resultIndex++; } } return result; } } /// @dev Adapted from memcpy() by @arachnid (Nick Johnson <arachnid@notdot.net>) /// This method is licenced under the Apache License. /// Ref: https://github.com/Arachnid/solidity-stringutils/blob/2f6ca9accb48ae14c66f1437ec50ed19a0616f78/strings.sol function _memcpy(uint _dest, uint _src, uint _len) private view { // Copy word-length chunks while possible for(; _len >= 32; _len -= 32) { assembly { mstore(_dest, mload(_src)) } _dest += 32; _src += 32; } // Copy remaining bytes uint256 mask = 256 ** (32 - _len) - 1; assembly { let srcpart := and(mload(_src), not(mask)) let destpart := and(mload(_dest), mask) mstore(_dest, or(destpart, srcpart)) } } /// @dev Adapted from toString(slice) by @arachnid (Nick Johnson <arachnid@notdot.net>) /// This method is licenced under the Apache License. /// Ref: https://github.com/Arachnid/solidity-stringutils/blob/2f6ca9accb48ae14c66f1437ec50ed19a0616f78/strings.sol function _toString(bytes32[4] _rawBytes, uint256 _stringLength) private view returns (string) { var outputString = new string(_stringLength); uint256 outputPtr; uint256 bytesPtr; assembly { outputPtr := add(outputString, 32) bytesPtr := _rawBytes } _memcpy(outputPtr, bytesPtr, _stringLength); return outputString; } /// @notice Returns a URI pointing to a metadata package for this token conforming to /// ERC-721 (https://github.com/ethereum/EIPs/issues/721) /// @param _tokenId The ID number of the Kitty whose metadata should be returned. function tokenMetadata(uint256 _tokenId, string _preferredTransport) external view returns (string infoUrl) { require(erc721Metadata != address(0)); bytes32[4] memory buffer; uint256 count; (buffer, count) = erc721Metadata.getMetadata(_tokenId, _preferredTransport); return _toString(buffer, count); } } /* /// contract ContentSales is ContentOwnership { /// @dev Set the cooldownEndTime for the given Kitty, based on its current cooldownIndex. /// Also increments the cooldownIndex (unless it has hit the cap). /// @param _film A reference to the Content in storage which has been sold. function _triggerTerritoryTransfer(Content storage _film) internal { // Compute an estimation of the cooldown time in blocks (based on current cooldownIndex). _film.territories[] = _territories; saleTerritories = _territories; } /// @dev Set the cooldownEndTime for the given Kitty, based on its current cooldownIndex. /// Also increments the cooldownIndex (unless it has hit the cap). /// @param _film A reference to the Content in storage which has been sold. function _triggerMediaTransfer(Content storage _film) internal { // Compute an estimation of the cooldown time in blocks (based on current cooldownIndex). _film.medias[] = _medias; saleMedias = _medias; } // maybe remove medias/territories/update/transfer original coin to buyer. create new coin for the owner since it can use msg.sender... }*/
0.4.18