Transaction Hash:
Block:
6558969 at Oct-21-2018 10:40:54 PM +UTC
Transaction Fee:
0.00024736272 ETH
$0.54
Gas Used:
204,432 Gas / 1.21 Gwei
Account State Difference:
| Address | Before | After | State Difference | ||
|---|---|---|---|---|---|
| 0x4F2d119b...88758BDEF | |||||
| 0x59De2a5C...0FC5fF7b5 | |||||
|
0x5A0b54D5...D3E029c4c
Miner
| (Spark Pool) | 6,166.112485636569853697 Eth | 6,166.112732999289853697 Eth | 0.00024736272 | |
| 0xed1b3F41...e1b7Eefbf |
0.004964860008888888 Eth
Nonce: 169
|
0.004717497288888888 Eth
Nonce: 170
| 0.00024736272 |
Execution Trace
MEAManager.launchShipOnMEA( _assetId=202, starId=42 ) => ( 1540228186 )
-
CSCPreSaleManager.getCollectibleDetails( _assetId=202 ) => ( assetId=202, sequenceId=33, collectibleType=1, collectibleClass=2, isRedeemed=False, owner=0xed1b3F41d412d41411c8eb311de0083e1b7Eefbf ) -
0x4f2d119b1063f75bd2088b80ce288a588758bdef.8ede1817( ) -
0x4f2d119b1063f75bd2088b80ce288a588758bdef.7f9c8974( ) -
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 <dete@axiomzen.co> (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 <arachnid@notdot.net>
* Ref: https://github.com/Arachnid/solidity-stringutils/blob/2f6ca9accb48ae14c66f1437ec50ed19a0616f78/strings.sol
* @title String & slice utility library for Solidity contracts.
* @author Nick Johnson <arachnid@notdot.net>
*/
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 <dete@axiomzen.co> (https://github.com/dete)
contract ERC721 {
// Required methods
function balanceOf(address _owner) public view returns (uint256 balance);
function ownerOf(uint256 _assetId) public view returns (address owner);
function approve(address _to, uint256 _assetId) public;
function transfer(address _to, uint256 _assetId) public;
function transferFrom(address _from, address _to, uint256 _assetId) public;
function implementsERC721() public pure returns (bool);
function takeOwnership(uint256 _assetId) 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 game play state and access rights for game 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 Game Managers (Primary/Secondary): Has universal control of all game 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 gameManagerPrimary;
address public gameManagerSecondary;
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 onlyGameManager() {
require(msg.sender == gameManagerPrimary || msg.sender == gameManagerSecondary);
_;
}
modifier onlyBanker() {
require(msg.sender == bankManager);
_;
}
modifier anyOperator() {
require(
msg.sender == gameManagerPrimary ||
msg.sender == gameManagerSecondary ||
msg.sender == bankManager
);
_;
}
/// @dev Assigns a new address to act as the GM.
function setPrimaryGameManager(address _newGM) external onlyGameManager {
require(_newGM != address(0));
gameManagerPrimary = _newGM;
}
/// @dev Assigns a new address to act as the GM.
function setSecondaryGameManager(address _newGM) external onlyGameManager {
require(_newGM != address(0));
gameManagerSecondary = _newGM;
}
/// @dev Assigns a new address to act as the Banker.
function setBanker(address _newBK) external onlyGameManager {
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 onlyGameManager 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 onlyGameManager 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 onlyGameManager 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 onlyGameManager whenPaused {
error = false;
}
}
contract CSCCollectibleBase 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, bool isRedeemed);
event Transfer(address from, address to, uint256 shipId);
/*** CONSTANTS ***/
/// @notice Name and symbol of the non fungible token, as defined in ERC721.
string public constant NAME = "CSCPreSaleShip";
string public constant SYMBOL = "CSC";
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 ship
struct CSCPreSaleItem {
/// @dev asset ID i..e Local Index
uint256 assetId;
/// @dev name of the collectible stored in bytes
bytes32 collectibleName;
/// @dev Timestamp when bought
uint256 boughtTimestamp;
/// @dev Collectible Types (Voucher/Ship)
/// can be 0 - Voucher, 1 - Ship
uint256 collectibleType;
/// @dev Collectible Class (1 - Prometheus, 2 - Crosair, 3 - Intrepid)
uint256 collectibleClass;
// @dev owner address
address owner;
// @dev redeeme flag (to help whether it got redeemed or not)
bool isRedeemed;
}
// @dev Mapping containing the reference to all CSC PreSaleItem
//mapping (uint256 => CSCPreSaleItem[]) public indexToPreSaleItem;
// @dev array of CSCPreSaleItem type holding information on the Ships
CSCPreSaleItem[] allPreSaleItems;
// Max Count for Voucher(s), Prometheus, Crosair & Intrepid Ships
uint256 public constant PROMETHEUS_SHIP_LIMIT = 300;
uint256 public constant INTREPID_SHIP_LIMIT = 1500;
uint256 public constant CROSAIR_SHIP_LIMIT = 600;
uint256 public constant PROMETHEUS_VOUCHER_LIMIT = 100;
uint256 public constant INTREPID_VOUCHER_LIMIT = 300;
uint256 public constant CROSAIR_VOUCHER_LIMIT = 200;
// Variable to keep a count of Prometheus/Intrepid/Crosair Minted
uint256 public prometheusShipMinted;
uint256 public intrepidShipMinted;
uint256 public crosairShipMinted;
uint256 public prometheusVouchersMinted;
uint256 public intrepidVouchersMinted;
uint256 public crosairVouchersMinted;
// @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 Ship 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
/// 0 - Voucher
/// 1 - Prometheus
/// 2 - Crosair
/// 3 - Intrepid
mapping (uint256 => mapping (uint256 => mapping ( uint256 => uint256 ) ) ) public preSaleItemTypeToSequenceIdToCollectible;
/// @dev A mapping from Pre Sale Item Type IDs to the Sequqence Number .
/// 0 - Voucher
/// 1 - Prometheus
/// 2 - Crosair
/// 3 - Intrepid
mapping (uint256 => mapping ( uint256 => uint256 ) ) public preSaleItemTypeToCollectibleCount;
/// @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 getCollectibleDetails(uint256 _assetId) external view returns(uint256 assetId, uint256 sequenceId, uint256 collectibleType, uint256 collectibleClass, bool isRedeemed, address owner) {
CSCPreSaleItem memory _Obj = allPreSaleItems[_assetId];
assetId = _assetId;
sequenceId = _Obj.assetId;
collectibleType = _Obj.collectibleType;
collectibleClass = _Obj.collectibleClass;
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 _assetId The ID of the Token that can be transferred if this call succeeds.
/// @dev Required for ERC-721 compliance.
function approve(address _to, uint256 _assetId) public {
// Caller must own token.
require(_owns(msg.sender, _assetId));
preSaleItemIndexToApproved[_assetId] = _to;
Approval(msg.sender, _to, _assetId);
}
/// 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 _assetId The tokenID for owner inquiry
/// @dev Required for ERC-721 compliance.
function ownerOf(uint256 _assetId) public view returns (address owner) {
owner = preSaleItemIndexToOwner[_assetId];
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 _assetId The ID of the Token that can be transferred if this call succeeds.
/// @dev Required for ERC-721 compliance.
function takeOwnership(uint256 _assetId) public {
address newOwner = msg.sender;
address oldOwner = preSaleItemIndexToOwner[_assetId];
// Safety check to prevent against an unexpected 0x0 default.
require(_addressNotNull(newOwner));
// Making sure transfer is approved
require(_approved(newOwner, _assetId));
_transfer(oldOwner, newOwner, _assetId);
}
/// @param _owner The owner whose ships 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 CSCShips array looking for emojis 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 totalShips = totalSupply() + 1;
uint256 resultIndex = 0;
// We count on the fact that all CSC Ship Collectible have IDs starting at 0 and increasing
// sequentially up to the total count.
uint256 _assetId;
for (_assetId = 0; _assetId < totalShips; _assetId++) {
if (preSaleItemIndexToOwner[_assetId] == _owner) {
result[resultIndex] = _assetId;
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 _assetId The ID of the Token that can be transferred if this call succeeds.
/// @dev Required for ERC-721 compliance.
function transfer(address _to, uint256 _assetId) public {
require(_addressNotNull(_to));
require(_owns(msg.sender, _assetId));
_transfer(msg.sender, _to, _assetId);
}
/// 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 _assetId 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 _assetId) public {
require(_owns(_from, _assetId));
require(_approved(_to, _assetId));
require(_addressNotNull(_to));
_transfer(_from, _to, _assetId);
}
/*** 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 _assetId) internal view returns (bool) {
return preSaleItemIndexToApproved[_assetId] == _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,
0,
_collectibleType,
_collectibleClass,
address(0),
false
);
uint256 newCollectibleId = allPreSaleItems.push(_collectibleObj) - 1;
preSaleItemTypeToSequenceIdToCollectible[_collectibleType][_collectibleClass][_sequenceId] = newCollectibleId;
preSaleItemTypeToCollectibleCount[_collectibleType][_collectibleClass] = _sequenceId;
// emit Created event
// CollectibleCreated(address owner, uint256 globalId, uint256 collectibleType, uint256 collectibleClass, uint256 sequenceId, bytes32[6] attributes, bool isRedeemed);
CollectibleCreated(address(this), newCollectibleId, _collectibleType, _collectibleClass, _sequenceId, _collectibleObj.collectibleName, false);
// This will assign ownership, and also emit the Transfer event as
// per ERC721 draft
_transfer(address(0), address(this), newCollectibleId);
return newCollectibleId;
}
/// Check for token ownership
function _owns(address claimant, uint256 _assetId) internal view returns (bool) {
return claimant == preSaleItemIndexToOwner[_assetId];
}
/// @dev Assigns ownership of a specific Emoji to an address.
function _transfer(address _from, address _to, uint256 _assetId) internal {
// Updating the owner details of the ship
CSCPreSaleItem memory _shipObj = allPreSaleItems[_assetId];
_shipObj.owner = _to;
allPreSaleItems[_assetId] = _shipObj;
// Since the number of emojis is capped to 2^32 we can't overflow this
ownershipTokenCount[_to]++;
//transfer ownership
preSaleItemIndexToOwner[_assetId] = _to;
// When creating new emojis _from is 0x0, but we can't account that address.
if (_from != address(0)) {
ownershipTokenCount[_from]--;
// clear any previously approved ownership exchange
delete preSaleItemIndexToApproved[_assetId];
}
// Emit the transfer event.
Transfer(_from, _to, _assetId);
}
/// @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 _assetId) internal view returns (bool) {
return preSaleItemIndexToApproved[_assetId] == _claimant;
}
function _getCollectibleDetails (uint256 _assetId) internal view returns(CSCPreSaleItem) {
CSCPreSaleItem storage _Obj = allPreSaleItems[_assetId];
return _Obj;
}
/// @dev Helps in fetching the attributes of the ship depending on the ship
/// assetId : The actual ERC721 Asset ID
/// sequenceId : Index w.r.t Ship type
function getShipDetails(uint256 _sequenceId, uint256 _shipClass) external view returns (
uint256 assetId,
uint256 sequenceId,
string shipName,
uint256 collectibleClass,
uint256 boughtTimestamp,
address owner
) {
uint256 _assetId = preSaleItemTypeToSequenceIdToCollectible[1][_shipClass][_sequenceId];
CSCPreSaleItem storage _collectibleObj = allPreSaleItems[_assetId];
require(_collectibleObj.collectibleType == 1);
assetId = _assetId;
sequenceId = _sequenceId;
shipName = bytes32ToString(_collectibleObj.collectibleName);
collectibleClass = _collectibleObj.collectibleClass;
boughtTimestamp = _collectibleObj.boughtTimestamp;
owner = _collectibleObj.owner;
}
/// @dev Helps in fetching information regarding a Voucher
/// assetId : The actual ERC721 Asset ID
/// sequenceId : Index w.r.t Voucher Type
function getVoucherDetails(uint256 _sequenceId, uint256 _voucherClass) external view returns (
uint256 assetId,
uint256 sequenceId,
uint256 boughtTimestamp,
uint256 voucherClass,
address owner
) {
uint256 _assetId = preSaleItemTypeToSequenceIdToCollectible[0][_voucherClass][_sequenceId];
CSCPreSaleItem storage _collectibleObj = allPreSaleItems[_assetId];
require(_collectibleObj.collectibleType == 0);
assetId = _assetId;
sequenceId = _sequenceId;
boughtTimestamp = _collectibleObj.boughtTimestamp;
voucherClass = _collectibleObj.collectibleClass;
owner = _collectibleObj.owner;
}
function _isActive(uint256 _assetId) internal returns(bool) {
CSCPreSaleItem memory _Obj = allPreSaleItems[_assetId];
return (_Obj.boughtTimestamp == 0);
}
}
/* Lucid Sight, Inc. ERC-721 CSC Collectilbe Sale Contract.
* @title CSCCollectibleSale
* @author Fazri Zubair & Farhan Khwaja (Lucid Sight, Inc.)
*/
contract CSCCollectibleSale is CSCCollectibleBase {
event CollectibleBought (uint256 _assetId, address owner);
event PriceUpdated (uint256 collectibleClass, uint256 newPrice, uint256 oldPrice);
// SHIP DATATYPES & CONSTANTS
// @dev ship Prices & price cap
uint256 public PROMETHEUS_SHIP_PRICE = 0.25 ether;
uint256 public INTREPID_SHIP_PRICE = 0.005 ether;
uint256 public CROSAIR_SHIP_PRICE = 0.1 ether;
uint256 public constant PROMETHEUS_MAX_PRICE = 0.85 ether;
uint256 public constant INTREPID_MAX_PRICE = 0.25 ether;
uint256 public constant CROSAIR_MAX_PRICE = 0.5 ether;
uint256 public constant PROMETHEUS_PRICE_INCREMENT = 0.05 ether;
uint256 public constant INTREPID_PRICE_INCREMENT = 0.002 ether;
uint256 public constant CROSAIR_PRICE_INCREMENT = 0.01 ether;
uint256 public constant PROMETHEUS_PRICE_THRESHOLD = 0.85 ether;
uint256 public constant INTREPID_PRICE_THRESHOLD = 0.25 ether;
uint256 public constant CROSAIR_PRICE_THRESHOLD = 0.5 ether;
uint256 public prometheusSoldCount;
uint256 public intrepidSoldCount;
uint256 public crosairSoldCount;
// VOUCHER DATATYPES & CONSTANTS
uint256 public PROMETHEUS_VOUCHER_PRICE = 0.75 ether;
uint256 public INTREPID_VOUCHER_PRICE = 0.2 ether;
uint256 public CROSAIR_VOUCHER_PRICE = 0.35 ether;
uint256 public prometheusVoucherSoldCount;
uint256 public crosairVoucherSoldCount;
uint256 public intrepidVoucherSoldCount;
/// @dev Mapping created store the amount of value a wallet address used to buy assets
mapping(address => uint256) addressToValue;
/// @dev Mapping to holde the balance of each address, i.e. addrs -> collectibleType -> collectibleClass -> balance
mapping(address => mapping(uint256 => mapping (uint256 => uint256))) addressToCollectibleTypeBalance;
function _bid(uint256 _assetId, uint256 _price,uint256 _collectibleType,uint256 _collectibleClass, address _buyer) internal {
CSCPreSaleItem memory _Obj = allPreSaleItems[_assetId];
if(_collectibleType == 1 && _collectibleClass == 1) {
require(_price == PROMETHEUS_SHIP_PRICE);
_Obj.owner = _buyer;
_Obj.boughtTimestamp = now;
addressToValue[_buyer] += _price;
prometheusSoldCount++;
if(prometheusSoldCount % 10 == 0){
if(PROMETHEUS_SHIP_PRICE < PROMETHEUS_PRICE_THRESHOLD){
PROMETHEUS_SHIP_PRICE += PROMETHEUS_PRICE_INCREMENT;
}
}
}
if(_collectibleType == 1 && _collectibleClass == 2) {
require(_price == CROSAIR_SHIP_PRICE);
_Obj.owner = _buyer;
_Obj.boughtTimestamp = now;
addressToValue[_buyer] += _price;
crosairSoldCount++;
if(crosairSoldCount % 10 == 0){
if(CROSAIR_SHIP_PRICE < CROSAIR_PRICE_THRESHOLD){
CROSAIR_SHIP_PRICE += CROSAIR_PRICE_INCREMENT;
}
}
}
if(_collectibleType == 1 && _collectibleClass == 3) {
require(_price == INTREPID_SHIP_PRICE);
_Obj.owner = _buyer;
_Obj.boughtTimestamp = now;
addressToValue[_buyer] += _price;
intrepidSoldCount++;
if(intrepidSoldCount % 10 == 0){
if(INTREPID_SHIP_PRICE < INTREPID_PRICE_THRESHOLD){
INTREPID_SHIP_PRICE += INTREPID_PRICE_INCREMENT;
}
}
}
if(_collectibleType == 0 &&_collectibleClass == 1) {
require(_price == PROMETHEUS_VOUCHER_PRICE);
_Obj.owner = _buyer;
_Obj.boughtTimestamp = now;
addressToValue[_buyer] += _price;
prometheusVoucherSoldCount++;
}
if(_collectibleType == 0 && _collectibleClass == 2) {
require(_price == CROSAIR_VOUCHER_PRICE);
_Obj.owner = _buyer;
_Obj.boughtTimestamp = now;
addressToValue[_buyer] += _price;
crosairVoucherSoldCount++;
}
if(_collectibleType == 0 && _collectibleClass == 3) {
require(_price == INTREPID_VOUCHER_PRICE);
_Obj.owner = _buyer;
_Obj.boughtTimestamp = now;
addressToValue[_buyer] += _price;
intrepidVoucherSoldCount++;
}
addressToCollectibleTypeBalance[_buyer][_collectibleType][_collectibleClass]++;
CollectibleBought(_assetId, _buyer);
}
function getCollectibleTypeBalance(address _owner, uint256 _collectibleType, uint256 _collectibleClass) external view returns(uint256) {
require(_owner != address(0));
return addressToCollectibleTypeBalance[_owner][_collectibleType][_collectibleClass];
}
function getCollectiblePrice(uint256 _collectibleType, uint256 _collectibleClass) external view returns(uint256 _price){
// For Ships
if(_collectibleType == 1 && _collectibleClass == 1) {
return PROMETHEUS_SHIP_PRICE;
}
if(_collectibleType == 1 && _collectibleClass == 2) {
return CROSAIR_SHIP_PRICE;
}
if(_collectibleType == 1 && _collectibleClass == 3) {
return INTREPID_SHIP_PRICE;
}
// For Vouchers
if(_collectibleType == 0 && _collectibleClass == 1) {
return PROMETHEUS_VOUCHER_PRICE;
}
if(_collectibleType == 0 && _collectibleClass == 2) {
return CROSAIR_VOUCHER_PRICE;
}
if(_collectibleType == 0 && _collectibleClass == 3) {
return INTREPID_VOUCHER_PRICE;
}
}
}
/* Lucid Sight, Inc. ERC-721 Collectibles.
* @title LSNFT - Lucid Sight, Inc. Non-Fungible Token
* @author Fazri Zubair & Farhan Khwaja (Lucid Sight, Inc.)
*/
contract CSCPreSaleManager is CSCCollectibleSale {
event RefundClaimed(address owner, uint256 refundValue);
// Ship Names
string private constant prometheusShipName = "Vulcan Harvester";
string private constant crosairShipName = "Phoenix Cruiser";
string private constant intrepidShipName = "Reaper Interceptor";
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;
gameManagerPrimary = msg.sender;
}
function addToApprovedAddress (address _newAddr) onlyGameManager {
require(_newAddr != address(0));
require(!approvedAddressList[_newAddr]);
approvedAddressList[_newAddr] = true;
}
function removeFromApprovedAddress (address _newAddr) onlyGameManager {
require(_newAddr != address(0));
require(approvedAddressList[_newAddr]);
approvedAddressList[_newAddr] = false;
}
function() external payable {
}
/// @dev Bid Function which call the interncal bid function
/// after doing all the pre-checks required to initiate a bid
function bid(uint256 _collectibleType, uint256 _collectibleClass) external payable {
require(msg.sender != address(0));
require(msg.sender != address(this));
require(_collectibleType >= 0 && _collectibleType <= 1);
require(_isActive(_assetId));
bytes32 collectibleName;
if(_collectibleType == 0){
collectibleName = bytes32("NoNameForVoucher");
if(_collectibleClass == 1){
require(prometheusVouchersMinted < PROMETHEUS_VOUCHER_LIMIT);
collectibleName = stringToBytes32(prometheusShipName);
prometheusVouchersMinted++;
}
if(_collectibleClass == 2){
require(crosairVouchersMinted < CROSAIR_VOUCHER_LIMIT);
crosairVouchersMinted++;
}
if(_collectibleClass == 3){
require(intrepidVoucherSoldCount < INTREPID_VOUCHER_LIMIT);
intrepidVouchersMinted++;
}
}
if(_collectibleType == 1){
if(_collectibleClass == 1){
require(prometheusShipMinted < PROMETHEUS_SHIP_LIMIT);
collectibleName = stringToBytes32(prometheusShipName);
prometheusShipMinted++;
}
if(_collectibleClass == 2){
require(crosairShipMinted < CROSAIR_VOUCHER_LIMIT);
collectibleName = stringToBytes32(crosairShipName);
crosairShipMinted++;
}
if(_collectibleClass == 3){
require(intrepidShipMinted < INTREPID_SHIP_LIMIT);
collectibleName = stringToBytes32(intrepidShipName);
intrepidShipMinted++;
}
}
uint256 _assetId = _createCollectible(collectibleName, _collectibleType, _collectibleClass);
CSCPreSaleItem memory _Obj = allPreSaleItems[_assetId];
_bid(_assetId, msg.value, _Obj.collectibleType, _Obj.collectibleClass, msg.sender);
_transfer(address(this), msg.sender, _assetId);
}
/// @dev Bid Function which call the interncal bid function
/// after doing all the pre-checks required to initiate a bid
function createReferralGiveAways(uint256 _collectibleType, uint256 _collectibleClass, address _toAddress) onlyGameManager external {
require(msg.sender != address(0));
require(msg.sender != address(this));
require(_collectibleType >= 0 && _collectibleType <= 1);
bytes32 collectibleName;
if(_collectibleType == 0){
collectibleName = bytes32("ReferralGiveAwayVoucher");
if(_collectibleClass == 1){
collectibleName = stringToBytes32(prometheusShipName);
}
if(_collectibleClass == 2){
crosairVouchersMinted++;
}
if(_collectibleClass == 3){
intrepidVouchersMinted++;
}
}
if(_collectibleType == 1){
if(_collectibleClass == 1){
collectibleName = stringToBytes32(prometheusShipName);
}
if(_collectibleClass == 2){
collectibleName = stringToBytes32(crosairShipName);
}
if(_collectibleClass == 3){
collectibleName = stringToBytes32(intrepidShipName);
}
}
uint256 _assetId = _createCollectible(collectibleName, _collectibleType, _collectibleClass);
CSCPreSaleItem memory _Obj = allPreSaleItems[_assetId];
_transfer(address(this), _toAddress, _assetId);
}
/// @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 onlyGameManager whenPaused {
// Actually unpause the contract.
super.unpause();
}
/// @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);
}
function claimRefund(address _ownerAddress) whenError {
uint256 refundValue = addressToValue[_ownerAddress];
addressToValue[_ownerAddress] = 0;
_ownerAddress.transfer(refundValue);
RefundClaimed(_ownerAddress, refundValue);
}
function preSaleInit() onlyGameManager {
require(!CSCPreSaleInit);
require(allPreSaleItems.length == 0);
CSCPreSaleInit = true;
//Fill in index 0 to null requests
CSCPreSaleItem memory _Obj = CSCPreSaleItem(0, stringToBytes32("DummyAsset"), 0, 0, 0, address(this), true);
allPreSaleItems.push(_Obj);
}
function isRedeemed(uint256 _assetId) {
require(approvedAddressList[msg.sender]);
CSCPreSaleItem memory _Obj = allPreSaleItems[_assetId];
_Obj.isRedeemed = true;
allPreSaleItems[_assetId] = _Obj;
}
}