// http://blockchaindev.kr/models/content/67 // https://ethfiddle.com/09YbyJRfiI // https://medium.com/@ihcho131313/이더리움에서-크립토키티-스타일-게임을-만드는-방법-8113372e65e4 // http://solidity.readthedocs.io/en/v0.4.24/types.html pragma solidity ^0.4.21; /// SafeMath library library SafeMath { /** * @dev Multiplies two numbers, throws on overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256) { if (a == 0) { return 0; } uint256 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 c; } /** * @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) { uint256 c = a + b; assert(c >= a); return c; } } /// Ownable contract Ownable { address public owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); function Ownable() public { owner = msg.sender; } 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) public onlyOwner { require(newOwner != address(0)); emit OwnershipTransferred(owner, newOwner); owner = newOwner; } } /// Suljomdao CEO/COO only Access modifier contract SulAccessControl { event ContractUpgrade(address newContract); address public ceoAddress; address public cooAddress; bool public paused = false; modifier onlyCLevel() { require( // codemath & Account 4 eth address msg.sender == ceoAddress || msg.sender == cooAddress ); _; } modifier onlyCEO() { require(msg.sender == ceoAddress); _; } modifier onlyCOO() { require(msg.sender == cooAddress); _; } function setCEO(address _newCEO) external onlyCEO { require(_newCEO != address(0)); ceoAddress = _newCEO; } function setCOO(address _newCOO) external onlyCOO { require(_newCOO != address(0)); cooAddress = _newCOO; } modifier whenNotPaused() { require(!paused); _; } modifier whenPaused { require(paused); _; } function pause() external onlyCLevel whenNotPaused { paused = true; } function unpause() public onlyCEO whenPaused { paused = false; } } /// ERC721 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); } /// Suljomdao Base contract contract SulBase is SulAccessControl{ event Make(address owner, string sulName ,uint256 sulId, uint256 price, uint256 IMGindex, uint256 gens, bool sale); event Transfer(address from, address to, uint256 tokenId); /// string sulName is specific drink; struct Sul { uint256 barcode; uint64 generateTime; string sulName; uint256 price; uint256 IMGindex; uint256 gens; bool sale; } Sul[] suls; mapping(uint256 => address) public SulIndexToOwner; mapping(address => uint256) public ownershipTokenCount; mapping(uint256 => address) public SulIndexToApproved; function _transfer(address _from, address _to, uint256 _tokenId) internal { ownershipTokenCount[_to]++; SulIndexToOwner[_tokenId] = _to; if (_from != address(0)) { ownershipTokenCount[_from]--; delete SulIndexToApproved[_tokenId]; } emit Transfer(_from, _to, _tokenId); } function _createSul(uint256 _barcode,string _sulName,uint256 _price, uint256 _IMGindex, uint256 _gens, address _owner, bool _sale) internal returns(uint) { Sul memory _sul = Sul({ barcode: _barcode, sulName: _sulName, generateTime: uint64(now), price: _price, IMGindex: _IMGindex, gens: _gens, sale: _sale }); uint256 newSulId = suls.push(_sul) - 1; require(newSulId == uint256(uint32(newSulId))); ///event emit Make(_owner, _sulName, newSulId, _price, _IMGindex, _gens, _sale); /// This will assign ownership, and also emit the Transfer event as /// per ERC721 draft _transfer(0, _owner, newSulId); return newSulId; } function CEOmakeSul(string _sulName, uint256 _price, uint256 _IMGindex, uint256 _gens) public whenNotPaused returns(uint256){ require(msg.sender == ceoAddress); uint256 sulId = _createSul( uint256( keccak256(_sulName) ) + uint256(_gens), _sulName, _price, _IMGindex, _gens, ceoAddress, true ); return sulId; } function Ingredient(string _sulName, uint256 _price, uint256 _IMGindex, uint256 _gens) internal whenNotPaused returns(uint256) { uint256 sulId = _createSul( uint256( keccak256(_sulName) ) + uint256(_gens), _sulName, _price, _IMGindex, _gens, ceoAddress, false ); return sulId; } function getSul(uint256 _id) public view returns ( uint256 barcode, string sulName, uint256 generateTime, uint256 price, uint256 IMGindex, uint256 gens, bool sale ){ Sul storage sul = suls[_id]; barcode = uint256(sul.barcode); sulName = string(sul.sulName); generateTime = uint256(sul.generateTime); price = uint256(sul.price); IMGindex = uint256(sul.IMGindex); gens = uint256(sul.gens); sale = bool(sul.sale); } function _approve(uint256 _tokenId, address _approved) internal { SulIndexToApproved[_tokenId] = _approved; } function _BidSul(uint[] _tokenIdSet) public payable{ // validate sum of price uint p=0; uint SumOfPrice = 0; for(p;p<_tokenIdSet.length;p++){ Sul memory sulp = suls[_tokenIdSet[p]]; SumOfPrice+=sulp.price; } require(msg.value == SumOfPrice); // validate sum of price uint e=0; for(e; e<_tokenIdSet.length; e++){ Sul storage sul = suls[_tokenIdSet[e]]; uint256 price = uint256(sul.price); uint256 Newgens = sul.gens+1; sul.gens = Newgens; sul.price = price + (price * 5) / 1000; string sulName = string(sul.sulName); uint256 IMGindex = uint256(sul.IMGindex); uint256 newGenIncredient = Ingredient(sulName, price, IMGindex, Newgens); _approve(newGenIncredient, msg.sender); } } } /// @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; } } } contract SulJom4DalLaGu7 is SulBase, ERC721 { string public constant name = "SulJomDaO"; string public constant symbol = "SUL"; // The contract that will return sul metadata 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)')); 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); } /// @dev Checks if a given address is the current owner of a particular Kitty. /// @param _claimant the address we are validating against. /// @param _tokenId kitten id, only valid when > 0 function _owns(address _claimant, uint256 _tokenId) internal view returns (bool) { return SulIndexToOwner[_tokenId] == _claimant; } function _approvedFor(address _claimant, uint256 _tokenId) internal view returns (bool) { return SulIndexToApproved[_tokenId] == _claimant; } function _approve(uint256 _tokenId, address _approved) internal { SulIndexToApproved[_tokenId] = _approved; } function balanceOf(address _owner) public view returns (uint256 count) { return ownershipTokenCount[_owner]; } /// @notice Transfers a SUL to another address. If transferring to a smart /// contract be VERY CAREFUL to ensure that it is aware of ERC-721 (or /// CryptoKitties specifically) or your Kitty may be lost forever. Seriously. /// @param _to The address of the recipient, can be a user or contract. /// @param _tokenId The ID of the Kitty to transfer. /// @dev Required for ERC-721 compliance. function transfer( address _to, uint256 _tokenId ) external whenNotPaused { // 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. // 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); } function approve( address _to, uint256 _tokenId ) external whenNotPaused { // 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. emit 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 whenNotPaused { // 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 SUL currently in existence. /// @dev Required for ERC-721 compliance. function totalSupply() public view returns (uint) { return suls.length - 1; } /// @notice Returns the address currently assigned ownership of a given SUL. /// @dev Required for ERC-721 compliance. function ownerOf(uint256 _tokenId) external view returns (address owner) { owner = SulIndexToOwner[_tokenId]; require(owner != address(0)); } /// @notice Returns a list of all SUL IDs assigned to an address. /// @param _owner The owner whose suls we are interested in. /// @dev This method MUST NEVER be called by smart contract code. First, it's fairly /// expensive (it walks the entire Sul 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 totalSuls = 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 sulId; for (sulId = 1; sulId <= totalSuls; sulId++) { if (SulIndexToOwner[sulId] == _owner) { result[resultIndex] = sulId; resultIndex++; } } return result; } } 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); } function salesOfSuls(address _owner) external view returns(uint256[] salesSuls) { require(msg.sender == ceoAddress); uint256 tokenCount = balanceOf(_owner); if (tokenCount == 0) { // Return an empty array return new uint256[](0); } else { uint256[] memory result = new uint256[](tokenCount); uint256 totalSuls = 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 sulId; for (sulId = 1; sulId <= totalSuls; sulId++) { if (SulIndexToOwner[sulId] == _owner) { result[resultIndex] = sulId; resultIndex++; } } return result; } } } contract Pausable is Ownable { event Pause(); event Unpause(); bool public paused = false; /** * @dev modifier to allow actions only when the contract IS paused */ modifier whenNotPaused() { require(!paused); _; } /** * @dev modifier to allow actions only when the contract IS NOT paused */ modifier whenPaused { require(paused); _; } /** * @dev called by the owner to pause, triggers stopped state */ function pause() onlyOwner whenNotPaused returns (bool) { paused = true; emit Pause(); return true; } /** * @dev called by the owner to unpause, returns to normal state */ function unpause() onlyOwner whenPaused returns (bool) { paused = false; emit Unpause(); return true; } }
0.4.21