Transaction Hash:
Block:
6454180 at Oct-04-2018 09:39:55 PM +UTC
Transaction Fee:
0.0002541546 ETH
$0.48
Gas Used:
60,513 Gas / 4.2 Gwei
Emitted Events:
96 |
BlockchainCutiesCore.SignUsed( signId=50019858, sender=[Sender] 0x4232acc4e999a5f1bfa30472211c51238d63c93e )
|
Account State Difference:
Address | Before | After | State Difference | ||
---|---|---|---|---|---|
0x4232acC4...38D63c93e |
0.0100198558 Eth
Nonce: 36
|
0.0097657012 Eth
Nonce: 37
| 0.0002541546 | ||
0xD73bE539...89aBC6Bbe | |||||
0xEA674fdD...16B898ec8
Miner
| (Ethermine) | 526.865575351848565414 Eth | 526.865829506448565414 Eth | 0.0002541546 |
Execution Trace
BlockchainCutiesCore.runPluginSigned( _pluginAddress=0x3D2BB0f9Fa7133799c0FA8E9B7F8CC83d0e4086d, _signId=50019858, _cutieId=0, _value=0, _parameter=0, _v=27, _r=53BA6C0D306A1874E20B05DB51FB903824D9B517C8F707E93ABA5542C8A4AFFA, _s=51A09D808F96906ACB231DC0AE6810C15F7B41B5B9E315232E912AED8D1B46E9 )

-
Null: 0x000...001.9ab8dbea( )
-
Lottery.runSigned( 0, 0, 0x4232acC4e999A5F1BFA30472211C51238D63c93e )
runPluginSigned[BlockchainCutiesCore (ln:983)]
_isOwner[BlockchainCutiesCore (ln:1000)]
isValidSignature[BlockchainCutiesCore (ln:1009)]
getSigner[BlockchainCutiesCore (ln:977)]
hashArguments[BlockchainCutiesCore (ln:958)]
ecrecover[BlockchainCutiesCore (ln:959)]
SignUsed[BlockchainCutiesCore (ln:1012)]
value[BlockchainCutiesCore (ln:1016)]
File 1 of 2: BlockchainCutiesCore
File 2 of 2: Lottery
pragma solidity ^0.4.20; /// BlockchainCuties: Collectible and breedable cuties on the Ethereum blockchain. /// https://blockchaincuties.co/ /// @title defined the interface that will be referenced in main Cutie contract contract GeneMixerInterface { /// @dev simply a boolean to indicate this is the contract we expect to be function isGeneMixer() external pure returns (bool); /// @dev given genes of cutie 1 & 2, return a genetic combination - may have a random factor /// @param genes1 genes of mom /// @param genes2 genes of dad /// @return the genes that are supposed to be passed down the child function mixGenes(uint256 genes1, uint256 genes2) public view returns (uint256); function canBreed(uint40 momId, uint256 genes1, uint40 dadId, uint256 genes2) public view returns (bool); } /// @author https://BlockChainArchitect.iocontract Bank is CutiePluginBase contract PluginInterface { /// @dev simply a boolean to indicate this is the contract we expect to be function isPluginInterface() public pure returns (bool); function onRemove() public; /// @dev Begins new feature. /// @param _cutieId - ID of token to auction, sender must be owner. /// @param _parameter - arbitrary parameter /// @param _seller - Old owner, if not the message sender function run( uint40 _cutieId, uint256 _parameter, address _seller ) public payable; /// @dev Begins new feature, approved and signed by COO. /// @param _cutieId - ID of token to auction, sender must be owner. /// @param _parameter - arbitrary parameter function runSigned( uint40 _cutieId, uint256 _parameter, address _owner ) external payable; function withdraw() public; } /// @title Auction Market for Blockchain Cuties. /// @author https://BlockChainArchitect.io contract MarketInterface { function withdrawEthFromBalance() external; function createAuction(uint40 _cutieId, uint128 _startPrice, uint128 _endPrice, uint40 _duration, address _seller) public payable; function bid(uint40 _cutieId) public payable; function cancelActiveAuctionWhenPaused(uint40 _cutieId) public; function getAuctionInfo(uint40 _cutieId) public view returns ( address seller, uint128 startPrice, uint128 endPrice, uint40 duration, uint40 startedAt, uint128 featuringFee ); } /// @title BlockchainCuties: Collectible and breedable cuties on the Ethereum blockchain. /// @author https://BlockChainArchitect.io /// @dev This is the BlockchainCuties configuration. It can be changed redeploying another version. contract ConfigInterface { function isConfig() public pure returns (bool); function getCooldownIndexFromGeneration(uint16 _generation) public view returns (uint16); function getCooldownEndTimeFromIndex(uint16 _cooldownIndex) public view returns (uint40); function getCooldownIndexCount() public view returns (uint256); function getBabyGen(uint16 _momGen, uint16 _dadGen) public pure returns (uint16); function getTutorialBabyGen(uint16 _dadGen) public pure returns (uint16); function getBreedingFee(uint40 _momId, uint40 _dadId) public pure returns (uint256); } /// @dev Note: the ERC-165 identifier for this interface is 0xf0b9e5ba interface ERC721TokenReceiver { /// @notice Handle the receipt of an NFT /// @dev The ERC721 smart contract calls this function on the recipient /// after a `transfer`. This function MAY throw to revert and reject the /// transfer. This function MUST use 50,000 gas or less. Return of other /// than the magic value MUST result in the transaction being reverted. /// Note: the contract address is always the message sender. /// @param _from The sending address /// @param _tokenId The NFT identifier which is being transfered /// @param data Additional data with no specified format /// @return `bytes4(keccak256("onERC721Received(address,uint256,bytes)"))` /// unless throwing function onERC721Received(address _from, uint256 _tokenId, bytes data) external returns(bytes4); } /// @title BlockchainCuties: Collectible and breedable cuties on the Ethereum blockchain. /// @author https://BlockChainArchitect.io /// @dev This is the main BlockchainCuties contract. For separated logical sections the code is divided in // several separately-instantiated sibling contracts that handle auctions and the genetic combination algorithm. // By keeping auctions separate it is possible to upgrade them without disrupting the main contract that tracks // the ownership of the cutie. The genetic combination algorithm is kept separate so that all of the rest of the // code can be open-sourced. // The contracts: // // - BlockchainCuties: The fundamental code, including main data storage, constants and data types, as well as // internal functions for managing these items ans ERC-721 implementation. // Various addresses and constraints for operations can be executed only by specific roles - // Owner, Operator and Parties. // Methods for interacting with additional features (Plugins). // The methods for breeding and keeping track of breeding offers, relies on external genetic combination // contract. // Public methods for auctioning or bidding or breeding. // // - SaleMarket and BreedingMarket: The actual auction functionality is handled in two sibling contracts - one // for sales and one for breeding. Auction creation and bidding is mostly mediated through this side of // the core contract. // // - Effects: Contracts allow to use item effects on cuties, implemented as plugins. Items are not stored in // blockchain to not overload Ethereum network. Operator generates signatures, and Plugins check it // and perform effect. // // - ItemMarket: Plugin contract used to transfer money from buyer to seller. // // - Bank: Plugin contract used to receive payments for payed features. contract BlockchainCutiesCore /*is ERC721, CutieCoreInterface*/ { /// @notice A descriptive name for a collection of NFTs in this contract function name() external pure returns (string _name) { return "BlockchainCuties"; } /// @notice An abbreviated name for NFTs in this contract function symbol() external pure returns (string _symbol) { return "BC"; } /// @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. /// @return `true` if the contract implements `interfaceID` and /// `interfaceID` is not 0xffffffff, `false` otherwise function supportsInterface(bytes4 interfaceID) external pure returns (bool) { return interfaceID == 0x6466353c || interfaceID == bytes4(keccak256('supportsInterface(bytes4)')); } event Transfer(address indexed _from, address indexed _to, uint256 _tokenId); event Approval(address indexed _owner, address indexed _approved, uint256 _tokenId); event ApprovalForAll(address indexed _owner, address indexed _operator, bool _approved); /// @dev The Birth event is fired as soon as a new cutie is created. This /// is any time a cutie comes into existence through the giveBirth method, as well as /// when a new gen0 cutie is created. event Birth(address indexed owner, uint40 cutieId, uint40 momId, uint40 dadId, uint256 genes); /// @dev This struct represents a blockchain Cutie. It was ensured that struct fits well into /// exactly two 256-bit words. The order of the members in this structure /// matters because of the Ethereum byte-packing rules. /// Reference: http://solidity.readthedocs.io/en/develop/miscellaneous.html struct Cutie { // The Cutie's genetic code is in these 256-bits. Cutie's genes never change. uint256 genes; // The timestamp from the block when this cutie was created. uint40 birthTime; // The minimum timestamp after which the cutie can start breeding // again. uint40 cooldownEndTime; // The cutie's parents ID is set to 0 for gen0 cuties. // Because of using 32-bit unsigned integers the limit is 4 billion cuties. // Current Ethereum annual limit is about 500 million transactions. uint40 momId; uint40 dadId; // Set the index in the cooldown array (see below) that means // the current cooldown duration for this Cutie. Starts at 0 // for gen0 cats, and is initialized to floor(generation/2) for others. // Incremented by one for each successful breeding, regardless // of being cutie mom or cutie dad. uint16 cooldownIndex; // The "generation number" of the cutie. Cutioes minted by the contract // for sale are called "gen0" with generation number of 0. All other cuties' // generation number is the larger of their parents' two generation // numbers, plus one (i.e. max(mom.generation, dad.generation) + 1) uint16 generation; // Some optional data used by external contracts // Cutie struct is 2x256 bits long. uint64 optional; } /// @dev An array containing the Cutie struct for all Cuties in existence. The ID /// of each cutie is actually an index into this array. ID 0 is the parent /// of all generation 0 cats, and both parents to itself. It is an invalid genetic code. Cutie[] public cuties; /// @dev A mapping from cutie IDs to the address that owns them. All cuties have /// some valid owner address, even gen0 cuties are created with a non-zero owner. mapping (uint40 => address) public cutieIndexToOwner; // @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 CutieIDs to an address that has been approved to call /// transferFrom(). A Cutie can have one approved address for transfer /// at any time. A zero value means that there is no outstanding approval. mapping (uint40 => address) public cutieIndexToApproved; /// @dev A mapping from CutieIDs to an address that has been approved to use /// this Cutie for breeding via breedWith(). A Cutie can have one approved /// address for breeding at any time. A zero value means that there is no outstanding approval. mapping (uint40 => address) public sireAllowedToAddress; /// @dev The address of the Market contract used to sell cuties. This /// contract used both peer-to-peer sales and the gen0 sales that are /// initiated each 15 minutes. MarketInterface public saleMarket; /// @dev The address of a custom Market subclassed contract used for breeding /// auctions. Is to be separated from saleMarket as the actions taken on success /// after a sales and breeding auction are quite different. MarketInterface public breedingMarket; // Modifiers to check that inputs can be safely stored with a certain // number of bits. modifier canBeStoredIn40Bits(uint256 _value) { require(_value <= 0xFFFFFFFFFF); _; } /// @notice Returns the total number of Cuties in existence. /// @dev Required for ERC-721 compliance. function totalSupply() external view returns (uint256) { return cuties.length - 1; } /// @notice Returns the total number of Cuties in existence. /// @dev Required for ERC-721 compliance. function _totalSupply() internal view returns (uint256) { return cuties.length - 1; } // Internal utility functions assume that their input arguments // are valid. Public methods sanitize their inputs and follow // the required logic. /// @dev Checks if a given address is the current owner of a certain Cutie. /// @param _claimant the address we are validating against. /// @param _cutieId cutie id, only valid when > 0 function _isOwner(address _claimant, uint40 _cutieId) internal view returns (bool) { return cutieIndexToOwner[_cutieId] == _claimant; } /// @dev Checks if a given address currently has transferApproval for a certain Cutie. /// @param _claimant the address we are confirming the cutie is approved for. /// @param _cutieId cutie id, only valid when > 0 function _approvedFor(address _claimant, uint40 _cutieId) internal view returns (bool) { return cutieIndexToApproved[_cutieId] == _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 done on purpose: /// _approve() and transferFrom() are used together for putting Cuties on auction. /// There is no value in spamming the log with Approval events in that case. function _approve(uint40 _cutieId, address _approved) internal { cutieIndexToApproved[_cutieId] = _approved; } /// @notice Returns the number of Cuties owned by a specific address. /// @param _owner The owner address to check. /// @dev Required for ERC-721 compliance function balanceOf(address _owner) external view returns (uint256 count) { return ownershipTokenCount[_owner]; } /// @notice Transfers a Cutie to another address. When transferring to a smart /// contract, ensure that it is aware of ERC-721 (or /// BlockchainCuties specifically), otherwise the Cutie may be lost forever. /// @param _to The address of the recipient, can be a user or contract. /// @param _cutieId The ID of the Cutie to transfer. /// @dev Required for ERC-721 compliance. function transfer(address _to, uint256 _cutieId) external whenNotPaused canBeStoredIn40Bits(_cutieId) { // You can only send your own cutie. require(_isOwner(msg.sender, uint40(_cutieId))); // Reassign ownership, clear pending approvals, emit Transfer event. _transfer(msg.sender, _to, uint40(_cutieId)); } /// @notice Grant another address the right to transfer a perticular Cutie via transferFrom(). /// This flow is preferred for transferring NFTs to contracts. /// @param _to The address to be granted transfer approval. Pass address(0) to clear all approvals. /// @param _cutieId The ID of the Cutie that can be transferred if this call succeeds. /// @dev Required for ERC-721 compliance. function approve(address _to, uint256 _cutieId) external whenNotPaused canBeStoredIn40Bits(_cutieId) { // Only cutie's owner can grant transfer approval. require(_isOwner(msg.sender, uint40(_cutieId))); // Registering approval replaces any previous approval. _approve(uint40(_cutieId), _to); // Emit approval event. emit Approval(msg.sender, _to, _cutieId); } /// @notice Transfers the ownership of an NFT from one address to another address. /// @dev Throws unless `msg.sender` is the current owner, an authorized /// operator, or the approved address for this NFT. Throws if `_from` is /// not the current owner. Throws if `_to` is the zero address. Throws if /// `_tokenId` is not a valid NFT. When transfer is complete, this function /// checks if `_to` is a smart contract (code size > 0). If so, it calls /// `onERC721Received` on `_to` and throws if the return value is not /// `bytes4(keccak256("onERC721Received(address,uint256,bytes)"))`. /// @param _from The current owner of the NFT /// @param _to The new owner /// @param _tokenId The NFT to transfer /// @param data Additional data with no specified format, sent in call to `_to` function safeTransferFrom(address _from, address _to, uint256 _tokenId, bytes data) external whenNotPaused canBeStoredIn40Bits(_tokenId) { require(_to != address(0)); require(_to != address(this)); require(_to != address(saleMarket)); require(_to != address(breedingMarket)); // Check for approval and valid ownership require(_approvedFor(msg.sender, uint40(_tokenId)) || _isApprovedForAll(_from, msg.sender)); require(_isOwner(_from, uint40(_tokenId))); // Reassign ownership, clearing pending approvals and emitting Transfer event. _transfer(_from, _to, uint40(_tokenId)); ERC721TokenReceiver (_to).onERC721Received(_from, _tokenId, data); } /// @notice Transfers the ownership of an NFT from one address to another address /// @dev This works identically to the other function with an extra data parameter, /// except this function just sets data to "" /// @param _from The current owner of the NFT /// @param _to The new owner /// @param _tokenId The NFT to transfer function safeTransferFrom(address _from, address _to, uint256 _tokenId) external whenNotPaused canBeStoredIn40Bits(_tokenId) { require(_to != address(0)); require(_to != address(this)); require(_to != address(saleMarket)); require(_to != address(breedingMarket)); // Check for approval and valid ownership require(_approvedFor(msg.sender, uint40(_tokenId)) || _isApprovedForAll(_from, msg.sender)); require(_isOwner(_from, uint40(_tokenId))); // Reassign ownership, clearing pending approvals and emitting Transfer event. _transfer(_from, _to, uint40(_tokenId)); } /// @notice Transfer a Cutie owned by another address, for which the calling address /// has been granted transfer approval by the owner. /// @param _from The address that owns the Cutie to be transfered. /// @param _to Any address, including the caller address, can take ownership of the Cutie. /// @param _tokenId The ID of the Cutie to be transferred. /// @dev Required for ERC-721 compliance. function transferFrom(address _from, address _to, uint256 _tokenId) external whenNotPaused canBeStoredIn40Bits(_tokenId) { // Check for approval and valid ownership require(_approvedFor(msg.sender, uint40(_tokenId)) || _isApprovedForAll(_from, msg.sender)); require(_isOwner(_from, uint40(_tokenId))); // Reassign ownership, clearing pending approvals and emitting Transfer event. _transfer(_from, _to, uint40(_tokenId)); } /// @notice Returns the address currently assigned ownership of a given Cutie. /// @dev Required for ERC-721 compliance. function ownerOf(uint256 _cutieId) external view canBeStoredIn40Bits(_cutieId) returns (address owner) { owner = cutieIndexToOwner[uint40(_cutieId)]; require(owner != address(0)); } /// @notice Returns the nth Cutie assigned to an address, with n specified by the /// _index argument. /// @param _owner The owner of the Cuties we are interested in. /// @param _index The zero-based index of the cutie within the owner's list of cuties. /// Must be less than balanceOf(_owner). /// @dev This method must not be called by smart contract code. It will almost /// certainly blow past the block gas limit once there are a large number of /// Cuties in existence. Exists only to allow off-chain queries of ownership. /// Optional method for ERC-721. function tokenOfOwnerByIndex(address _owner, uint256 _index) external view returns (uint256 cutieId) { uint40 count = 0; for (uint40 i = 1; i <= _totalSupply(); ++i) { if (cutieIndexToOwner[i] == _owner) { if (count == _index) { return i; } else { count++; } } } revert(); } /// @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 pure returns (uint256) { return _index; } /// @dev A mapping from Cuties owner (account) to an address that has been approved to call /// transferFrom() for all cuties, owned by owner. /// Only one approved address is permitted for each account for transfer /// at any time. A zero value means there is no outstanding approval. mapping (address => address) public addressToApprovedAll; /// @notice Enable or disable approval for a third party ("operator") to manage /// all your asset. /// @dev Emits the ApprovalForAll event /// @param _operator Address to add to the set of authorized operators. /// @param _approved True if the operators is approved, false to revoke approval function setApprovalForAll(address _operator, bool _approved) external { if (_approved) { addressToApprovedAll[msg.sender] = _operator; } else { delete addressToApprovedAll[msg.sender]; } emit ApprovalForAll(msg.sender, _operator, _approved); } /// @notice Get the approved address for a single NFT /// @dev Throws if `_tokenId` is not a valid NFT /// @param _tokenId The NFT to find the approved address for /// @return The approved address for this NFT, or the zero address if there is none function getApproved(uint256 _tokenId) external view canBeStoredIn40Bits(_tokenId) returns (address) { require(_tokenId <= _totalSupply()); if (cutieIndexToApproved[uint40(_tokenId)] != address(0)) { return cutieIndexToApproved[uint40(_tokenId)]; } address owner = cutieIndexToOwner[uint40(_tokenId)]; return addressToApprovedAll[owner]; } /// @notice Query if an address is an authorized operator for another address /// @param _owner The address that owns the NFTs /// @param _operator The address that acts on behalf of the owner /// @return True if `_operator` is an approved operator for `_owner`, false otherwise function isApprovedForAll(address _owner, address _operator) external view returns (bool) { return addressToApprovedAll[_owner] == _operator; } function _isApprovedForAll(address _owner, address _operator) internal view returns (bool) { return addressToApprovedAll[_owner] == _operator; } ConfigInterface public config; /// @dev Update the address of the config contract. /// @param _address An address of a ConfigInterface contract instance to be used from this point forward. function setConfigAddress(address _address) public onlyOwner { ConfigInterface candidateContract = ConfigInterface(_address); require(candidateContract.isConfig()); // Set the new contract address config = candidateContract; } function getCooldownIndexFromGeneration(uint16 _generation) internal view returns (uint16) { return config.getCooldownIndexFromGeneration(_generation); } /// @dev An internal method that creates a new cutie and stores it. This /// method does not check anything and should only be called when the /// input data is valid for sure. Will generate both a Birth event /// and a Transfer event. /// @param _momId The cutie ID of the mom of this cutie (zero for gen0) /// @param _dadId The cutie ID of the dad of this cutie (zero for gen0) /// @param _generation The generation number of this cutie, must be computed by caller. /// @param _genes The cutie's genetic code. /// @param _owner The initial owner of this cutie, must be non-zero (except for the unCutie, ID 0) function _createCutie( uint40 _momId, uint40 _dadId, uint16 _generation, uint16 _cooldownIndex, uint256 _genes, address _owner, uint40 _birthTime ) internal returns (uint40) { Cutie memory _cutie = Cutie({ genes: _genes, birthTime: _birthTime, cooldownEndTime: 0, momId: _momId, dadId: _dadId, cooldownIndex: _cooldownIndex, generation: _generation, optional: 0 }); uint256 newCutieId256 = cuties.push(_cutie) - 1; // Check if id can fit into 40 bits require(newCutieId256 <= 0xFFFFFFFFFF); uint40 newCutieId = uint40(newCutieId256); // emit the birth event emit Birth(_owner, newCutieId, _cutie.momId, _cutie.dadId, _cutie.genes); // This will assign ownership, as well as emit the Transfer event as // per ERC721 draft _transfer(0, _owner, newCutieId); return newCutieId; } /// @notice Returns all the relevant information about a certain cutie. /// @param _id The ID of the cutie of interest. function getCutie(uint40 _id) external view returns ( uint256 genes, uint40 birthTime, uint40 cooldownEndTime, uint40 momId, uint40 dadId, uint16 cooldownIndex, uint16 generation ) { Cutie storage cutie = cuties[_id]; genes = cutie.genes; birthTime = cutie.birthTime; cooldownEndTime = cutie.cooldownEndTime; momId = cutie.momId; dadId = cutie.dadId; cooldownIndex = cutie.cooldownIndex; generation = cutie.generation; } /// @dev Assigns ownership of a particular Cutie to an address. function _transfer(address _from, address _to, uint40 _cutieId) internal { // since the number of cuties is capped to 2^40 // there is no way to overflow this ownershipTokenCount[_to]++; // transfer ownership cutieIndexToOwner[_cutieId] = _to; // When creating new cuties _from is 0x0, but we cannot account that address. if (_from != address(0)) { ownershipTokenCount[_from]--; // once the cutie is transferred also clear breeding allowances delete sireAllowedToAddress[_cutieId]; // clear any previously approved ownership exchange delete cutieIndexToApproved[_cutieId]; } // Emit the transfer event. emit Transfer(_from, _to, _cutieId); } /// @dev For transferring a cutie owned by this contract to the specified address. /// Used to rescue lost cuties. (There is no "proper" flow where this contract /// should be the owner of any Cutie. This function exists for us to reassign /// the ownership of Cuties that users may have accidentally sent to our address.) /// @param _cutieId - ID of cutie /// @param _recipient - Address to send the cutie to function restoreCutieToAddress(uint40 _cutieId, address _recipient) public onlyOperator whenNotPaused { require(_isOwner(this, _cutieId)); _transfer(this, _recipient, _cutieId); } address ownerAddress; address operatorAddress; bool public paused = false; modifier onlyOwner() { require(msg.sender == ownerAddress); _; } function setOwner(address _newOwner) public onlyOwner { require(_newOwner != address(0)); ownerAddress = _newOwner; } modifier onlyOperator() { require(msg.sender == operatorAddress || msg.sender == ownerAddress); _; } function setOperator(address _newOperator) public onlyOwner { require(_newOperator != address(0)); operatorAddress = _newOperator; } modifier whenNotPaused() { require(!paused); _; } modifier whenPaused { require(paused); _; } function pause() public onlyOwner whenNotPaused { paused = true; } string public metadataUrlPrefix = "https://blockchaincuties.co/cutie/"; string public metadataUrlSuffix = ".svg"; /// @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 infoUrl) { return concat(toSlice(metadataUrlPrefix), toSlice(concat(toSlice(uintToString(_tokenId)), toSlice(metadataUrlSuffix)))); } function setMetadataUrl(string _metadataUrlPrefix, string _metadataUrlSuffix) public onlyOwner { metadataUrlPrefix = _metadataUrlPrefix; metadataUrlSuffix = _metadataUrlSuffix; } mapping(address => PluginInterface) public plugins; PluginInterface[] public pluginsArray; mapping(uint40 => address) public usedSignes; uint40 public minSignId; event GenesChanged(uint40 indexed cutieId, uint256 oldValue, uint256 newValue); event CooldownEndTimeChanged(uint40 indexed cutieId, uint40 oldValue, uint40 newValue); event CooldownIndexChanged(uint40 indexed cutieId, uint16 ololdValue, uint16 newValue); event GenerationChanged(uint40 indexed cutieId, uint16 oldValue, uint16 newValue); event OptionalChanged(uint40 indexed cutieId, uint64 oldValue, uint64 newValue); event SignUsed(uint40 signId, address sender); event MinSignSet(uint40 signId); /// @dev Sets the reference to the plugin contract. /// @param _address - Address of plugin contract. function addPlugin(address _address) public onlyOwner { PluginInterface candidateContract = PluginInterface(_address); // verify that a contract is what we expect require(candidateContract.isPluginInterface()); // Set the new contract address plugins[_address] = candidateContract; pluginsArray.push(candidateContract); } /// @dev Remove plugin and calls onRemove to cleanup function removePlugin(address _address) public onlyOwner { plugins[_address].onRemove(); delete plugins[_address]; uint256 kindex = 0; while (kindex < pluginsArray.length) { if (address(pluginsArray[kindex]) == _address) { pluginsArray[kindex] = pluginsArray[pluginsArray.length-1]; pluginsArray.length--; } else { kindex++; } } } /// @dev Put a cutie up for plugin feature. function runPlugin( address _pluginAddress, uint40 _cutieId, uint256 _parameter ) public whenNotPaused payable { // If cutie is already on any auction or in adventure, this will throw // because it will be owned by the other contract. // If _cutieId is 0, then cutie is not used on this feature. require(_cutieId == 0 || _isOwner(msg.sender, _cutieId)); require(address(plugins[_pluginAddress]) != address(0)); if (_cutieId > 0) { _approve(_cutieId, _pluginAddress); } // Plugin contract throws if inputs are invalid and clears // transfer after escrowing the cutie. plugins[_pluginAddress].run.value(msg.value)( _cutieId, _parameter, msg.sender ); } /// @dev Called from plugin contract when using items as effect function getGenes(uint40 _id) public view returns ( uint256 genes ) { Cutie storage cutie = cuties[_id]; genes = cutie.genes; } /// @dev Called from plugin contract when using items as effect function changeGenes( uint40 _cutieId, uint256 _genes) public whenNotPaused { // if caller is registered plugin contract require(address(plugins[msg.sender]) != address(0)); Cutie storage cutie = cuties[_cutieId]; if (cutie.genes != _genes) { emit GenesChanged(_cutieId, cutie.genes, _genes); cutie.genes = _genes; } } function getCooldownEndTime(uint40 _id) public view returns ( uint40 cooldownEndTime ) { Cutie storage cutie = cuties[_id]; cooldownEndTime = cutie.cooldownEndTime; } function changeCooldownEndTime( uint40 _cutieId, uint40 _cooldownEndTime) public whenNotPaused { require(address(plugins[msg.sender]) != address(0)); Cutie storage cutie = cuties[_cutieId]; if (cutie.cooldownEndTime != _cooldownEndTime) { emit CooldownEndTimeChanged(_cutieId, cutie.cooldownEndTime, _cooldownEndTime); cutie.cooldownEndTime = _cooldownEndTime; } } function getCooldownIndex(uint40 _id) public view returns ( uint16 cooldownIndex ) { Cutie storage cutie = cuties[_id]; cooldownIndex = cutie.cooldownIndex; } function changeCooldownIndex( uint40 _cutieId, uint16 _cooldownIndex) public whenNotPaused { require(address(plugins[msg.sender]) != address(0)); Cutie storage cutie = cuties[_cutieId]; if (cutie.cooldownIndex != _cooldownIndex) { emit CooldownIndexChanged(_cutieId, cutie.cooldownIndex, _cooldownIndex); cutie.cooldownIndex = _cooldownIndex; } } function changeGeneration( uint40 _cutieId, uint16 _generation) public whenNotPaused { require(address(plugins[msg.sender]) != address(0)); Cutie storage cutie = cuties[_cutieId]; if (cutie.generation != _generation) { emit GenerationChanged(_cutieId, cutie.generation, _generation); cutie.generation = _generation; } } function getGeneration(uint40 _id) public view returns (uint16 generation) { Cutie storage cutie = cuties[_id]; generation = cutie.generation; } function changeOptional( uint40 _cutieId, uint64 _optional) public whenNotPaused { require(address(plugins[msg.sender]) != address(0)); Cutie storage cutie = cuties[_cutieId]; if (cutie.optional != _optional) { emit OptionalChanged(_cutieId, cutie.optional, _optional); cutie.optional = _optional; } } function getOptional(uint40 _id) public view returns (uint64 optional) { Cutie storage cutie = cuties[_id]; optional = cutie.optional; } /// @dev Common function to be used also in backend function hashArguments( address _pluginAddress, uint40 _signId, uint40 _cutieId, uint128 _value, uint256 _parameter) public pure returns (bytes32 msgHash) { msgHash = keccak256(_pluginAddress, _signId, _cutieId, _value, _parameter); } /// @dev Common function to be used also in backend function getSigner( address _pluginAddress, uint40 _signId, uint40 _cutieId, uint128 _value, uint256 _parameter, uint8 _v, bytes32 _r, bytes32 _s ) public pure returns (address) { bytes32 msgHash = hashArguments(_pluginAddress, _signId, _cutieId, _value, _parameter); return ecrecover(msgHash, _v, _r, _s); } /// @dev Common function to be used also in backend function isValidSignature( address _pluginAddress, uint40 _signId, uint40 _cutieId, uint128 _value, uint256 _parameter, uint8 _v, bytes32 _r, bytes32 _s ) public view returns (bool) { return getSigner(_pluginAddress, _signId, _cutieId, _value, _parameter, _v, _r, _s) == operatorAddress; } /// @dev Put a cutie up for plugin feature with signature. /// Can be used for items equip, item sales and other features. /// Signatures are generated by Operator role. function runPluginSigned( address _pluginAddress, uint40 _signId, uint40 _cutieId, uint128 _value, uint256 _parameter, uint8 _v, bytes32 _r, bytes32 _s ) public whenNotPaused payable { // If cutie is already on any auction or in adventure, this will throw // as it will be owned by the other contract. // If _cutieId is 0, then cutie is not used on this feature. require(_cutieId == 0 || _isOwner(msg.sender, _cutieId)); require(address(plugins[_pluginAddress]) != address(0)); require (usedSignes[_signId] == address(0)); require (_signId >= minSignId); // value can also be zero for free calls require (_value <= msg.value); require (isValidSignature(_pluginAddress, _signId, _cutieId, _value, _parameter, _v, _r, _s)); usedSignes[_signId] = msg.sender; emit SignUsed(_signId, msg.sender); // Plugin contract throws if inputs are invalid and clears // transfer after escrowing the cutie. plugins[_pluginAddress].runSigned.value(_value)( _cutieId, _parameter, msg.sender ); } /// @dev Sets minimal signId, than can be used. /// All unused signatures less than signId will be cancelled on off-chain server /// and unused items will be transfered back to owner. function setMinSign(uint40 _newMinSignId) public onlyOperator { require (_newMinSignId > minSignId); minSignId = _newMinSignId; emit MinSignSet(minSignId); } event BreedingApproval(address indexed _owner, address indexed _approved, uint256 _tokenId); // Set in case the core contract is broken and an upgrade is required address public upgradedContractAddress; function isCutieCore() pure public returns (bool) { return true; } /// @notice Creates the main BlockchainCuties smart contract instance. function BlockchainCutiesCore() public { // Starts paused. paused = true; // the creator of the contract is the initial owner ownerAddress = msg.sender; // the creator of the contract is also the initial operator operatorAddress = msg.sender; // start with the mythical cutie 0 - so there are no generation-0 parent issues _createCutie(0, 0, 0, 0, uint256(-1), address(0), 0); } event ContractUpgrade(address newContract); /// @dev Aimed to mark the smart contract as upgraded if there is a crucial /// bug. This keeps track of the new contract and indicates that the new address is set. /// Updating to the new contract address is up to the clients. (This contract will /// be paused indefinitely if such an upgrade takes place.) /// @param _newAddress new address function setUpgradedAddress(address _newAddress) public onlyOwner whenPaused { require(_newAddress != address(0)); upgradedContractAddress = _newAddress; emit ContractUpgrade(upgradedContractAddress); } /// @dev Import cuties from previous version of Core contract. /// @param _oldAddress Old core contract address /// @param _fromIndex (inclusive) /// @param _toIndex (inclusive) function migrate(address _oldAddress, uint40 _fromIndex, uint40 _toIndex) public onlyOwner whenPaused { require(_totalSupply() + 1 == _fromIndex); BlockchainCutiesCore old = BlockchainCutiesCore(_oldAddress); for (uint40 i = _fromIndex; i <= _toIndex; i++) { uint256 genes; uint40 birthTime; uint40 cooldownEndTime; uint40 momId; uint40 dadId; uint16 cooldownIndex; uint16 generation; (genes, birthTime, cooldownEndTime, momId, dadId, cooldownIndex, generation) = old.getCutie(i); Cutie memory _cutie = Cutie({ genes: genes, birthTime: birthTime, cooldownEndTime: cooldownEndTime, momId: momId, dadId: dadId, cooldownIndex: cooldownIndex, generation: generation, optional: 0 }); cuties.push(_cutie); } } /// @dev Import cuties from previous version of Core contract (part 2). /// @param _oldAddress Old core contract address /// @param _fromIndex (inclusive) /// @param _toIndex (inclusive) function migrate2(address _oldAddress, uint40 _fromIndex, uint40 _toIndex, address saleAddress, address breedingAddress) public onlyOwner whenPaused { BlockchainCutiesCore old = BlockchainCutiesCore(_oldAddress); MarketInterface oldSaleMarket = MarketInterface(saleAddress); MarketInterface oldBreedingMarket = MarketInterface(breedingAddress); for (uint40 i = _fromIndex; i <= _toIndex; i++) { address owner = old.ownerOf(i); if (owner == saleAddress) { (owner,,,,,) = oldSaleMarket.getAuctionInfo(i); } if (owner == breedingAddress) { (owner,,,,,) = oldBreedingMarket.getAuctionInfo(i); } _transfer(0, owner, i); } } /// @dev Override unpause so it requires upgradedContractAddress not set, because then the contract was upgraded. function unpause() public onlyOwner whenPaused { require(upgradedContractAddress == address(0)); paused = false; } // Counts the number of cuties the contract owner has created. uint40 public promoCutieCreatedCount; uint40 public gen0CutieCreatedCount; uint40 public gen0Limit = 50000; uint40 public promoLimit = 5000; /// @dev Creates a new gen0 cutie with the given genes and /// creates an auction for it. function createGen0Auction(uint256 _genes, uint128 startPrice, uint128 endPrice, uint40 duration) public onlyOperator { require(gen0CutieCreatedCount < gen0Limit); uint40 cutieId = _createCutie(0, 0, 0, 0, _genes, address(this), uint40(now)); _approve(cutieId, saleMarket); saleMarket.createAuction( cutieId, startPrice, endPrice, duration, address(this) ); gen0CutieCreatedCount++; } function createPromoCutie(uint256 _genes, address _owner) public onlyOperator { require(promoCutieCreatedCount < promoLimit); if (_owner == address(0)) { _owner = operatorAddress; } promoCutieCreatedCount++; gen0CutieCreatedCount++; _createCutie(0, 0, 0, 0, _genes, _owner, uint40(now)); } /// @dev Put a cutie up for auction to be dad. /// Performs checks to ensure the cutie can be dad, then /// delegates to reverse auction. /// Optional money amount can be sent to contract to feature auction. /// Pricea are available on web. function createBreedingAuction( uint40 _cutieId, uint128 _startPrice, uint128 _endPrice, uint40 _duration ) public whenNotPaused payable { // Auction contract checks input sizes // If cutie is already on any auction, this will throw // because it will be owned by the auction contract. require(_isOwner(msg.sender, _cutieId)); require(canBreed(_cutieId)); _approve(_cutieId, breedingMarket); // breeding auction function is called if inputs are invalid and clears // transfer and sire approval after escrowing the cutie. breedingMarket.createAuction.value(msg.value)( _cutieId, _startPrice, _endPrice, _duration, msg.sender ); } /// @dev Sets the reference to the breeding auction. /// @param _breedingAddress - Address of breeding market contract. /// @param _saleAddress - Address of sale market contract. function setMarketAddress(address _breedingAddress, address _saleAddress) public onlyOwner { //require(address(breedingMarket) == address(0)); //require(address(saleMarket) == address(0)); breedingMarket = MarketInterface(_breedingAddress); saleMarket = MarketInterface(_saleAddress); } /// @dev Completes a breeding auction by bidding. /// Immediately breeds the winning mom with the dad on auction. /// @param _dadId - ID of the dad on auction. /// @param _momId - ID of the mom owned by the bidder. function bidOnBreedingAuction( uint40 _dadId, uint40 _momId ) public payable whenNotPaused returns (uint256) { // Auction contract checks input sizes require(_isOwner(msg.sender, _momId)); require(canBreed(_momId)); require(_canMateViaMarketplace(_momId, _dadId)); // Take breeding fee uint256 fee = getBreedingFee(_momId, _dadId); require(msg.value >= fee); // breeding auction will throw if the bid fails. breedingMarket.bid.value(msg.value - fee)(_dadId); return _breedWith(_momId, _dadId); } /// @dev Put a cutie up for auction. /// Does some ownership trickery for creating auctions in one transaction. /// Optional money amount can be sent to contract to feature auction. /// Pricea are available on web. function createSaleAuction( uint40 _cutieId, uint128 _startPrice, uint128 _endPrice, uint40 _duration ) public whenNotPaused payable { // Auction contract checks input sizes // If cutie is already on any auction, this will throw // because it will be owned by the auction contract. require(_isOwner(msg.sender, _cutieId)); _approve(_cutieId, saleMarket); // Sale auction throws if inputs are invalid and clears // transfer and sire approval after escrowing the cutie. saleMarket.createAuction.value(msg.value)( _cutieId, _startPrice, _endPrice, _duration, msg.sender ); } /// @dev The address of the sibling contract that is used to implement the genetic combination algorithm. GeneMixerInterface geneMixer; /// @dev Check if dad has authorized breeding with the mom. True if both dad /// and mom have the same owner, or if the dad has given breeding permission to /// the mom's owner (via approveBreeding()). function _isBreedingPermitted(uint40 _dadId, uint40 _momId) internal view returns (bool) { address momOwner = cutieIndexToOwner[_momId]; address dadOwner = cutieIndexToOwner[_dadId]; // Breeding is approved if they have same owner, or if the mom's owner was given // permission to breed with the dad. return (momOwner == dadOwner || sireAllowedToAddress[_dadId] == momOwner); } /// @dev Update the address of the genetic contract. /// @param _address An address of a GeneMixer contract instance to be used from this point forward. function setGeneMixerAddress(address _address) public onlyOwner { GeneMixerInterface candidateContract = GeneMixerInterface(_address); require(candidateContract.isGeneMixer()); // Set the new contract address geneMixer = candidateContract; } /// @dev Checks that a given cutie is able to breed. Requires that the /// current cooldown is finished (for dads) function _canBreed(Cutie _cutie) internal view returns (bool) { return _cutie.cooldownEndTime <= now; } /// @notice Grants approval to another user to sire with one of your Cuties. /// @param _addr The address that will be able to sire with your Cutie. Set to /// address(0) to clear all breeding approvals for this Cutie. /// @param _dadId A Cutie that you own that _addr will now be able to dad with. function approveBreeding(address _addr, uint40 _dadId) public whenNotPaused { require(_isOwner(msg.sender, _dadId)); sireAllowedToAddress[_dadId] = _addr; emit BreedingApproval(msg.sender, _addr, _dadId); } /// @dev Set the cooldownEndTime for the given Cutie, based on its current cooldownIndex. /// Also increments the cooldownIndex (unless it has hit the cap). /// @param _cutie A reference to the Cutie in storage which needs its timer started. function _triggerCooldown(uint40 _cutieId, Cutie storage _cutie) internal { // Compute the end of the cooldown time, based on current cooldownIndex uint40 oldValue = _cutie.cooldownIndex; _cutie.cooldownEndTime = config.getCooldownEndTimeFromIndex(_cutie.cooldownIndex); emit CooldownEndTimeChanged(_cutieId, oldValue, _cutie.cooldownEndTime); // Increment the breeding count. if (_cutie.cooldownIndex + 1 < config.getCooldownIndexCount()) { uint16 oldValue2 = _cutie.cooldownIndex; _cutie.cooldownIndex++; emit CooldownIndexChanged(_cutieId, oldValue2, _cutie.cooldownIndex); } } /// @notice Checks that a certain cutie is not /// in the middle of a breeding cooldown and is able to breed. /// @param _cutieId reference the id of the cutie, any user can inquire about it function canBreed(uint40 _cutieId) public view returns (bool) { require(_cutieId > 0); Cutie storage cutie = cuties[_cutieId]; return _canBreed(cutie); } /// @dev Check if given mom and dad are a valid mating pair. function _canPairMate( Cutie storage _mom, uint40 _momId, Cutie storage _dad, uint40 _dadId ) private view returns(bool) { // A Cutie can't breed with itself. if (_dadId == _momId) { return false; } // Cuties can't breed with their parents. if (_mom.momId == _dadId) { return false; } if (_mom.dadId == _dadId) { return false; } if (_dad.momId == _momId) { return false; } if (_dad.dadId == _momId) { return false; } // We can short circuit the sibling check (below) if either cat is // gen zero (has a mom ID of zero). if (_dad.momId == 0) { return true; } if (_mom.momId == 0) { return true; } // Cuties can't breed with full or half siblings. if (_dad.momId == _mom.momId) { return false; } if (_dad.momId == _mom.dadId) { return false; } if (_dad.dadId == _mom.momId) { return false; } if (_dad.dadId == _mom.dadId) { return false; } if (geneMixer.canBreed(_momId, _mom.genes, _dadId, _dad.genes)) { return true; } return false; } /// @notice Checks to see if two cuties can breed together (checks both /// ownership and breeding approvals, but does not check if both cuties are ready for /// breeding). /// @param _momId The ID of the proposed mom. /// @param _dadId The ID of the proposed dad. function canBreedWith(uint40 _momId, uint40 _dadId) public view returns(bool) { require(_momId > 0); require(_dadId > 0); Cutie storage mom = cuties[_momId]; Cutie storage dad = cuties[_dadId]; return _canPairMate(mom, _momId, dad, _dadId) && _isBreedingPermitted(_dadId, _momId); } /// @dev Internal check to see if a given dad and mom are a valid mating pair for /// breeding via market (this method doesn't check ownership and if mating is allowed). function _canMateViaMarketplace(uint40 _momId, uint40 _dadId) internal view returns (bool) { Cutie storage mom = cuties[_momId]; Cutie storage dad = cuties[_dadId]; return _canPairMate(mom, _momId, dad, _dadId); } function getBreedingFee(uint40 _momId, uint40 _dadId) public view returns (uint256) { return config.getBreedingFee(_momId, _dadId); } /// @notice Breed cuties that you own, or for which you /// have previously been given Breeding approval. Will either make your cutie give birth, or will /// fail. /// @param _momId The ID of the Cutie acting as mom (will end up give birth if successful) /// @param _dadId The ID of the Cutie acting as dad (will begin its breeding cooldown if successful) function breedWith(uint40 _momId, uint40 _dadId) public whenNotPaused payable returns (uint40) { // Caller must own the mom. require(_isOwner(msg.sender, _momId)); // Neither dad nor mom can be on auction during // breeding. // For mom: The caller of this function can't be the owner of the mom // because the owner of a Cutie on auction is the auction house, and the // auction house will never call breedWith(). // For dad: Similarly, a dad on auction will be owned by the auction house // and the act of transferring ownership will have cleared any outstanding // breeding approval. // Thus we don't need check if either cutie // is on auction. // Check that mom and dad are both owned by caller, or that the dad // has given breeding permission to caller (i.e. mom's owner). // Will fail for _dadId = 0 require(_isBreedingPermitted(_dadId, _momId)); // Check breeding fee require(getBreedingFee(_momId, _dadId) <= msg.value); // Grab a reference to the potential mom Cutie storage mom = cuties[_momId]; // Make sure mom's cooldown isn't active, or in the middle of a breeding cooldown require(_canBreed(mom)); // Grab a reference to the potential dad Cutie storage dad = cuties[_dadId]; // Make sure dad cooldown isn't active, or in the middle of a breeding cooldown require(_canBreed(dad)); // Test that these cuties are a valid mating pair. require(_canPairMate( mom, _momId, dad, _dadId )); return _breedWith(_momId, _dadId); } /// @dev Internal utility function to start breeding, assumes that all breeding /// requirements have been checked. function _breedWith(uint40 _momId, uint40 _dadId) internal returns (uint40) { // Grab a reference to the Cuties from storage. Cutie storage dad = cuties[_dadId]; Cutie storage mom = cuties[_momId]; // Trigger the cooldown for both parents. _triggerCooldown(_dadId, dad); _triggerCooldown(_momId, mom); // Clear breeding permission for both parents. delete sireAllowedToAddress[_momId]; delete sireAllowedToAddress[_dadId]; // Check that the mom is a valid cutie. require(mom.birthTime != 0); // Determine the higher generation number of the two parents uint16 babyGen = config.getBabyGen(mom.generation, dad.generation); // Call the gene mixing operation. uint256 childGenes = geneMixer.mixGenes(mom.genes, dad.genes); // Make the new cutie address owner = cutieIndexToOwner[_momId]; uint40 cutieId = _createCutie(_momId, _dadId, babyGen, getCooldownIndexFromGeneration(babyGen), childGenes, owner, mom.cooldownEndTime); // return the new cutie's ID return cutieId; } mapping(address => uint40) isTutorialPetUsed; /// @dev Completes a breeding tutorial cutie (non existing in blockchain) /// with auction by bidding. Immediately breeds with dad on auction. /// @param _dadId - ID of the dad on auction. function bidOnBreedingAuctionTutorial( uint40 _dadId ) public payable whenNotPaused returns (uint) { require(isTutorialPetUsed[msg.sender] == 0); // Take breeding fee uint256 fee = getBreedingFee(0, _dadId); require(msg.value >= fee); // breeding auction will throw if the bid fails. breedingMarket.bid.value(msg.value - fee)(_dadId); // Grab a reference to the Cuties from storage. Cutie storage dad = cuties[_dadId]; // Trigger the cooldown for parent. _triggerCooldown(_dadId, dad); // Clear breeding permission for parent. delete sireAllowedToAddress[_dadId]; uint16 babyGen = config.getTutorialBabyGen(dad.generation); // tutorial pet genome is zero uint256 childGenes = geneMixer.mixGenes(0x0, dad.genes); // tutorial pet id is zero uint40 cutieId = _createCutie(0, _dadId, babyGen, getCooldownIndexFromGeneration(babyGen), childGenes, msg.sender, 12); isTutorialPetUsed[msg.sender] = cutieId; // return the new cutie's ID return cutieId; } address party1address; address party2address; address party3address; address party4address; address party5address; /// @dev Setup project owners function setParties(address _party1, address _party2, address _party3, address _party4, address _party5) public onlyOwner { require(_party1 != address(0)); require(_party2 != address(0)); require(_party3 != address(0)); require(_party4 != address(0)); require(_party5 != address(0)); party1address = _party1; party2address = _party2; party3address = _party3; party4address = _party4; party5address = _party5; } /// @dev Reject all Ether which is not from game contracts from being sent here. function() external payable { require( msg.sender == address(saleMarket) || msg.sender == address(breedingMarket) || address(plugins[msg.sender]) != address(0) ); } /// @dev The balance transfer from the market and plugins contract /// to the CutieCore contract. function withdrawBalances() external { require( msg.sender == ownerAddress || msg.sender == operatorAddress); saleMarket.withdrawEthFromBalance(); breedingMarket.withdrawEthFromBalance(); for (uint32 i = 0; i < pluginsArray.length; ++i) { pluginsArray[i].withdraw(); } } /// @dev The balance transfer from CutieCore contract to project owners function withdrawEthFromBalance() external { require( msg.sender == party1address || msg.sender == party2address || msg.sender == party3address || msg.sender == party4address || msg.sender == party5address || msg.sender == ownerAddress || msg.sender == operatorAddress); require(party1address != 0); require(party2address != 0); require(party3address != 0); require(party4address != 0); require(party5address != 0); uint256 total = address(this).balance; party1address.transfer(total*105/1000); party2address.transfer(total*105/1000); party3address.transfer(total*140/1000); party4address.transfer(total*140/1000); party5address.transfer(total*510/1000); } /* * @title String & slice utility library for Solidity contracts. * @author Nick Johnson <[email protected]> * * @dev Functionality in this library is largely implemented using an * abstraction called a 'slice'. A slice represents a part of a string - * anything from the entire string to a single character, or even no * characters at all (a 0-length slice). Since a slice only has to specify * an offset and a length, copying and manipulating slices is a lot less * expensive than copying and manipulating the strings they reference. * * To further reduce gas costs, most functions on slice that need to return * a slice modify the original one instead of allocating a new one; for * instance, `s.split(".")` will return the text up to the first '.', * modifying s to only contain the remainder of the string after the '.'. * In situations where you do not want to modify the original slice, you * can make a copy first with `.copy()`, for example: * `s.copy().split(".")`. Try and avoid using this idiom in loops; since * Solidity has no memory management, it will result in allocating many * short-lived slices that are later discarded. * * Functions that return two slices come in two versions: a non-allocating * version that takes the second slice as an argument, modifying it in * place, and an allocating version that allocates and returns the second * slice; see `nextRune` for example. * * Functions that have to copy string data will return strings rather than * slices; these can be cast back to slices for further processing if * required. * * For convenience, some functions are provided with non-modifying * variants that create a new slice and return both; for instance, * `s.splitNew('.')` leaves s unmodified, and returns two values * corresponding to the left and right parts of the string. */ struct slice { uint _len; uint _ptr; } /* * @dev Returns a slice containing the entire string. * @param self The string to make a slice from. * @return A newly allocated slice containing the entire string. */ function toSlice(string self) internal pure returns (slice) { uint ptr; assembly { ptr := add(self, 0x20) } return slice(bytes(self).length, ptr); } function memcpy(uint dest, uint src, uint len) private pure { // Copy word-length chunks while possible for(; len >= 32; len -= 32) { assembly { mstore(dest, mload(src)) } dest += 32; src += 32; } // Copy remaining bytes uint 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 Returns a newly allocated string containing the concatenation of * `self` and `other`. * @param self The first slice to concatenate. * @param other The second slice to concatenate. * @return The concatenation of the two strings. */ function concat(slice self, slice other) internal pure returns (string) { string memory ret = new string(self._len + other._len); uint retptr; assembly { retptr := add(ret, 32) } memcpy(retptr, self._ptr, self._len); memcpy(retptr + self._len, other._ptr, other._len); return ret; } function uintToString(uint256 a) internal pure returns (string result) { string memory r = ""; do { uint b = a % 10; a /= 10; string memory c = ""; if (b == 0) c = "0"; else if (b == 1) c = "1"; else if (b == 2) c = "2"; else if (b == 3) c = "3"; else if (b == 4) c = "4"; else if (b == 5) c = "5"; else if (b == 6) c = "6"; else if (b == 7) c = "7"; else if (b == 8) c = "8"; else if (b == 9) c = "9"; r = concat(toSlice(c), toSlice(r)); } while (a > 0); result = r; } }
File 2 of 2: Lottery
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 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 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; } } /** * @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() onlyOwner whenNotPaused public { paused = true; emit Pause(); } /** * @dev called by the owner to unpause, returns to normal state */ function unpause() onlyOwner whenPaused public { paused = false; emit Unpause(); } } pragma solidity ^0.4.20; /// @author https://BlockChainArchitect.iocontract Bank is CutiePluginBase contract PluginInterface { /// @dev simply a boolean to indicate this is the contract we expect to be function isPluginInterface() public pure returns (bool); function onRemove() public; /// @dev Begins new feature. /// @param _cutieId - ID of token to auction, sender must be owner. /// @param _parameter - arbitrary parameter /// @param _seller - Old owner, if not the message sender function run( uint40 _cutieId, uint256 _parameter, address _seller ) public payable; /// @dev Begins new feature, approved and signed by COO. /// @param _cutieId - ID of token to auction, sender must be owner. /// @param _parameter - arbitrary parameter function runSigned( uint40 _cutieId, uint256 _parameter, address _owner ) external payable; function withdraw() public; } pragma solidity ^0.4.20; contract CutieCoreInterface { function isCutieCore() pure public returns (bool); function transferFrom(address _from, address _to, uint256 _cutieId) external; function transfer(address _to, uint256 _cutieId) external; function ownerOf(uint256 _cutieId) external view returns (address owner); function getCutie(uint40 _id) external view returns ( uint256 genes, uint40 birthTime, uint40 cooldownEndTime, uint40 momId, uint40 dadId, uint16 cooldownIndex, uint16 generation ); function getGenes(uint40 _id) public view returns ( uint256 genes ); function getCooldownEndTime(uint40 _id) public view returns ( uint40 cooldownEndTime ); function getCooldownIndex(uint40 _id) public view returns ( uint16 cooldownIndex ); function getGeneration(uint40 _id) public view returns ( uint16 generation ); function getOptional(uint40 _id) public view returns ( uint64 optional ); function changeGenes( uint40 _cutieId, uint256 _genes) public; function changeCooldownEndTime( uint40 _cutieId, uint40 _cooldownEndTime) public; function changeCooldownIndex( uint40 _cutieId, uint16 _cooldownIndex) public; function changeOptional( uint40 _cutieId, uint64 _optional) public; function changeGeneration( uint40 _cutieId, uint16 _generation) public; } /// @author https://BlockChainArchitect.iocontract Bank is CutiePluginBase contract CutiePluginBase is PluginInterface, Pausable { function isPluginInterface() public pure returns (bool) { return true; } // Reference to contract tracking NFT ownership CutieCoreInterface public coreContract; // Cut owner takes on each auction, measured in basis points (1/100 of a percent). // Values 0-10,000 map to 0%-100% uint16 public ownerFee; // @dev Throws if called by any account other than the owner. modifier onlyCore() { require(msg.sender == address(coreContract)); _; } /// @dev Constructor creates a reference to the NFT ownership contract /// and verifies the owner cut is in the valid range. /// @param _coreAddress - address of a deployed contract implementing /// the Nonfungible Interface. /// @param _fee - percent cut the owner takes on each auction, must be /// between 0-10,000. function setup(address _coreAddress, uint16 _fee) public { require(_fee <= 10000); require(msg.sender == owner); ownerFee = _fee; CutieCoreInterface candidateContract = CutieCoreInterface(_coreAddress); require(candidateContract.isCutieCore()); coreContract = candidateContract; } // @dev Set the owner's fee. // @param fee should be between 0-10,000. function setFee(uint16 _fee) public { require(_fee <= 10000); require(msg.sender == owner); ownerFee = _fee; } /// @dev Returns true if the claimant owns the token. /// @param _claimant - Address claiming to own the token. /// @param _cutieId - ID of token whose ownership to verify. function _isOwner(address _claimant, uint40 _cutieId) internal view returns (bool) { return (coreContract.ownerOf(_cutieId) == _claimant); } /// @dev Escrows the NFT, assigning ownership to this contract. /// Throws if the escrow fails. /// @param _owner - Current owner address of token to escrow. /// @param _cutieId - ID of token whose approval to verify. function _escrow(address _owner, uint40 _cutieId) internal { // it will throw if transfer fails coreContract.transferFrom(_owner, this, _cutieId); } /// @dev Transfers an NFT owned by this contract to another address. /// Returns true if the transfer succeeds. /// @param _receiver - Address to transfer NFT to. /// @param _cutieId - ID of token to transfer. function _transfer(address _receiver, uint40 _cutieId) internal { // it will throw if transfer fails coreContract.transfer(_receiver, _cutieId); } /// @dev Computes owner's cut of a sale. /// @param _price - Sale price of NFT. function _computeFee(uint128 _price) internal view returns (uint128) { // NOTE: We don't use SafeMath (or similar) in this function because // all of our entry functions carefully cap the maximum values for // currency (at 128-bits), and ownerFee <= 10000 (see the require() // statement in the ClockAuction constructor). The result of this // function is always guaranteed to be <= _price. return _price * ownerFee / 10000; } function withdraw() public { require( msg.sender == owner || msg.sender == address(coreContract) ); if (address(this).balance > 0) { address(coreContract).transfer(address(this).balance); } } function onRemove() public onlyCore { withdraw(); } function run( uint40, uint256, address ) public payable onlyCore { revert(); } } /// @dev Receives payments for payd features from players for Blockchain Cuties /// @author https://BlockChainArchitect.io contract Lottery is CutiePluginBase { function run( uint40, uint256, address ) public payable onlyCore { // just accept bid } function runSigned(uint40, uint256, address) external payable onlyCore { // just accept bid } }