Transaction Hash:
Block:
6018132 at Jul-23-2018 09:58:00 PM +UTC
Transaction Fee:
0.0005159704 ETH
$0.96
Gas Used:
234,532 Gas / 2.2 Gwei
Account State Difference:
Address | Before | After | State Difference | ||
---|---|---|---|---|---|
0x4F2d119b...88758BDEF | |||||
0x59De2a5C...0FC5fF7b5 | |||||
0xbc7de2B7...57dCABd7b |
0.349036402634259261 Eth
Nonce: 1068
|
0.348520432234259261 Eth
Nonce: 1069
| 0.0005159704 | ||
0xEA674fdD...16B898ec8
Miner
| (Ethermine) | 465.868755640899094079 Eth | 465.869271611299094079 Eth | 0.0005159704 |
Execution Trace
MEAManager.launchShipOnMEA( _assetId=3268, starId=38 ) => ( 1532467186 )
-
CSCPreSaleManager.getCollectibleDetails( _tokenId=3268 ) => ( assetId=3268, sequenceId=32, collectibleType=0, collectibleClass=1, collectibleName=Prometheus Voucher, isRedeemed=False, owner=0xbc7de2B767fA97Ea9D5Ebc05A8d0C8557dCABd7b )
-
0x4f2d119b1063f75bd2088b80ce288a588758bdef.8ede1817( )
-
0x4f2d119b1063f75bd2088b80ce288a588758bdef.7f9c8974( )
-
0x4f2d119b1063f75bd2088b80ce288a588758bdef.51cfa44b( )
-
0x4f2d119b1063f75bd2088b80ce288a588758bdef.85dc6721( )
-
0x4f2d119b1063f75bd2088b80ce288a588758bdef.4d15642a( )
launchShipOnMEA[MEAManager (ln:530)]
_getShipInfo[MEAManager (ln:537)]
getCollectibleDetails[MEAManager (ln:669)]
getCollectibleDetails[MEAManager (ln:673)]
getReturnTime[MEAManager (ln:543)]
_claimOreAndClear[MEAManager (ln:546)]
getAssetCollectedOreBallancesArray[MEAManager (ln:643)]
getStarTotalSupply[MEAManager (ln:655)]
emptyShipCargo[MEAManager (ln:658)]
startMEAMission[MEAManager (ln:620)]
File 1 of 2: MEAManager
File 2 of 2: CSCPreSaleManager
pragma solidity ^0.4.19; /// @title Interface for contracts conforming to ERC-721: Non-Fungible Tokens /// @author Dieter Shirley <[email protected]> (https://github.com/dete) contract CSCERC721 { // Required methods function balanceOf(address _owner) public view returns (uint256 balance) { return 0; } function ownerOf(uint256 _tokenId) public view returns (address owner) { return;} function getCollectibleDetails(uint256 _assetId) external view returns(uint256 assetId, uint256 sequenceId, uint256 collectibleType, uint256 collectibleClass, bool isRedeemed, address owner) { assetId = 0; sequenceId = 0; collectibleType = 0; collectibleClass = 0; owner = 0; isRedeemed = false; } function tokensOfOwner(address _owner) external view returns(uint256[] ownerTokens) { return; } } contract CSCFactoryERC721 { function ownerOf(uint256 _tokenId) public view returns (address owner) { return;} function getCollectibleDetails(uint256 _tokenId) external view returns(uint256 assetId, uint256 sequenceId, uint256 collectibleType, uint256 collectibleClass, bytes32 collectibleName, bool isRedeemed, address owner) { assetId = 0; sequenceId = 0; collectibleType = 0; collectibleClass = 0; owner = 0; collectibleName = 0x0; isRedeemed = false; } function tokensOfOwner(address _owner) external view returns(uint256[] ownerTokens) { return; } } contract ERC20 { function balanceOf(address who) public view returns (uint256); function transfer(address to, uint256 value) public returns (bool); } contract CSCResourceFactory { mapping(uint16 => address) public resourceIdToAddress; } contract MEAHiddenLogic { function getTotalTonsClaimed() external view returns(uint32) { return; } function getTotalSupply() external view returns(uint32) { return; } function getStarTotalSupply(uint8 _starId) external view returns(uint32) { return; } function getReturnTime(uint256 _assetId) external view returns(uint256 time) { return; } //uint256 iron, uint256 quartz, uint256 nickel, uint256 cobalt, uint256 silver, uint256 titanium, uint256 lucinite, uint256 gold, uint256 cosmethyst, uint256 allurum, uint256 platinum, uint256 trilite function setResourceForStar(uint8[5] _resourceTypes, uint16[5] _resourcePer, uint32[5] _resourceAmounts) public returns(uint8 starId) { } /// @dev Method to fetch collected ore details function getAssetCollectedOreBallances(uint256 _assetID) external view returns(uint256 iron, uint256 quartz, uint256 nickel, uint256 cobalt, uint256 silver, uint256 titanium, uint256 lucinite, uint256 gold, uint256 cosmethyst, uint256 allurum, uint256 platinum, uint256 trilite); function getAssetCollectedOreBallancesArray(uint256 _assetID) external view returns(uint256[12] ores); function emptyShipCargo(uint32 _assetId) external; /// @dev For creating CSC Collectible function startMEAMission(uint256 _assetId, uint256 oreMax, uint8 starId, uint256 _travelTime) public returns(uint256); } /* Controls state and access rights for contract functions * @title Operational Control * @author Fazri Zubair & Farhan Khwaja (Lucid Sight, Inc.) * Inspired and adapted from contract created by OpenZeppelin * Ref: https://github.com/OpenZeppelin/zeppelin-solidity/ */ contract OperationalControl { // Facilitates access & control for the game. // Roles: // -The Managers (Primary/Secondary): Has universal control of all elements (No ability to withdraw) // -The Banker: The Bank can withdraw funds and adjust fees / prices. // -otherManagers: Contracts that need access to functions for gameplay /// @dev Emited when contract is upgraded event ContractUpgrade(address newContract); /// @dev Emited when other manager is set event OtherManagerUpdated(address otherManager, uint256 state); // The addresses of the accounts (or contracts) that can execute actions within each roles. address public managerPrimary; address public managerSecondary; address public bankManager; // Contracts that require access for gameplay mapping(address => uint8) public otherManagers; // @dev Keeps track whether the contract is paused. When that is true, most actions are blocked bool public paused = false; // @dev Keeps track whether the contract erroredOut. When that is true, most actions are blocked & refund can be claimed bool public error = false; /// @dev Operation modifiers for limiting access modifier onlyManager() { require(msg.sender == managerPrimary || msg.sender == managerSecondary); _; } modifier onlyBanker() { require(msg.sender == bankManager); _; } modifier onlyOtherManagers() { require(otherManagers[msg.sender] == 1); _; } modifier anyOperator() { require( msg.sender == managerPrimary || msg.sender == managerSecondary || msg.sender == bankManager || otherManagers[msg.sender] == 1 ); _; } /// @dev Assigns a new address to act as the Other Manager. (State = 1 is active, 0 is disabled) function setOtherManager(address _newOp, uint8 _state) external onlyManager { require(_newOp != address(0)); otherManagers[_newOp] = _state; OtherManagerUpdated(_newOp,_state); } /// @dev Assigns a new address to act as the Primary Manager. function setPrimaryManager(address _newGM) external onlyManager { require(_newGM != address(0)); managerPrimary = _newGM; } /// @dev Assigns a new address to act as the Secondary Manager. function setSecondaryManager(address _newGM) external onlyManager { require(_newGM != address(0)); managerSecondary = _newGM; } /// @dev Assigns a new address to act as the Banker. function setBanker(address _newBK) external onlyManager { require(_newBK != address(0)); bankManager = _newBK; } /*** Pausable functionality adapted from OpenZeppelin ***/ /// @dev Modifier to allow actions only when the contract IS NOT paused modifier whenNotPaused() { require(!paused); _; } /// @dev Modifier to allow actions only when the contract IS paused modifier whenPaused { require(paused); _; } /// @dev Modifier to allow actions only when the contract has Error modifier whenError { require(error); _; } /// @dev Called by any Operator role to pause the contract. /// Used only if a bug or exploit is discovered (Here to limit losses / damage) function pause() external onlyManager whenNotPaused { paused = true; } /// @dev Unpauses the smart contract. Can only be called by the Game Master /// @notice This is public rather than external so it can be called by derived contracts. function unpause() public onlyManager whenPaused { // can't unpause if contract was upgraded paused = false; } /// @dev Unpauses the smart contract. Can only be called by the Game Master /// @notice This is public rather than external so it can be called by derived contracts. function hasError() public onlyManager whenPaused { error = true; } /// @dev Unpauses the smart contract. Can only be called by the Game Master /// @notice This is public rather than external so it can be called by derived contracts. function noError() public onlyManager whenPaused { error = false; } } contract MEAManager is OperationalControl { /*** EVENTS ***/ /*** CONSTANTS ***/ uint256 public constant REAPER_INTREPID = 3; uint256 public constant REAPER_INTREPID_EXTRACTION_BASE = 10; // tons per hour of mining uint256 public constant REAPER_INTREPID_FTL_SPEED = 900; // Seconds to travel 1 light year uint256 public constant REAPER_INTREPID_MAX_CARGO = 320; uint256 public constant PHOENIX_CORSAIR = 2; uint256 public constant PHOENIX_CORSAIR_EXTRACTION_BASE = 40; // tons per hour of mining uint256 public constant PHOENIX_CORSAIR_FTL_SPEED = 1440; // Seconds to travel 1 light year uint256 public constant PHOENIX_CORSAIR_MAX_CARGO = 1500; uint256 public constant VULCAN_PROMETHEUS = 1; uint256 public constant VULCAN_PROMETHEUS_EXTRACTION_BASE = 300; // tons per hour of mining uint256 public constant VULCAN_PROMETHEUS_FTL_SPEED = 2057; // Seconds to travel 1 light year uint256 public constant VULCAN_PROMETHEUS_MAX_CARGO = 6000; uint256 public constant SIGMA = 4; uint256 public constant SIGMA_EXTRACTION_BASE = 150; // tons per hour of mining uint256 public constant SIGMA_FTL_SPEED = 4235; // Seconds to travel 1 light year uint256 public constant SIGMA_MAX_CARGO = 15000; uint256 public constant HAYATO = 5; uint256 public constant HAYATO_EXTRACTION_BASE = 150; // tons per hour of mining uint256 public constant HAYATO_FTL_SPEED = 360; // Seconds to travel 1 light year uint256 public constant HAYATO_MAX_CARGO = 1500; uint256 public constant CPGPEREGRINE = 6; uint256 public constant CPGPEREGRINE_EXTRACTION_BASE = 150; // tons per hour of mining uint256 public constant CPGPEREGRINE_FTL_SPEED = 720; // Seconds to travel 1 light year uint256 public constant CPGPEREGRINE_MAX_CARGO = 4000; uint256 public constant TACTICALCRUISER = 7; uint256 public constant TACTICALCRUISER_EXTRACTION_BASE = 150; // tons per hour of mining uint256 public constant TACTICALCRUISER_FTL_SPEED = 720; // Seconds to travel 1 light year uint256 public constant TACTICALCRUISER_MAX_CARGO = 1000; uint256 public constant OTHERCRUISER = 8; uint256 public constant OTHERCRUISER_EXTRACTION_BASE = 100; // tons per hour of mining uint256 public constant OTHERCRUISER_FTL_SPEED = 720; // Seconds to travel 1 light year uint256 public constant OTHERCRUISER_MAX_CARGO = 1500; uint256 public constant VULCAN_POD = 9; uint256 public constant VULCAN_POD_EXTRACTION_BASE = 1; // tons per hour of mining uint256 public constant VULCAN_POD_FTL_SPEED = 2000; // Seconds to travel 1 light year uint256 public constant VULCAN_POD_MAX_CARGO = 75; //For Devs to Travel Around uint256 public constant DEVCLASS = 99; uint256 public constant DEVCLASS_EXTRACTION_BASE = 50; // tons per hour of mining uint256 public constant DEVCLASS_FTL_SPEED = 10; // Seconds to travel 1 light year uint256 public constant DEVCLASS_MAX_CARGO = 500; /// @notice Name and symbol of the non fungible token, as defined in ERC721. string public constant NAME = "MEAGameManager"; /*** Mappings ***/ /// @dev assetID to ore type to qty collected mapping(uint32 => mapping(uint8 => uint32)) public collectedOreAssetMapping; /// @dev owner address to ore type to qty collected mapping(address => mapping(uint8 => uint32)) public collectedOreBalanceMapping; /// @dev owner address to ore type to qty collected mapping(address => mapping(uint8 => uint32)) public distributedOreBalanceMapping; /// @dev assetID to number of MEA trips it has completed mapping(uint32 => uint32) public assetIdNumberOfTripsMapping; /// @dev assetID to ore type to qty collected mapping(uint8 => uint16) public starLightyearDistanceMapping; /// @dev assetID to last star visited mapping(uint32 => uint8) public assetIdToStarVisitedMapping; /// @dev assetID to last star visited mapping(uint16 => address) public resourceERC20Address; /// @dev assetID to Start Time of Current Trip mapping(uint32 => uint32) public assetIdCurrentTripStartTimeMapping; /*** Variables ***/ uint256 public miningTimePerTrip = 3600; // 3600 for 1 hour 10 uint256 public aimeIncreasePerTrip = 2500; // 25.00 address cscERC721Address; address cscFactoryERC721Address; address hiddenLogicAddress; function MEAManager() public { require(msg.sender != address(0)); paused = true; managerPrimary = msg.sender; managerSecondary = msg.sender; bankManager = msg.sender; cscERC721Address = address(0xe4f5e0d5c033f517a943602df942e794a06bc123); cscFactoryERC721Address = address(0xcc9a66acf8574141b0e025202dd57649765a4be7); } /*** Management Functions ***/ /// @dev Set HiddenLogic function setHiddenLogic(address _hiddenLogicAddress) public onlyManager { hiddenLogicAddress = _hiddenLogicAddress; } /// @dev Set HiddenLogic function setResourceERC20Address(uint16 _resId, address _reourceAddress) public onlyManager { resourceERC20Address[_resId] = _reourceAddress; } /// @dev Set HiddenLogic function setAllResourceERC20Addresses(address _master) public onlyManager { CSCResourceFactory factory = CSCResourceFactory(_master); for(uint8 i = 0; i < 12; i++) { resourceERC20Address[i] = factory.resourceIdToAddress(i); } } /// @dev Set CSCErc721 Contract function setCSCERC721(address _cscERC721Address) public onlyManager { cscERC721Address = _cscERC721Address; } /// @dev Set CSCFactoryErc721 Contract function setCSCFactoryERC721(address _cscFactoryERC721Address) public onlyManager { cscFactoryERC721Address = _cscFactoryERC721Address; } /// @dev Set / Modify Lightyear Distance 3.456 ly = 3456 function setStarDistance(uint8 _starId, uint16 _lightyearsInThousands) public anyOperator { starLightyearDistanceMapping[_starId] = _lightyearsInThousands; } /// @dev Set / Modify MEA Game Attributes function setMEAAttributes(uint256 _aime, uint256 _miningTime) public onlyManager { aimeIncreasePerTrip = _aime; miningTimePerTrip = _miningTime; } /// @dev Withdraw Remaining Resource Tokens function reclaimResourceDeposits(address _withdrawAddress) public onlyManager { require(_withdrawAddress != address(0)); for(uint8 ii = 0; ii < 12; ii++) { if(resourceERC20Address[ii] != 0) { ERC20 resCont = ERC20(resourceERC20Address[ii]); uint256 bal = resCont.balanceOf(this); resCont.transfer(_withdrawAddress, bal); } } } /*** Public Functions ***/ /// @dev Get Current Cargo Hold of AssetId (item names) function getAssetIdCargo(uint32 _assetId) public view returns(uint256 iron, uint256 quartz, uint256 nickel, uint256 cobalt, uint256 silver, uint256 titanium, uint256 lucinite, uint256 gold, uint256 cosmethyst, uint256 allurum, uint256 platinum, uint256 trilite) { uint256[12] memory _ores = getAssetIdCargoArray(_assetId); iron = _ores[0]; quartz = _ores[1]; nickel = _ores[2]; cobalt = _ores[3]; silver = _ores[4]; titanium = _ores[5]; lucinite = _ores[6]; gold = _ores[7]; cosmethyst = _ores[8]; allurum = _ores[9]; platinum = _ores[10]; trilite = _ores[11]; } // function getAllShipStats(uint32[] _shipIds) public view returns(uint32[] results) { // //loop all results // for(uint i = 0; i < _shipIds.length; i++) { // results[]]; // } // } /// @dev Get Current Cargo Hold of AssetId (array) function getAssetIdCargoArray (uint32 _assetId) public view returns(uint256[12]) { MEAHiddenLogic logic = MEAHiddenLogic(hiddenLogicAddress); return logic.getAssetCollectedOreBallancesArray(_assetId); } /// @dev Get AssetId Trip Completed Time function getAssetIdTripCompletedTime(uint256 _assetId) external view returns(uint256 time) { MEAHiddenLogic logic = MEAHiddenLogic(hiddenLogicAddress); return logic.getReturnTime(uint32(_assetId)); } /// @dev Get AssetId Trip Completed Time function getAssetIdTripStartTime(uint256 _assetId) external view returns(uint256 time) { return assetIdCurrentTripStartTimeMapping[uint32(_assetId)]; } function getLastStarOfAssetId(uint32 _assetId) public view returns(uint8 starId){ return assetIdToStarVisitedMapping[_assetId]; } /// @dev Get Resource Address function getResourceERC20Address(uint16 _resId) public view returns(address resourceContract) { return resourceERC20Address[_resId]; } /// @dev Get Time function getMEATime() external view returns(uint256 time) { return now; } /// @dev Method to fetch processed ore details function getCollectedOreBalances(address _owner) external view returns(uint256 iron, uint256 quartz, uint256 nickel, uint256 cobalt, uint256 silver, uint256 titanium, uint256 lucinite, uint256 gold, uint256 cosmethyst, uint256 allurum, uint256 platinum, uint256 trilite) { iron = collectedOreBalanceMapping[_owner][0]; quartz = collectedOreBalanceMapping[_owner][1]; nickel = collectedOreBalanceMapping[_owner][2]; cobalt = collectedOreBalanceMapping[_owner][3]; silver = collectedOreBalanceMapping[_owner][4]; titanium = collectedOreBalanceMapping[_owner][5]; lucinite = collectedOreBalanceMapping[_owner][6]; gold = collectedOreBalanceMapping[_owner][7]; cosmethyst = collectedOreBalanceMapping[_owner][8]; allurum = collectedOreBalanceMapping[_owner][9]; platinum = collectedOreBalanceMapping[_owner][10]; trilite = collectedOreBalanceMapping[_owner][11]; } /// @dev Method to fetch processed ore details function getDistributedOreBalances(address _owner) external view returns(uint256 iron, uint256 quartz, uint256 nickel, uint256 cobalt, uint256 silver, uint256 titanium, uint256 lucinite, uint256 gold, uint256 cosmethyst, uint256 allurum, uint256 platinum, uint256 trilite) { iron = distributedOreBalanceMapping[_owner][0]; quartz = distributedOreBalanceMapping[_owner][1]; nickel = distributedOreBalanceMapping[_owner][2]; cobalt = distributedOreBalanceMapping[_owner][3]; silver = distributedOreBalanceMapping[_owner][4]; titanium = distributedOreBalanceMapping[_owner][5]; lucinite = distributedOreBalanceMapping[_owner][6]; gold = distributedOreBalanceMapping[_owner][7]; cosmethyst = distributedOreBalanceMapping[_owner][8]; allurum = distributedOreBalanceMapping[_owner][9]; platinum = distributedOreBalanceMapping[_owner][10]; trilite = distributedOreBalanceMapping[_owner][11]; } function withdrawCollectedResources() public { for(uint8 ii = 0; ii < 12; ii++) { require(resourceERC20Address[ii] != address(0)); uint32 oreOutstanding = collectedOreBalanceMapping[msg.sender][ii] - distributedOreBalanceMapping[msg.sender][ii]; if(oreOutstanding > 0) { ERC20 resCont = ERC20(resourceERC20Address[ii]); distributedOreBalanceMapping[msg.sender][ii] += oreOutstanding; resCont.transfer(msg.sender, oreOutstanding); } } } //Gets star distance in thousandths of ly function getStarDistanceInLyThousandths(uint8 _starId) public view returns (uint32 total) { return starLightyearDistanceMapping[_starId]; } //Gets total resources already claimed by commanders function totalMEATonsClaimed() public view returns (uint32 total) { MEAHiddenLogic logic = MEAHiddenLogic(hiddenLogicAddress); return logic.getTotalTonsClaimed(); } //Gets total seeded supply commanders function totalMEATonsSupply() public view returns (uint32 total) { MEAHiddenLogic logic = MEAHiddenLogic(hiddenLogicAddress); return logic.getTotalSupply(); } function totalStarSupplyRemaining(uint8 _starId) external view returns(uint32) { MEAHiddenLogic logic = MEAHiddenLogic(hiddenLogicAddress); return logic.getStarTotalSupply(_starId); } function claimOreOnlyFromAssetId(uint256 _assetId) { uint256 collectibleClass = 0; address shipOwner; (collectibleClass, shipOwner) = _getShipInfo(_assetId); require(shipOwner == msg.sender); _claimOreAndClear(uint32(_assetId), 0); } /// @dev For creating CSC Collectible function launchShipOnMEA(uint256 _assetId, uint8 starId) public whenNotPaused returns(uint256) { MEAHiddenLogic logic = MEAHiddenLogic(hiddenLogicAddress); uint256 collectibleClass = 0; address shipOwner; (collectibleClass, shipOwner) = _getShipInfo(_assetId); //Check if the ship owner is sender require(shipOwner == msg.sender); //Check if ship is back at earth require(now > logic.getReturnTime(_assetId)); //Claims ore and clears _claimOreAndClear(uint32(_assetId), starId); //Get Asset Stats uint tripCount = assetIdNumberOfTripsMapping[uint32(_assetId)]; uint starTripDist = starLightyearDistanceMapping[starId]; uint256 oreMax = 5; uint256 tripSeconds = 10; if(collectibleClass == REAPER_INTREPID) { oreMax = REAPER_INTREPID_EXTRACTION_BASE + (REAPER_INTREPID_EXTRACTION_BASE * tripCount * aimeIncreasePerTrip / 10000); tripSeconds = REAPER_INTREPID_FTL_SPEED * starTripDist / 1000; // 4LPH - 900 seconds per light year if(oreMax > REAPER_INTREPID_MAX_CARGO) oreMax = REAPER_INTREPID_MAX_CARGO; } else if(collectibleClass == PHOENIX_CORSAIR) { oreMax = PHOENIX_CORSAIR_EXTRACTION_BASE + (PHOENIX_CORSAIR_EXTRACTION_BASE * tripCount * aimeIncreasePerTrip / 10000); tripSeconds = PHOENIX_CORSAIR_FTL_SPEED * starTripDist / 1000; // 2.5LPH - 1440 seconds per light year if(oreMax > PHOENIX_CORSAIR_MAX_CARGO) oreMax = PHOENIX_CORSAIR_MAX_CARGO; } else if(collectibleClass == VULCAN_PROMETHEUS) { oreMax = VULCAN_PROMETHEUS_EXTRACTION_BASE + (VULCAN_PROMETHEUS_EXTRACTION_BASE * tripCount * aimeIncreasePerTrip / 10000); tripSeconds = VULCAN_PROMETHEUS_FTL_SPEED * starTripDist / 1000; // 1.75LPH - 2057 seconds per light year if(oreMax > VULCAN_PROMETHEUS_MAX_CARGO) oreMax = VULCAN_PROMETHEUS_MAX_CARGO; } else if(collectibleClass == SIGMA) { oreMax = SIGMA_EXTRACTION_BASE + (SIGMA_EXTRACTION_BASE * tripCount * aimeIncreasePerTrip / 10000); tripSeconds = SIGMA_FTL_SPEED * starTripDist / 1000; // 0.85LPH - 4235 seconds per light year if(oreMax > SIGMA_MAX_CARGO) oreMax = SIGMA_MAX_CARGO; } else if(collectibleClass == HAYATO) { //Hayato oreMax = HAYATO_EXTRACTION_BASE + (HAYATO_EXTRACTION_BASE * tripCount * aimeIncreasePerTrip / 10000); tripSeconds = HAYATO_FTL_SPEED * starTripDist / 1000; // 10LPH - 360 seconds per light year if(oreMax > HAYATO_MAX_CARGO) oreMax = HAYATO_MAX_CARGO; } else if(collectibleClass == CPGPEREGRINE) { //CPG Peregrine oreMax = CPGPEREGRINE_EXTRACTION_BASE + (CPGPEREGRINE_EXTRACTION_BASE * tripCount * aimeIncreasePerTrip / 10000); tripSeconds = CPGPEREGRINE_FTL_SPEED * starTripDist / 1000; // 5LPH -720 seconds per light year if(oreMax > CPGPEREGRINE_MAX_CARGO) oreMax = CPGPEREGRINE_MAX_CARGO; } else if(collectibleClass == TACTICALCRUISER) { //TACTICA CRUISER Ships oreMax = TACTICALCRUISER_EXTRACTION_BASE + (TACTICALCRUISER_EXTRACTION_BASE * tripCount * aimeIncreasePerTrip / 10000); tripSeconds = TACTICALCRUISER_FTL_SPEED * starTripDist / 1000; if(oreMax > TACTICALCRUISER_MAX_CARGO) oreMax = TACTICALCRUISER_MAX_CARGO; } else if(collectibleClass == VULCAN_POD) { //TACTICA CRUISER Ships oreMax = VULCAN_POD_EXTRACTION_BASE + (VULCAN_POD_EXTRACTION_BASE * tripCount * aimeIncreasePerTrip / 10000); tripSeconds = VULCAN_POD_FTL_SPEED * starTripDist / 1000; if(oreMax > VULCAN_POD_MAX_CARGO) oreMax = VULCAN_POD_MAX_CARGO; } else if(collectibleClass >= DEVCLASS) { //Dev Ships oreMax = DEVCLASS_EXTRACTION_BASE + (DEVCLASS_EXTRACTION_BASE * tripCount * aimeIncreasePerTrip / 10000); tripSeconds = DEVCLASS_FTL_SPEED * starTripDist / 1000; if(oreMax > DEVCLASS_MAX_CARGO) oreMax = DEVCLASS_MAX_CARGO; } else { if(collectibleClass >= OTHERCRUISER) { //Support Other Promo Ships oreMax = OTHERCRUISER_EXTRACTION_BASE + (OTHERCRUISER_EXTRACTION_BASE * tripCount * aimeIncreasePerTrip / 10000); tripSeconds = OTHERCRUISER_FTL_SPEED * starTripDist / 1000; if(oreMax > OTHERCRUISER_MAX_CARGO) oreMax = OTHERCRUISER_MAX_CARGO; } } //Make Round Trip + Mining tripSeconds = ((tripSeconds * 2) + miningTimePerTrip); //3600 for an hour - 0 for testing *************************** //calculate travel time uint256 returnTime = logic.startMEAMission(_assetId, oreMax, starId, tripSeconds); //Confirm trip if(returnTime > 0) { assetIdNumberOfTripsMapping[uint32(_assetId)] += 1; assetIdToStarVisitedMapping[uint32(_assetId)] = starId; assetIdCurrentTripStartTimeMapping[uint32(_assetId)] = uint32(now); } return returnTime; } /*** PRIVATE FUNCTIONS ***/ /// @dev Safety check on _to address to prevent against an unexpected 0x0 default. function _addressNotNull(address _to) internal pure returns (bool) { return _to != address(0); } /// @dev Claims and clears cargo -- ONLY INTERNAL function _claimOreAndClear (uint32 _assetId, uint8 _starId) internal { MEAHiddenLogic logic = MEAHiddenLogic(hiddenLogicAddress); uint256[12] memory _ores = logic.getAssetCollectedOreBallancesArray(_assetId); bool hasItems = false; for(uint8 i = 0; i < 12; i++) { if(_ores[i] > 0) { collectedOreBalanceMapping[msg.sender][i] += uint32(_ores[i]); hasItems = true; } } //Doesn't Let you Travel to empty stars but lets you collect if(hasItems == false && _starId > 0) { require(logic.getStarTotalSupply(_starId) > 0); } logic.emptyShipCargo(_assetId); } function _getShipInfo(uint256 _assetId) internal view returns (uint256 collectibleClass, address owner) { uint256 nulldata; bool nullbool; uint256 collectibleType; if(_assetId <= 3000) { CSCERC721 shipData = CSCERC721(cscERC721Address); (nulldata, nulldata, collectibleType, collectibleClass, nullbool, owner) = shipData.getCollectibleDetails(_assetId); } else { bytes32 nullstring; CSCFactoryERC721 shipFData = CSCFactoryERC721(cscFactoryERC721Address); (nulldata, nulldata, collectibleType, collectibleClass, nullstring, nullbool, owner) = shipFData.getCollectibleDetails(_assetId); } } }
File 2 of 2: CSCPreSaleManager
pragma solidity ^0.4.19; /* Adapted from strings.sol created by Nick Johnson <[email protected]> * Ref: https://github.com/Arachnid/solidity-stringutils/blob/2f6ca9accb48ae14c66f1437ec50ed19a0616f78/strings.sol * @title String & slice utility library for Solidity contracts. * @author Nick Johnson <[email protected]> */ library strings { 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)) } } function concat(slice self, slice other) internal returns (string) { var 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; } /* * @dev Counts the number of nonoverlapping occurrences of `needle` in `self`. * @param self The slice to search. * @param needle The text to search for in `self`. * @return The number of occurrences of `needle` found in `self`. */ function count(slice self, slice needle) internal returns (uint cnt) { uint ptr = findPtr(self._len, self._ptr, needle._len, needle._ptr) + needle._len; while (ptr <= self._ptr + self._len) { cnt++; ptr = findPtr(self._len - (ptr - self._ptr), ptr, needle._len, needle._ptr) + needle._len; } } // Returns the memory address of the first byte of the first occurrence of // `needle` in `self`, or the first byte after `self` if not found. function findPtr(uint selflen, uint selfptr, uint needlelen, uint needleptr) private returns (uint) { uint ptr; uint idx; if (needlelen <= selflen) { if (needlelen <= 32) { // Optimized assembly for 68 gas per byte on short strings assembly { let mask := not(sub(exp(2, mul(8, sub(32, needlelen))), 1)) let needledata := and(mload(needleptr), mask) let end := add(selfptr, sub(selflen, needlelen)) ptr := selfptr loop: jumpi(exit, eq(and(mload(ptr), mask), needledata)) ptr := add(ptr, 1) jumpi(loop, lt(sub(ptr, 1), end)) ptr := add(selfptr, selflen) exit: } return ptr; } else { // For long needles, use hashing bytes32 hash; assembly { hash := sha3(needleptr, needlelen) } ptr = selfptr; for (idx = 0; idx <= selflen - needlelen; idx++) { bytes32 testHash; assembly { testHash := sha3(ptr, needlelen) } if (hash == testHash) return ptr; ptr += 1; } } } return selfptr + selflen; } /* * @dev Splits the slice, setting `self` to everything after the first * occurrence of `needle`, and `token` to everything before it. If * `needle` does not occur in `self`, `self` is set to the empty slice, * and `token` is set to the entirety of `self`. * @param self The slice to split. * @param needle The text to search for in `self`. * @param token An output parameter to which the first token is written. * @return `token`. */ function split(slice self, slice needle, slice token) internal returns (slice) { uint ptr = findPtr(self._len, self._ptr, needle._len, needle._ptr); token._ptr = self._ptr; token._len = ptr - self._ptr; if (ptr == self._ptr + self._len) { // Not found self._len = 0; } else { self._len -= token._len + needle._len; self._ptr = ptr + needle._len; } return token; } /* * @dev Splits the slice, setting `self` to everything after the first * occurrence of `needle`, and returning everything before it. If * `needle` does not occur in `self`, `self` is set to the empty slice, * and the entirety of `self` is returned. * @param self The slice to split. * @param needle The text to search for in `self`. * @return The part of `self` up to the first occurrence of `delim`. */ function split(slice self, slice needle) internal returns (slice token) { split(self, needle, token); } /* * @dev Copies a slice to a new string. * @param self The slice to copy. * @return A newly allocated string containing the slice's text. */ function toString(slice self) internal pure returns (string) { var ret = new string(self._len); uint retptr; assembly { retptr := add(ret, 32) } memcpy(retptr, self._ptr, self._len); return ret; } } /* Helper String Functions for Game Manager Contract * @title String Healpers * @author Fazri Zubair & Farhan Khwaja (Lucid Sight, Inc.) */ contract StringHelpers { using strings for *; function stringToBytes32(string memory source) internal returns (bytes32 result) { bytes memory tempEmptyStringTest = bytes(source); if (tempEmptyStringTest.length == 0) { return 0x0; } assembly { result := mload(add(source, 32)) } } function bytes32ToString(bytes32 x) constant internal returns (string) { bytes memory bytesString = new bytes(32); uint charCount = 0; for (uint j = 0; j < 32; j++) { byte char = byte(bytes32(uint(x) * 2 ** (8 * j))); if (char != 0) { bytesString[charCount] = char; charCount++; } } bytes memory bytesStringTrimmed = new bytes(charCount); for (j = 0; j < charCount; j++) { bytesStringTrimmed[j] = bytesString[j]; } return string(bytesStringTrimmed); } } /// @title Interface for contracts conforming to ERC-721: Non-Fungible Tokens /// @author Dieter Shirley <[email protected]> (https://github.com/dete) contract ERC721 { // Required methods function balanceOf(address _owner) public view returns (uint256 balance); function ownerOf(uint256 _tokenId) public view returns (address owner); function approve(address _to, uint256 _tokenId) public; function transfer(address _to, uint256 _tokenId) public; function transferFrom(address _from, address _to, uint256 _tokenId) public; function implementsERC721() public pure returns (bool); function takeOwnership(uint256 _tokenId) public; function totalSupply() public view returns (uint256 total); event Transfer(address indexed from, address indexed to, uint256 tokenId); event Approval(address indexed owner, address indexed approved, uint256 tokenId); // Optional // function name() public view returns (string name); // function symbol() public view returns (string symbol); // function tokenOfOwnerByIndex(address _owner, uint256 _index) external view returns (uint256 tokenId); // function tokenMetadata(uint256 _tokenId) public view returns (string infoUrl); // ERC-165 Compatibility (https://github.com/ethereum/EIPs/issues/165) function supportsInterface(bytes4 _interfaceID) external view returns (bool); } /* Controls state and access rights for contract functions * @title Operational Control * @author Fazri Zubair & Farhan Khwaja (Lucid Sight, Inc.) * Inspired and adapted from contract created by OpenZeppelin * Ref: https://github.com/OpenZeppelin/zeppelin-solidity/ */ contract OperationalControl { // Facilitates access & control for the game. // Roles: // -The Managers (Primary/Secondary): Has universal control of all elements (No ability to withdraw) // -The Banker: The Bank can withdraw funds and adjust fees / prices. /// @dev Emited when contract is upgraded event ContractUpgrade(address newContract); // The addresses of the accounts (or contracts) that can execute actions within each roles. address public managerPrimary; address public managerSecondary; address public bankManager; // @dev Keeps track whether the contract is paused. When that is true, most actions are blocked bool public paused = false; // @dev Keeps track whether the contract erroredOut. When that is true, most actions are blocked & refund can be claimed bool public error = false; /// @dev Operation modifiers for limiting access modifier onlyManager() { require(msg.sender == managerPrimary || msg.sender == managerSecondary); _; } modifier onlyBanker() { require(msg.sender == bankManager); _; } modifier anyOperator() { require( msg.sender == managerPrimary || msg.sender == managerSecondary || msg.sender == bankManager ); _; } /// @dev Assigns a new address to act as the Primary Manager. function setPrimaryManager(address _newGM) external onlyManager { require(_newGM != address(0)); managerPrimary = _newGM; } /// @dev Assigns a new address to act as the Secondary Manager. function setSecondaryManager(address _newGM) external onlyManager { require(_newGM != address(0)); managerSecondary = _newGM; } /// @dev Assigns a new address to act as the Banker. function setBanker(address _newBK) external onlyManager { require(_newBK != address(0)); bankManager = _newBK; } /*** Pausable functionality adapted from OpenZeppelin ***/ /// @dev Modifier to allow actions only when the contract IS NOT paused modifier whenNotPaused() { require(!paused); _; } /// @dev Modifier to allow actions only when the contract IS paused modifier whenPaused { require(paused); _; } /// @dev Modifier to allow actions only when the contract has Error modifier whenError { require(error); _; } /// @dev Called by any Operator role to pause the contract. /// Used only if a bug or exploit is discovered (Here to limit losses / damage) function pause() external onlyManager whenNotPaused { paused = true; } /// @dev Unpauses the smart contract. Can only be called by the Game Master /// @notice This is public rather than external so it can be called by derived contracts. function unpause() public onlyManager whenPaused { // can't unpause if contract was upgraded paused = false; } /// @dev Unpauses the smart contract. Can only be called by the Game Master /// @notice This is public rather than external so it can be called by derived contracts. function hasError() public onlyManager whenPaused { error = true; } /// @dev Unpauses the smart contract. Can only be called by the Game Master /// @notice This is public rather than external so it can be called by derived contracts. function noError() public onlyManager whenPaused { error = false; } } contract CSCPreSaleItemBase is ERC721, OperationalControl, StringHelpers { /*** EVENTS ***/ /// @dev The Created event is fired whenever a new collectible comes into existence. event CollectibleCreated(address owner, uint256 globalId, uint256 collectibleType, uint256 collectibleClass, uint256 sequenceId, bytes32 collectibleName); /*** CONSTANTS ***/ /// @notice Name and symbol of the non fungible token, as defined in ERC721. string public constant NAME = "CSCPreSaleFactory"; string public constant SYMBOL = "CSCPF"; 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)')); /// @dev CSC Pre Sale Struct, having details of the collectible struct CSCPreSaleItem { /// @dev sequence ID i..e Local Index uint256 sequenceId; /// @dev name of the collectible stored in bytes bytes32 collectibleName; /// @dev Collectible Type uint256 collectibleType; /// @dev Collectible Class uint256 collectibleClass; /// @dev owner address address owner; /// @dev redeemed flag (to help whether it got redeemed or not) bool isRedeemed; } /// @dev array of CSCPreSaleItem type holding information on the Collectibles Created CSCPreSaleItem[] allPreSaleItems; /// @dev Max Count for preSaleItem type -> preSaleItem class -> max. limit mapping(uint256 => mapping(uint256 => uint256)) public preSaleItemTypeToClassToMaxLimit; /// @dev Map from preSaleItem type -> preSaleItem class -> max. limit set (bool) mapping(uint256 => mapping(uint256 => bool)) public preSaleItemTypeToClassToMaxLimitSet; /// @dev Map from preSaleItem type -> preSaleItem class -> Name (string / bytes32) mapping(uint256 => mapping(uint256 => bytes32)) public preSaleItemTypeToClassToName; // @dev mapping which holds all the possible addresses which are allowed to interact with the contract mapping (address => bool) approvedAddressList; // @dev mapping holds the preSaleItem -> owner details mapping (uint256 => address) public preSaleItemIndexToOwner; // @dev A mapping from owner address to count of tokens that address owns. // Used internally inside balanceOf() to resolve ownership count. mapping (address => uint256) private ownershipTokenCount; /// @dev A mapping from preSaleItem to an address that has been approved to call /// transferFrom(). Each Collectible can only have one approved address for transfer /// at any time. A zero value means no approval is outstanding. mapping (uint256 => address) public preSaleItemIndexToApproved; /// @dev A mapping of preSaleItem Type to Type Sequence Number to Collectible mapping (uint256 => mapping (uint256 => mapping ( uint256 => uint256 ) ) ) public preSaleItemTypeToSequenceIdToCollectible; /// @dev A mapping from Pre Sale Item Type IDs to the Sequqence Number . mapping (uint256 => mapping ( uint256 => uint256 ) ) public preSaleItemTypeToCollectibleCount; /// @dev Token Starting Index taking into account the old presaleContract total assets that can be generated uint256 public STARTING_ASSET_BASE = 3000; /// @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)); } function setMaxLimit(string _collectibleName, uint256 _collectibleType, uint256 _collectibleClass, uint256 _maxLimit) external onlyManager whenNotPaused { require(_maxLimit > 0); require(_collectibleType >= 0 && _collectibleClass >= 0); require(stringToBytes32(_collectibleName) != stringToBytes32("")); require(!preSaleItemTypeToClassToMaxLimitSet[_collectibleType][_collectibleClass]); preSaleItemTypeToClassToMaxLimit[_collectibleType][_collectibleClass] = _maxLimit; preSaleItemTypeToClassToMaxLimitSet[_collectibleType][_collectibleClass] = true; preSaleItemTypeToClassToName[_collectibleType][_collectibleClass] = stringToBytes32(_collectibleName); } /// @dev Method to fetch collectible details function getCollectibleDetails(uint256 _tokenId) external view returns(uint256 assetId, uint256 sequenceId, uint256 collectibleType, uint256 collectibleClass, string collectibleName, bool isRedeemed, address owner) { require (_tokenId > STARTING_ASSET_BASE); uint256 generatedCollectibleId = _tokenId - STARTING_ASSET_BASE; CSCPreSaleItem memory _Obj = allPreSaleItems[generatedCollectibleId]; assetId = _tokenId; sequenceId = _Obj.sequenceId; collectibleType = _Obj.collectibleType; collectibleClass = _Obj.collectibleClass; collectibleName = bytes32ToString(_Obj.collectibleName); owner = _Obj.owner; isRedeemed = _Obj.isRedeemed; } /*** PUBLIC FUNCTIONS ***/ /// @notice Grant another address the right to transfer token via takeOwnership() and transferFrom(). /// @param _to The address to be granted transfer approval. Pass address(0) to /// clear all approvals. /// @param _tokenId The ID of the Token that can be transferred if this call succeeds. /// @dev Required for ERC-721 compliance. function approve(address _to, uint256 _tokenId) public { // Caller must own token. require (_tokenId > STARTING_ASSET_BASE); require(_owns(msg.sender, _tokenId)); preSaleItemIndexToApproved[_tokenId] = _to; Approval(msg.sender, _to, _tokenId); } /// For querying balance of a particular account /// @param _owner The address for balance query /// @dev Required for ERC-721 compliance. function balanceOf(address _owner) public view returns (uint256 balance) { return ownershipTokenCount[_owner]; } function implementsERC721() public pure returns (bool) { return true; } /// For querying owner of token /// @param _tokenId The tokenID for owner inquiry /// @dev Required for ERC-721 compliance. function ownerOf(uint256 _tokenId) public view returns (address owner) { require (_tokenId > STARTING_ASSET_BASE); owner = preSaleItemIndexToOwner[_tokenId]; require(owner != address(0)); } /// @dev Required for ERC-721 compliance. function symbol() public pure returns (string) { return SYMBOL; } /// @notice Allow pre-approved user to take ownership of a token /// @param _tokenId The ID of the Token that can be transferred if this call succeeds. /// @dev Required for ERC-721 compliance. function takeOwnership(uint256 _tokenId) public { require (_tokenId > STARTING_ASSET_BASE); address newOwner = msg.sender; address oldOwner = preSaleItemIndexToOwner[_tokenId]; // Safety check to prevent against an unexpected 0x0 default. require(_addressNotNull(newOwner)); // Making sure transfer is approved require(_approved(newOwner, _tokenId)); _transfer(oldOwner, newOwner, _tokenId); } /// @param _owner The owner whose collectibles tokens we are interested in. /// @dev This method MUST NEVER be called by smart contract code. First, it's fairly /// expensive (it walks the entire CSCPreSaleItem array looking for collectibles 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 totalCount = totalSupply() + 1 + STARTING_ASSET_BASE; uint256 resultIndex = 0; // We count on the fact that all LS PreSaleItems have IDs starting at 0 and increasing // sequentially up to the total count. uint256 _tokenId; for (_tokenId = STARTING_ASSET_BASE; _tokenId < totalCount; _tokenId++) { if (preSaleItemIndexToOwner[_tokenId] == _owner) { result[resultIndex] = _tokenId; resultIndex++; } } return result; } } /// For querying totalSupply of token /// @dev Required for ERC-721 compliance. function totalSupply() public view returns (uint256 total) { return allPreSaleItems.length - 1; //Removed 0 index } /// Owner initates the transfer of the token to another account /// @param _to The address for the token to be transferred to. /// @param _tokenId The ID of the Token that can be transferred if this call succeeds. /// @dev Required for ERC-721 compliance. function transfer(address _to, uint256 _tokenId) public { require (_tokenId > STARTING_ASSET_BASE); require(_addressNotNull(_to)); require(_owns(msg.sender, _tokenId)); _transfer(msg.sender, _to, _tokenId); } /// Third-party initiates transfer of token from address _from to address _to /// @param _from The address for the token to be transferred from. /// @param _to The address for the token to be transferred to. /// @param _tokenId The ID of the Token that can be transferred if this call succeeds. /// @dev Required for ERC-721 compliance. function transferFrom(address _from, address _to, uint256 _tokenId) public { require (_tokenId > STARTING_ASSET_BASE); require(_owns(_from, _tokenId)); require(_approved(_to, _tokenId)); require(_addressNotNull(_to)); _transfer(_from, _to, _tokenId); } /*** PRIVATE FUNCTIONS ***/ /// @dev Safety check on _to address to prevent against an unexpected 0x0 default. function _addressNotNull(address _to) internal pure returns (bool) { return _to != address(0); } /// @dev For checking approval of transfer for address _to function _approved(address _to, uint256 _tokenId) internal view returns (bool) { return preSaleItemIndexToApproved[_tokenId] == _to; } /// @dev For creating CSC Collectible function _createCollectible(bytes32 _collectibleName, uint256 _collectibleType, uint256 _collectibleClass) internal returns(uint256) { uint256 _sequenceId = uint256(preSaleItemTypeToCollectibleCount[_collectibleType][_collectibleClass]) + 1; // These requires are not strictly necessary, our calling code should make // sure that these conditions are never broken. require(_sequenceId == uint256(uint32(_sequenceId))); CSCPreSaleItem memory _collectibleObj = CSCPreSaleItem( _sequenceId, _collectibleName, _collectibleType, _collectibleClass, address(0), false ); uint256 generatedCollectibleId = allPreSaleItems.push(_collectibleObj) - 1; uint256 collectibleIndex = generatedCollectibleId + STARTING_ASSET_BASE; preSaleItemTypeToSequenceIdToCollectible[_collectibleType][_collectibleClass][_sequenceId] = collectibleIndex; preSaleItemTypeToCollectibleCount[_collectibleType][_collectibleClass] = _sequenceId; // emit Created event // CollectibleCreated(address owner, uint256 globalId, uint256 collectibleType, uint256 collectibleClass, uint256 sequenceId, bytes32 collectibleName); CollectibleCreated(address(this), collectibleIndex, _collectibleType, _collectibleClass, _sequenceId, _collectibleObj.collectibleName); // This will assign ownership, and also emit the Transfer event as // per ERC721 draft _transfer(address(0), address(this), collectibleIndex); return collectibleIndex; } /// @dev Check for token ownership function _owns(address claimant, uint256 _tokenId) internal view returns (bool) { return claimant == preSaleItemIndexToOwner[_tokenId]; } /// @dev Assigns ownership of a specific preSaleItem to an address. function _transfer(address _from, address _to, uint256 _tokenId) internal { uint256 generatedCollectibleId = _tokenId - STARTING_ASSET_BASE; // Updating the owner details of the collectible CSCPreSaleItem memory _Obj = allPreSaleItems[generatedCollectibleId]; _Obj.owner = _to; allPreSaleItems[generatedCollectibleId] = _Obj; // Since the number of preSaleItem is capped to 2^32 we can't overflow this ownershipTokenCount[_to]++; //transfer ownership preSaleItemIndexToOwner[_tokenId] = _to; // When creating new collectibles _from is 0x0, but we can't account that address. if (_from != address(0)) { ownershipTokenCount[_from]--; // clear any previously approved ownership exchange delete preSaleItemIndexToApproved[_tokenId]; } // Emit the transfer event. Transfer(_from, _to, _tokenId); } /// @dev Checks if a given address currently has transferApproval for a particular CSCPreSaleItem. /// 0 is a valid value as it will be the starter function _approvedFor(address _claimant, uint256 _tokenId) internal view returns (bool) { require(_tokenId > STARTING_ASSET_BASE); return preSaleItemIndexToApproved[_tokenId] == _claimant; } } /* Lucid Sight, Inc. ERC-721 Collectibles Manager. * @title LSPreSaleManager - Lucid Sight, Inc. Non-Fungible Token * @author Fazri Zubair & Farhan Khwaja (Lucid Sight, Inc.) */ contract CSCPreSaleManager is CSCPreSaleItemBase { event RefundClaimed(address owner, uint256 refundValue); /// @dev defines if preSaleItem type -> preSaleItem class -> Vending Machine to set limit (bool) mapping(uint256 => mapping(uint256 => bool)) public preSaleItemTypeToClassToCanBeVendingMachine; /// @dev defines if preSaleItem type -> preSaleItem class -> Vending Machine Fee mapping(uint256 => mapping(uint256 => uint256)) public preSaleItemTypeToClassToVendingFee; /// @dev Mapping created store the amount of value a wallet address used to buy assets mapping(address => uint256) public addressToValue; bool CSCPreSaleInit = false; /// @dev Constructor creates a reference to the NFT (ERC721) ownership contract function CSCPreSaleManager() public { require(msg.sender != address(0)); paused = true; error = false; managerPrimary = msg.sender; } /// @dev allows the contract to accept ETH function() external payable { } /// @dev Function to add approved address to the /// approved address list function addToApprovedAddress (address _newAddr) onlyManager whenNotPaused { require(_newAddr != address(0)); require(!approvedAddressList[_newAddr]); approvedAddressList[_newAddr] = true; } /// @dev Function to remove an approved address from the /// approved address list function removeFromApprovedAddress (address _newAddr) onlyManager whenNotPaused { require(_newAddr != address(0)); require(approvedAddressList[_newAddr]); approvedAddressList[_newAddr] = false; } /// @dev Function toggle vending for collectible function toggleVending (uint256 _collectibleType, uint256 _collectibleClass) external onlyManager { if(preSaleItemTypeToClassToCanBeVendingMachine[_collectibleType][_collectibleClass] == false) { preSaleItemTypeToClassToCanBeVendingMachine[_collectibleType][_collectibleClass] = true; } else { preSaleItemTypeToClassToCanBeVendingMachine[_collectibleType][_collectibleClass] = false; } } /// @dev Function toggle vending for collectible function setVendingFee (uint256 _collectibleType, uint256 _collectibleClass, uint fee) external onlyManager { preSaleItemTypeToClassToVendingFee[_collectibleType][_collectibleClass] = fee; } /// @dev This helps in creating a collectible and then /// transfer it _toAddress function createCollectible(uint256 _collectibleType, uint256 _collectibleClass, address _toAddress) onlyManager external whenNotPaused { require(msg.sender != address(0)); require(msg.sender != address(this)); require(_toAddress != address(0)); require(_toAddress != address(this)); require(preSaleItemTypeToClassToMaxLimitSet[_collectibleType][_collectibleClass]); require(preSaleItemTypeToCollectibleCount[_collectibleType][_collectibleClass] < preSaleItemTypeToClassToMaxLimit[_collectibleType][_collectibleClass]); uint256 _tokenId = _createCollectible(preSaleItemTypeToClassToName[_collectibleType][_collectibleClass], _collectibleType, _collectibleClass); _transfer(address(this), _toAddress, _tokenId); } /// @dev This helps in creating a collectible and then /// transfer it _toAddress function vendingCreateCollectible(uint256 _collectibleType, uint256 _collectibleClass, address _toAddress) payable external whenNotPaused { //Only if Vending is Allowed for this Asset require(preSaleItemTypeToClassToCanBeVendingMachine[_collectibleType][_collectibleClass]); require(msg.value >= preSaleItemTypeToClassToVendingFee[_collectibleType][_collectibleClass]); require(msg.sender != address(0)); require(msg.sender != address(this)); require(_toAddress != address(0)); require(_toAddress != address(this)); require(preSaleItemTypeToClassToMaxLimitSet[_collectibleType][_collectibleClass]); require(preSaleItemTypeToCollectibleCount[_collectibleType][_collectibleClass] < preSaleItemTypeToClassToMaxLimit[_collectibleType][_collectibleClass]); uint256 _tokenId = _createCollectible(preSaleItemTypeToClassToName[_collectibleType][_collectibleClass], _collectibleType, _collectibleClass); uint256 excessBid = msg.value - preSaleItemTypeToClassToVendingFee[_collectibleType][_collectibleClass]; if(excessBid > 0) { msg.sender.transfer(excessBid); } addressToValue[msg.sender] += preSaleItemTypeToClassToVendingFee[_collectibleType][_collectibleClass]; _transfer(address(this), _toAddress, _tokenId); } /// @dev Override unpause so it requires all external contract addresses /// to be set before contract can be unpaused. Also, we can't have /// newContractAddress set either, because then the contract was upgraded. /// @notice This is public rather than external so we can call super.unpause /// without using an expensive CALL. function unpause() public onlyManager whenPaused { // Actually unpause the contract. super.unpause(); } /// @dev Override unpause so it requires all external contract addresses /// to be set before contract can be unpaused. Also, we can't have /// newContractAddress set either, because then the contract was upgraded. /// @notice This is public rather than external so we can call super.unpause /// without using an expensive CALL. function hasError() public onlyManager whenPaused { // Actually error out the contract. super.hasError(); } /// @dev Function does the init step and thus allow /// to create a Dummy 0th colelctible function preSaleInit() onlyManager { require(!CSCPreSaleInit); require(allPreSaleItems.length == 0); CSCPreSaleInit = true; //Fill in index 0 to null requests CSCPreSaleItem memory _Obj = CSCPreSaleItem(0, stringToBytes32("DummyAsset"), 0, 0, address(this), true); allPreSaleItems.push(_Obj); } /// @dev Remove all Ether from the contract, which is the owner's cuts /// as well as any Ether sent directly to the contract address. /// Always transfers to the NFT (ERC721) contract, but can be called either by /// the owner or the NFT (ERC721) contract. function withdrawBalance() onlyBanker { // We are using this boolean method to make sure that even if one fails it will still work bankManager.transfer(this.balance); } // @dev a function to claim refund if and only if theres an error in the contract function claimRefund(address _ownerAddress) whenError { uint256 refundValue = addressToValue[_ownerAddress]; require (refundValue > 0); addressToValue[_ownerAddress] = 0; _ownerAddress.transfer(refundValue); RefundClaimed(_ownerAddress, refundValue); } /// @dev Function used to set the flag isRedeemed to true /// can be called by addresses in the approvedAddressList function isRedeemed(uint256 _tokenId) { require(approvedAddressList[msg.sender]); require(_tokenId > STARTING_ASSET_BASE); uint256 generatedCollectibleId = _tokenId - STARTING_ASSET_BASE; CSCPreSaleItem memory _Obj = allPreSaleItems[generatedCollectibleId]; _Obj.isRedeemed = true; allPreSaleItems[generatedCollectibleId] = _Obj; } }